아메숑 2019. 4. 1. 09:09
#include <stdio.h>
#include <math.h>
#define GetBit(W,n) (((W)>>(10-n)) &0x01)
#define GetBit8(W,n) (((W)>>(8-n)) &0x01)
#define GetBit4(W,n) (((W)>>(4-n)) &0x01)
#define ReturnBit(W,n,k) (((GetBit(W,n)))<<(10-k))
#define ReturnBit8(W,n,k) (((GetBit(W,n)))<<(8-k))
#define ReturnBit8_8(W,n,k) (((GetBit8(W,n)))<<(8-k))
#define ReturnBit4_8(W,n,k) (((GetBit4(W,n)))<<(8-k))
#define ReturnBit4_4(W,n,k) (((GetBit4(W,n)))<<(4-k))

#define permutation(val)\
( ReturnBit(val,3,1) | ReturnBit(val,5,2) | ReturnBit(val,2,3) | \
ReturnBit(val,7,4) | ReturnBit(val,4,5) | ReturnBit(val,10,6) | \
ReturnBit(val,1,7) | ReturnBit(val,9,8) | ReturnBit(val,8,9) | \
ReturnBit(val,6,10))

#define permutation8(val)\
( ReturnBit8(val,6,1) | ReturnBit8(val,3,2) | ReturnBit8(val,7,3) | \
ReturnBit8(val,4,4) | ReturnBit8(val,8,5) | ReturnBit8(val,5,6) | \
ReturnBit8(val,10,7) | ReturnBit8(val,9,8))

#define IP(val)\
( ReturnBit8_8(val,2,1) | ReturnBit8_8(val,6,2) | ReturnBit8_8(val,3,3) | \
ReturnBit8_8(val,1,4) | ReturnBit8_8(val,4,5) | ReturnBit8_8(val,8,6) | \
ReturnBit8_8(val,5,7) | ReturnBit8_8(val,7,8))

#define rIP(val)\
( ReturnBit8_8(val,4,1) | ReturnBit8_8(val,1,2) | ReturnBit8_8(val,3,3) | \
ReturnBit8_8(val,5,4) | ReturnBit8_8(val,7,5) | ReturnBit8_8(val,2,6) | \
ReturnBit8_8(val,8,7) | ReturnBit8_8(val,6,8))

#define EP(val)\
( ReturnBit4_8(val,4,1) | ReturnBit4_8(val,1,2) | ReturnBit4_8(val,2,3) | \
ReturnBit4_8(val,3,4) | ReturnBit4_8(val,2,5) | ReturnBit4_8(val,3,6) | \
ReturnBit4_8(val,4,7) | ReturnBit4_8(val,1,8))

#define permutation4(val)\
( ReturnBit4_4(val,2,1) | ReturnBit4_4(val,4,2) | ReturnBit4_4(val,3,3) | \
ReturnBit4_4(val,1,4))

#define _setval(u8,val) u8.left = (val>>4); \
u8.right = val;
#define _print(pu8)printf(#pu8" : 0x%x%x\n",pu8.left,pu8.right);

#define ROR(N,W,i) (((W)>>(i)) | ((W)<<(N-(i))))
#define ROL(N,W,i) (((W)<<(i)) | ((W)>>(N-(i))))


int chartodecimal(char bin[])
{
    int i;
    int bin2[10];
    for(i=0;i<10;i++)
        bin2[i] = bin[i]-'0';
    int sum=0;
    int j = strlen(bin) - 1;
    for(i=0;i<strlen(bin);i++)
    {
        sum += bin2[i] * pow(2,j);
        j--;
    }
    return sum;
}

typedef struct bit10{
    unsigned p10:10;
    unsigned p8:8;
    unsigned left:5;
    unsigned right:5;
}p10;

typedef struct plain{
    unsigned p8:8;
    unsigned p4:4;
    unsigned left:4;
    unsigned right:4;
    unsigned templeft:4;
    unsigned tempright:4;
}p8;


char *uintToBinary(p10 i) {
    static char s[11];
    int count = 10;
    do { s[--count] = '0' + (char) (i.p10 & 1);
        i.p10 = i.p10 >> 1;
    } while (count);
    return s;
}

char *uintToBinary8(p10 i) {
    static char s[9];
    int count = 8;
    do { s[--count] = '0' + (char) (i.p8 & 1);
        i.p8 = i.p8 >> 1;
    } while (count);
    return s;
}

char *uintToBinaryplain8(p8 i) {
    static char s[9];
    int count = 8;
    do { s[--count] = '0' + (char) (i.p8 & 1);
        i.p8 = i.p8 >> 1;
    } while (count);
    return s;
}

char *uintToBinaryplain4(p8 i) {
    static char s[5];
    int count = 4;
    do { s[--count] = '0' + (char) (i.p4 & 1);
        i.p4 = i.p4 >> 1;
    } while (count);
    return s;
}

char *uintToBinary2(p10 i) {
    static char s[5] = { '0', };
    int count = 5;
    do { s[--count] = '0' + (char) (i.left & 1);
        i.left = i.left >> 1;
    } while (count);
    return s;
}

char *uintToBinary3(p10 i) {
    static char s[5] = { '0', };
    int count = 5;
    do { s[--count] = '0' + (char) (i.right & 1);
        i.right = i.right >> 1;
    } while (count);
    return s;
}

char *uintToBinarykey(int a) {
    static char s[8] = { '0', };
    int count = 8;
    do { s[--count] = '0' + (char) (a & 1);
        a = a >> 1;
    } while (count);
    return s;   //나중에 지워
}

