/*
D E S
*/
#include <stdio.h>
typedef unsigned long DWORD;
typedef unsigned short WORD;
typedef unsigned char BYTE;
typedef union {
DWORD dw[2];
WORD w[4];
BYTE b[8];
} BIT64;
BYTE mask[8] = {0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x1};
void IP(BIT64 *text) /* IP테이블 연산 */
{
BYTE ip_table[64] = { 58, 50, 42, 34, 26, 18, 10, 2,
60, 52, 44, 36, 28, 20, 12, 4,
62, 54, 46, 38, 30, 22, 14, 6,
64, 56, 48, 40, 32, 24, 16, 8,
57, 49, 41, 33, 25, 17, 9, 1,
59, 51, 43, 35, 27, 19, 11, 3,
61, 53, 45, 37, 29, 21, 13, 5,
63, 55, 47, 39, 31, 23, 15, 7 };
BYTE i;
BIT64 t;
t.dw[0] = t.dw[1] = 0;
for(i=0;i<64;i++)
{
BYTE temp = ip_table[i] -1;
if((text->b[temp/8] & mask[temp%8]) != 0)
t.b[i/8] |= mask[i%8];
}
text->dw[0] = t.dw[0];
text->dw[1] = t.dw[1];
}
void FP(BIT64 *text) /* IP역치환 테이블 */
{
BYTE fp_table[64] = { 40, 8, 48, 16, 56, 24, 64, 32,
39, 7, 47, 15, 55, 23, 63, 31,
38, 6, 46, 14, 54, 22, 62, 30,
37, 5, 45, 13, 53, 21, 61, 29,
36, 4, 44, 12, 52, 20, 60, 28,
35, 3, 43, 11, 51, 19, 59, 27,
34, 2, 42, 10, 50, 18, 58, 26,
33, 1, 41, 9, 49, 17, 57, 25 };
BYTE i;
BIT64 t;
t.dw[0] = t.dw[1] = 0;
for(i=0;i<64;i++)
{
BYTE temp = fp_table[i] -1;
if(text->b[temp/8] & mask[temp%8])
t.b[i/8] |= mask[i%8];
}
text->dw[0] = t.dw[0];
text->dw[1] = t.dw[1];
}
void MakeKey(BIT64 key, BIT64 keys[16]) /* 키만들기 */
{
BYTE i,j,k;
BYTE shift[16] = {1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1}; /* leftshift 관련 */
BYTE init_table[56] = { 57, 49, 41, 33, 25, 17, 9, /* PC-1 테이블 */
1, 58, 50, 42, 34, 26, 18,
10, 2, 59, 51, 43, 35, 27,
19, 11, 3, 60, 52, 44, 36,
63, 55, 47, 39, 31, 23, 15,
7, 62, 54, 46, 38, 30, 22,
14, 6, 61, 53, 45, 37, 29,
21, 13, 5, 28, 20, 12, 4 };
BYTE replace_table[48] = { 14, 17, 11, 24, 1, 5, /* PC-2 테이블 */
3, 28, 15, 6, 21, 10,
23, 19, 12, 4, 26, 8,
16, 7, 27, 20, 13, 2,
41, 52, 31, 37, 47, 55,
30, 40, 51, 45, 33, 48,
44, 49, 39, 56, 34, 53,
46, 42, 50, 36, 29, 32 };
BIT64 bit;
bit.dw[0] = bit.dw[1] = 0;
for(i=0;i<28;i++)
{
BYTE temp = init_table[i] -1;
if(key.b[temp/8] & mask[temp % 8])
bit.b[i/8] &= mask[i%8];
temp = init_table[i+28] -1;
if(key.b[temp/8] & mask[temp % 8])
bit.b[i/8 + 4] &= mask[i%8];
}
for(i=0;i<16;i++)
{
for(j=0;j<shift[i];j++)
{
BYTE temp = (BYTE)(bit.b[0] & 0x80);
bit.b[0] <<= 1;
if(bit.b[1] & 0x80)
bit.b[0] += 1;
bit.b[1] <<= 1;
if(bit.b[2] & 0x80)
bit.b[1] += 1;
bit.b[2] <<= 1;
if(bit.b[3] & 0x80)
bit.b[2] += 1;
bit.b[3] <<= 1;
if(temp)
bit.b[3] += 0x10;
temp = (BYTE)(bit.b[4] & 0x80);
bit.b[4] <<= 1;
if(bit.b[5] & 0x80)
bit.b[4] += 1;
bit.b[5] <<= 1;
if(bit.b[6] & 0x80)
bit.b[5] += 1;
bit.b[6] <<= 1;
if(bit.b[7] & 0x80)
bit.b[6] += 1;
bit.b[7] <<= 1;
if(temp)
bit.b[7] += 0x10;
}
keys[i].dw[0] = 0;
keys[i].dw[1] = 0;
for(j=0;j<48;j++)
{
BYTE temp = replace_table[j] -1;
if(temp < 28)
{
if(bit.b[temp / 8] & mask[temp%8])
keys[i].b[j/6] |= mask[j%6];
} else {
temp = temp - 28;
if(bit.b[temp/8 + 4] & mask[temp % 8])
keys[i].b[j/6] |= mask[j%6];
}
}
}
}
void RoundFunction(BIT64 key, BIT64 *text)
{
BIT64 a;
BIT64 t;
BYTE i,j,k;
BYTE expand_table[48] = { 32, 1, 2, 3, 4, 5, /* E 테이블 */
4, 5, 6, 7, 8, 9,
8, 9, 10, 11, 12, 13,
12, 13, 14, 15, 16, 17,
16, 17, 18, 19, 20, 21,
20, 21, 22, 23, 24, 25,
24, 25, 26, 27, 28, 29,
28, 29, 30, 31, 32, 1 };
BYTE tp_table[32] = { 16, 7, 20, 21, /* P 테이블 */
29, 12, 28, 17,
1, 15, 23, 26,
5, 18, 31, 10,
2, 8, 24, 14,
32, 27, 3, 9,
19, 13, 30, 6,
22, 11, 4, 25 };
BYTE s_table[8][64] = {
{ /* SBOX */
14, 0, 4, 15, 13, 7, 1, 4, 2, 14, 15, 2, 11, 13, 8, 1,
3, 10, 10, 6, 6, 12, 12, 11, 5, 9, 9, 5, 0, 3, 7, 8,
4, 15, 1, 12, 14, 8, 8, 2, 13, 4, 6, 9, 2, 1, 11, 7,
15, 5, 12, 11, 9, 3, 7, 14, 3, 10, 10, 0, 5, 6, 0, 13
}, {
15, 3, 1, 13, 8, 4, 14, 7, 6, 15, 11, 2, 3, 8, 4, 14,
9, 12, 7, 0, 2, 1, 13, 10, 12, 6, 0, 9, 5, 11, 10, 5,
0, 13, 14, 8, 7, 10, 11, 1, 10, 3, 4, 15, 13, 4, 1, 2,
5, 11, 8, 6, 12, 7, 6, 12, 9, 0, 3, 5, 2, 14, 15, 9
}, {
10, 13, 0, 7, 9, 0, 14, 9, 6, 3, 3, 4, 15, 6, 5, 10,
1, 2, 13, 8, 12, 5, 7, 14, 11, 12, 4, 11, 2, 15, 8, 1,
13, 1, 6, 10, 4, 13, 9, 0, 8, 6, 15, 9, 3, 8, 0, 7,
11, 4, 1, 15, 2, 14, 12, 3, 5, 11, 10, 5, 14, 2, 7, 12
}, {
7, 13, 13, 8, 14, 11, 3, 5, 0, 6, 6, 15, 9, 0, 10, 3,
1, 4, 2, 7, 8, 2, 5, 12, 11, 1, 12, 10, 4, 14, 15, 9,
10, 3, 6, 15, 9, 0, 0, 6, 12, 10, 11, 1, 7, 13, 13, 8,
15, 9, 1, 4, 3, 5, 14, 11, 5, 12, 2, 7, 8, 2, 4, 14
}, {
2, 14, 12, 11, 4, 2, 1, 12, 7, 4, 10, 7, 11, 13, 6, 1,
8, 5, 5, 0, 3, 15, 15, 10, 13, 3, 0, 9, 14, 8, 9, 6,
4, 11, 2, 8, 1, 12, 11, 7, 10, 1, 13, 14, 7, 2, 8, 13,
15, 6, 9, 15, 12, 0, 5, 9, 6, 10, 3, 4, 0, 5, 14, 3
}, {
12, 10, 1, 15, 10, 4, 15, 2, 9, 7, 2, 12, 6, 9, 8, 5,
0, 6, 13, 1, 3, 13, 4, 14, 14, 0, 7, 11, 5, 3, 11, 8,
9, 4, 14, 3, 15, 2, 5, 12, 2, 9, 8, 5, 12, 15, 3, 10,
7, 11, 0, 14, 4, 1, 10, 7, 1, 6, 13, 0, 11, 8, 6, 13
}, {
4, 13, 11, 0, 2, 11, 14, 7, 15, 4, 0, 9, 8, 1, 13, 10,
3, 14, 12, 3, 9, 5, 7, 12, 5, 2, 10, 15, 6, 8, 1, 6,
1, 6, 4, 11, 11, 13, 13, 8, 12, 1, 3, 4, 7, 10, 14, 7,
10, 9, 15, 5, 6, 0, 8, 15, 0, 14, 5, 2, 9, 3, 2, 12,
}, {
13, 1, 2, 15, 8, 13, 4, 8, 6, 10, 15, 3, 11, 7, 1, 4,
10, 12, 9, 5, 3, 6, 14, 11, 5, 0, 0, 14, 12, 9, 7, 2,
7, 2, 11, 1, 4, 14, 1, 7, 9, 4, 12, 10, 14, 8, 2, 13,
0, 15, 6, 12, 10, 9, 13, 0, 15, 3, 3, 5, 5, 6, 8, 11,
}
};
t.dw[0] = t.dw[1] = 0;
for(i=0;i<48;i++)
{
j = expand_table[i] + 31;
if(text->b[j/8] & mask[j%8])
{
t.b[i/6] |= mask[i%6];
}
}
for(i=0;i<8;i++)
{
t.b[i] ^= key.b[i];
}
a.dw[0] = a.dw[1] = 0;
printf("\nPOST S-Box 32bit 값 출력 [(16)진수] ");
for(i=0;i<8;i++)
{
if(i%2 == 0)
a.b[i/2] = s_table[i][t.b[i]>>2] << 4;
else
a.b[i/2] += s_table[i][t.b[i]>>2];
printf("\nS%d(B%d) %02x \t",i,i,a.b[i/2]);
}
t.dw[0] = t.dw[1] = 0;
for(i=0;i<32;i++)
{
BYTE temp = tp_table[i] -1;
if(a.b[temp / 8] & mask[temp%8])
t.b[i/8] |= mask[i%8];
}
text->dw[0] ^= t.dw[0];
}
void to_bin( int num )//10진수를 2진수로 변환, 32비트
{
unsigned mask = 0x80000000u;//mask값, 32비트 최고값.
int i;
printf( "%d(10)->", num );
for( i = 0; i < 32; i++ )
{
if( num & mask )
putchar( '1' );
else
putchar( '0' );
mask >>=1;
}
}
void des_encrytion(BIT64 key, BIT64 plain, BIT64 *out) /* 암호화 */
{
BIT64 keys[16];
BYTE i;
DWORD t;
MakeKey(key,keys); /* 암호화키 16개 만들기 */
out->dw[0] = plain.dw[0];
out->dw[1] = plain.dw[1];
IP(out); /* IP치환 */
for(i=0;i<16;i++) /* 16회 반복 */
{
RoundFunction(keys[i],out);
t = out->dw[0];
out->dw[0] = out->dw[1];
out->dw[1] = t;
printf("\n%d회차(16) 키 : %x\n",i+1,t); //16진수 출력
printf("10진수의 2진수 변환 => ");
to_bin(t);
printf("\n");
}
t = out->dw[0];
out->dw[0] = out->dw[1];
out->dw[1] = t;
FP(out); /* IP역치환 */
}
int main(void)
{
BIT64 key,in,out;
DWORD i;
BYTE ch[9];
BYTE KEY[8] = {0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01};
for(i=0;i<8;i++)
{
key.b[i] = KEY[i];
}
printf("\n--=================================--");
printf("\n D E S P R O G R A M ");
printf("\n--=================================--");
printf("\n오직 8글자 평문을 입력하시오 : ");
scanf("%s",&in);
printf("\n오직 8글자 암호키를 입력하시오 : ");
scanf("%s",&key);
des_encrytion(key,in,&out);
printf("\n 입력한 문자 16진수값 : %02X %02X %02X %02X %02X %02X %02X %02X",
in.b[0],in.b[1],in.b[2],in.b[3],in.b[4],in.b[5],in.b[6],in.b[7]);
printf("\n 입력한 암호키 16진수값 : %02X %02X %02X %02X %02X %02X %02X %02X",
key.b[0],key.b[1],key.b[2],key.b[3],key.b[4],key.b[5],key.b[6],key.b[7]);
printf("\n 암호문은 : %c%c%c%c%c%c%c%c",
out.b[0],out.b[1],out.b[2],out.b[3],out.b[4],out.b[5],out.b[6],out.b[7]);
printf("\n 확인하기어려울때(HEX) : %02X %02X %02X %02X %02X %02X %02X %02X \n",
out.b[0],out.b[1],out.b[2],out.b[3],out.b[4],out.b[5],out.b[6],out.b[7]);
return 0;
}
'암호화 알고리즘' 카테고리의 다른 글
쉽게보는 ARIA 알고리즘 - 라운드 (0) | 2018.12.26 |
---|---|
(3-DES) 간단한 대칭 알고리즘 예제 (0) | 2018.12.26 |
SHA1withRSA, SHA1withDSA 완성 (0) | 2018.12.26 |
DB암호화 방식 비교 (0) | 2018.12.26 |
국산 블럭암호 ARIA 기술 (2) | 2016.11.17 |