int *s0s1(p8 i)
{
    int s0[4][4] ={{1,0,3,2},
                    {3,2,1,0},
                    {0,2,1,3},
                    {3,1,3,2}};
    int s1[4][4] ={{1,0,2,3},
                    {2,0,1,3},
                    {3,0,1,0},
                    {2,1,0,3}};
    int x,y,z,w;
    x = GetBit4(i.left,1);
    y = GetBit4(i.left,2);
    z = GetBit4(i.left,3);
    w = GetBit4(i.left,4);

    int x1,y1,z1,w1;
    x1 = GetBit4(i.right,1);
    y1 = GetBit4(i.right,2);
    z1 = GetBit4(i.right,3);
    w1 = GetBit4(i.right,4);

    printf("%d %d %d %d %d %d %d %d \n",x,y,z,w,x1,y1,z1,w1);

    int l2,r2;
    l2 = s0[x*2+w][y*2+z];
    r2 = s1[x1*2+w1][y1*2+z1];
    printf("s0 s1 :%d %d\n",l2,r2);

    i.p4 = l2*4 + r2;
    printf("4bit : %d\n",i.p4);
    return i.p4;
}


int main(void){
    p10 initKey;
    char key[10];

    //scanf("%s",key); //0x282
    //initKey.p10=chartodecimal(key);
    initKey.p10= 0b1100001110;

    printf("p10 : %s \n",uintToBinary(initKey));
    p10 permutate;
    permutate.p10 = permutation(initKey.p10);
    printf("p10 : %s \n",uintToBinary(permutate));

    permutate.right = permutate.p10 ;
    permutate.left = ROR(10,permutate.p10,5);

    printf("왼쪽 5비트 p10 : %s \n",uintToBinary2(permutate));
    printf("오른쪽 5비트 p10 : %s \n",uintToBinary3(permutate));

    permutate.left = ROL(5,permutate.left,1);
    permutate.right = ROL(5,permutate.right,1);

    printf("왼쪽 5비트 p10 shift: %s \n",uintToBinary2(permutate));
    printf("오른쪽 5비트 p10 shift : %s \n",uintToBinary3(permutate));

    permutate.p10 = ROL(10,permutate.left,5)|permutate.right;

    printf("p10 : %s \n",uintToBinary(permutate));

    permutate.p8 = permutation8(permutate.p10);
    printf("k1 : %s \n",uintToBinary8(permutate));

    int key1 = permutate.p8;
    //printf("k1 : %s \n",uintToBinarykey(key1));

    permutate.left = ROL(5,permutate.left,2);
    permutate.right = ROL(5,permutate.right,2);
    permutate.p10 = ROL(10,permutate.left,5)|permutate.right;
    permutate.p8 = permutation8(permutate.p10);
    printf("k2 : %s \n",uintToBinary8(permutate));
    int key2 = permutate.p8;

    p8 plain;
    char plaintext[10];
    //printf("plaintext :");
    //scanf("%s",plaintext); //0x282
    //plain.p10=chartodecimal(plaintext);

    plain.p8= 0b10101010;

    plain.p8 = IP(plain.p8);
    printf("after IP plain : %s \n",uintToBinaryplain8(plain));
    plain.templeft = ROR(8,plain.p8,4);
    int plainright = plain.p8;
    plain.right = plain.p8;
    plain.p8 = EP(plain.right);
    printf("after E/P plain : %s \n",uintToBinaryplain8(plain));
    plain.p8 ^= key1;
    printf("after exclusive OR with k1 plain : %s \n",uintToBinaryplain8(plain));
    plain.left = ROR(8,plain.p8,4);
    plain.right = plain.p8;
    plain.p4 = s0s1(plain);
    printf("after s0s1 plain : %s \n",uintToBinaryplain4(plain));
    plain.p4 = permutation4(plain.p4);
    printf("after p4 plain : %s \n",uintToBinaryplain4(plain));
    plain.p4 ^= plain.templeft;
    printf("after exclusive plain : %s \n",uintToBinaryplain4(plain));
    plain.templeft = plainright;
    plain.p8 = ROL(8,plain.templeft,4)+ plain.p4;
    printf("after SW plain : %s \n",uintToBinaryplain8(plain));
    plain.templeft = ROR(8,plain.p8,4);
    plainright = plain.p4;
    plain.p8 = EP(plain.p4);
    plain.p8 ^= key2;
    plain.left = ROR(8,plain.p8,4);
    plain.right = plain.p8;
    plain.p4 = s0s1(plain);
    plain.p4 = permutation4(plain.p4);
    plain.p4 ^= plain.templeft;
    plain.templeft = plainright;
    plain.p8 = ROL(8,plain.p4,4) | plain.templeft;
    plain.p8 = rIP(plain.p8);
    printf("ciphertext : %s \n",uintToBinaryplain8(plain));

    //여기까지 암호화 이제부터 복호화 --------------------------------------------

    plain.p8 = IP(plain.p8);
    plain.tempright = plain.p8;
    plain.templeft = plain.p8 / 16;
    plain.p8 = EP(plain.tempright) ^ key2;
    plain.right = plain.p8;
    plain.left = plain.p8 / 16;
    plain.p4 = s0s1(plain);
    plain.p4 = permutation4(plain.p4);
    plain.left = plain.templeft ^ plain.p4;
    plain.p8 = ROL(8,plain.tempright,4)+ plain.left;

    plain.tempright = plain.p8;
    plain.templeft = plain.p8 / 16;
    plain.p8 = EP(plain.tempright) ^ key1;
    plain.right = plain.p8;
    plain.left = plain.p8 / 16;
    plain.p4 = s0s1(plain);
    plain.p4 = permutation4(plain.p4);
    plain.left = plain.templeft ^ plain.p4;
    plain.p8 = plain.left * 16 + plain.tempright;
    plain.p8 = rIP(plain.p8);
    printf("plaintext : %s \n",uintToBinaryplain8(plain));


    return 0;

}