C++語言: Codee#13635
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
typedef unsigned char uchar;
//初始換位IP
char IP [ 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
};
//逆初始換位IP-1
char IP_1 [ 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
};
//置換選擇1
char PC_1 [ 56 ] =
{
57 , 49 , 41 , 33 , 25 , 17 , 9 ,
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
};
//置換選擇2
char PC_2 [ 48 ] =
{
14 , 17 , 11 , 24 , 1 , 5 ,
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
};
//擴充置換Expansion
char Expansion [ 48 ] =
{
32 , 1 , 2 , 3 , 4 , 5 ,
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
};
//P盒置換
char PBox [ 32 ] = { 16 , 7 , 20 , 21 , 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 };
//S盒子
char SBox [ 8 ][ 4 ][ 16 ] =
{
{
14 , 4 , 13 , 1 , 2 , 15 , 11 , 8 , 3 , 10 , 6 , 12 , 5 , 9 , 0 , 7 ,
0 , 15 , 7 , 4 , 14 , 2 , 13 , 1 , 10 , 6 , 12 , 11 , 9 , 5 , 3 , 8 ,
4 , 1 , 14 , 8 , 13 , 6 , 2 , 11 , 15 , 12 , 9 , 7 , 3 , 10 , 5 , 0 ,
15 , 12 , 8 , 2 , 4 , 9 , 1 , 7 , 5 , 11 , 3 , 14 , 10 , 0 , 6 , 13
},
{
15 , 1 , 8 , 14 , 6 , 11 , 3 , 4 , 9 , 7 , 2 , 13 , 12 , 0 , 5 , 10 ,
3 , 13 , 4 , 7 , 15 , 2 , 8 , 14 , 12 , 0 , 1 , 10 , 6 , 9 , 11 , 5 ,
0 , 14 , 7 , 11 , 10 , 4 , 13 , 1 , 5 , 8 , 12 , 6 , 9 , 3 , 2 , 15 ,
13 , 8 , 10 , 1 , 3 , 15 , 4 , 2 , 11 , 6 , 7 , 12 , 0 , 5 , 14 , 9
},
{
10 , 0 , 9 , 14 , 6 , 3 , 15 , 5 , 1 , 13 , 12 , 7 , 11 , 4 , 2 , 8 ,
13 , 7 , 0 , 9 , 3 , 4 , 6 , 10 , 2 , 8 , 5 , 14 , 12 , 11 , 15 , 1 ,
13 , 6 , 4 , 9 , 8 , 15 , 3 , 0 , 11 , 1 , 2 , 12 , 5 , 10 , 14 , 7 ,
1 , 10 , 13 , 0 , 6 , 9 , 8 , 7 , 4 , 15 , 14 , 3 , 11 , 5 , 2 , 12
},
{
7 , 13 , 14 , 3 , 0 , 6 , 9 , 10 , 1 , 2 , 8 , 5 , 11 , 12 , 4 , 15 ,
13 , 8 , 11 , 5 , 6 , 15 , 0 , 3 , 4 , 7 , 2 , 12 , 1 , 10 , 14 , 9 ,
10 , 6 , 9 , 0 , 12 , 11 , 7 , 13 , 15 , 1 , 3 , 14 , 5 , 2 , 8 , 4 ,
3 , 15 , 0 , 6 , 10 , 1 , 13 , 8 , 9 , 4 , 5 , 11 , 12 , 7 , 2 , 14
},
{
2 , 12 , 4 , 1 , 7 , 10 , 11 , 6 , 8 , 5 , 3 , 15 , 13 , 0 , 14 , 9 ,
14 , 11 , 2 , 12 , 4 , 7 , 13 , 1 , 5 , 0 , 15 , 10 , 3 , 9 , 8 , 6 ,
4 , 2 , 1 , 11 , 10 , 13 , 7 , 8 , 15 , 9 , 12 , 5 , 6 , 3 , 0 , 14 ,
11 , 8 , 12 , 7 , 1 , 14 , 2 , 13 , 6 , 15 , 0 , 9 , 10 , 4 , 5 , 3
},
{
12 , 1 , 10 , 15 , 9 , 2 , 6 , 8 , 0 , 13 , 3 , 4 , 14 , 7 , 5 , 11 ,
10 , 15 , 4 , 2 , 7 , 12 , 9 , 5 , 6 , 1 , 13 , 14 , 0 , 11 , 3 , 8 ,
9 , 14 , 15 , 5 , 2 , 8 , 12 , 3 , 7 , 0 , 4 , 10 , 1 , 13 , 11 , 6 ,
4 , 3 , 2 , 12 , 9 , 5 , 15 , 10 , 11 , 14 , 1 , 7 , 6 , 0 , 8 , 13
},
{
4 , 11 , 2 , 14 , 15 , 0 , 8 , 13 , 3 , 12 , 9 , 7 , 5 , 10 , 6 , 1 ,
13 , 0 , 11 , 7 , 4 , 9 , 1 , 10 , 14 , 3 , 5 , 12 , 2 , 15 , 8 , 6 ,
1 , 4 , 11 , 13 , 12 , 3 , 7 , 14 , 10 , 15 , 6 , 8 , 0 , 5 , 9 , 2 ,
6 , 11 , 13 , 8 , 1 , 4 , 10 , 7 , 9 , 5 , 0 , 15 , 14 , 2 , 3 , 12
},
{
13 , 2 , 8 , 4 , 6 , 15 , 11 , 1 , 10 , 9 , 3 , 14 , 5 , 0 , 12 , 7 ,
1 , 15 , 13 , 8 , 10 , 3 , 7 , 4 , 12 , 5 , 6 , 11 , 0 , 14 , 9 , 2 ,
7 , 11 , 4 , 1 , 9 , 12 , 14 , 2 , 0 , 6 , 10 , 13 , 15 , 3 , 5 , 8 ,
2 , 1 , 14 , 7 , 4 , 10 , 8 , 13 , 15 , 12 , 9 , 0 , 3 , 5 , 6 , 11
}
};
//密鑰移位次序(循環左移),左右28位分别循環左移的
char LM [ 16 ] = { 1 , 1 , 2 , 2 , 2 , 2 , 2 , 2 , 1 , 2 , 2 , 2 , 2 , 2 , 2 , 1 };
//按位輸出n個位元組
void printBit( uchar a [], int n)
{
int i , j , bit;
for( i = 0; i <n; i ++ ){
for( j = 0; j < 8; j ++ ){
bit = ( a [ i ] >> ( 7 - j)) & 0x01;
printf( "%d" , bit);
}
if( i == n - 1) printf( " /n ");
else printf( ",");
}
}
//輸出n個位元組大小的數的16進制
void printHex( uchar a [], int n)
{
int i , t;
printf( "0x");
for( i = 0; i <n; i ++ ){
t = a [ i ]; //考慮到int在記憶體中的存儲(低低高高),就一個位元組一個位元組的存儲。
if( t > 16 )
printf( "%x" , t);
else
printf( "0%x" , t);
}
printf( " /n ");
}
//取bits位數的某位,為0傳回0,為1就傳回1
int GetBit( const uchar * number , int pos , int bits)
{
assert( pos > 0 && pos <= bits);
int i , j;
pos --;
i = pos / 8;
j = pos % 8;
return ( number [ i ] >> ( 7 - j)) & 0x01;
}
//使用bit數組來設定number的各位的值(共更改bits位)
void SetBit( uchar * number , int * bit , int bits)
{
uchar t;
int i , j , bytes;
if( bits % 8 == 0) bytes = bits / 8;
else bytes = bits / 8 + 1;
for( i = 0; i < bytes; i ++ ){
t = 0;
for( j = 0; ( j < 8) && ( i * 8 + j < bits); j ++)
t |= ( char)( bit [ i * 8 + j ] << ( 7 - j));
number [ i ] = t;
}
}
//初始換位
void ip( uchar LR [ 8 ])
{
int i , bit [ 64 ];
for( i = 0; i < 64; i ++)
bit [ i ] = GetBit( LR , IP [ i ], 64);
SetBit( LR , bit , 64);
}
//逆初始換位
void ip_1( uchar LR [ 8 ])
{
int i , bit [ 64 ];
for( i = 0; i < 64; i ++)
bit [ i ] = GetBit( LR , IP_1 [ i ], 64);
SetBit( LR , bit , 64);
}
//置換選擇1,從初始的64位密鑰中選取56位
void pc_1( const uchar password [ 8 ], uchar key [])
{
int i , bit [ 56 ];
for( i = 0; i < 56; i ++)
bit [ i ] = GetBit( password , PC_1 [ i ], 64);
SetBit( key , bit , 56);
}
//置換選擇2,從56位的CD(28b+28b)導出48為密鑰
void pc_2( const uchar CD [ 7 ], uchar K [ 6 ])
{
int i , bit [ 48 ];
for( i = 0; i < 48; i ++)
bit [ i ] = GetBit( CD , PC_2 [ i ], 56);
SetBit( K , bit , 48);
}
//對28位數循環左移n位,num[28]是01字元數組
void LeftMoveOf28Bit( int num [ 28 ], int n)
{
int i , t;
while(n -- ){
t = num [ 0 ];
for( i = 0; i < 27; i ++)
num [ i ] = num [ i + 1 ];
num [ 27 ] = t;
}
}
//把56為的cd分成兩個28位,分别循環左移n位
void lm( uchar CD [ 7 ], int n)
{
int i , bit [ 56 ], * C , * D;
for( i = 0; i < 56; i ++)
bit [ i ] = GetBit( CD , i + 1 , 56);
C = bit;
D = bit + 28;
LeftMoveOf28Bit( C , n);
LeftMoveOf28Bit( D , n);
SetBit( CD , bit , 56);
}
//擴充置換,把Ri從32為擴充到48位
void expansion( const uchar Ri [ 4 ], uchar Re [ 6 ])
{
int i , bit [ 48 ];
for( i = 0; i < 48; i ++)
bit [ i ] = GetBit( Ri , Expansion [ i ], 32);
SetBit( Re , bit , 48);
}
//對前bits位進行異或操作,X=A^B
void XOR( const uchar * A , const uchar *B , uchar * X , int bits)
{
int i , bytes;
if( bits % 8 == 0) bytes = bits / 8;
else bytes = bits / 8 + 1;
//memset(X, 0, bytes);
for( i = 0; i < bytes; i ++)
X [ i ] = A [ i ] ^ B [ i ];
}
//設定a[1]~a[4],表示為二進制的x, x>=0 && x<=15
void sboxSetBit( int a [], int x)
{
assert( x >= 0 && x <= 15);
a [ 0 ] = ( x & 8) >> 3;
a [ 1 ] = ( x & 4) >> 2;
a [ 2 ] = ( x & 2) >> 1;
a [ 3 ] = ( x & 1);
}
//S盒子操作
void sbox( uchar A [ 6 ], uchar B [ 4 ])
{
int i , t , row , column , bitA [ 48 ], bitB [ 32 ];
for( i = 0; i < 48; i ++)
bitA [ i ] = GetBit( A , i + 1 , 48);
//s盒子代換,由bitA[48]得到bitB[32]
for( i = 0; i < 8; i ++ ){
row = bitA [ i * 6 ] * 2 + bitA [ i * 6 + 5 ];
column = bitA [ i * 6 + 1 ] * 8 + bitA [ i * 6 + 2 ] * 4 + bitA [ i * 6 + 3 ] * 2 + bitA [ i * 6 + 4 ];
t = SBox [ i ][ row ][ column ];
sboxSetBit( bitB + i * 4 , t); //t>=0 && t=<15,占4bit
}
SetBit(B , bitB , 32);
}
//P盒子操作
void pbox( uchar A [ 4 ])
{
int i , bit [ 32 ];
for( i = 0; i < 32; i ++)
bit [ i ] = GetBit( A , PBox [ i ], 32);
SetBit( A , bit , 32);
}
//輸入的明文是8個位元組長的帶加密字元,和密鑰
uchar * DES( const char str [ 8 ], const char password [ 8 ])
{
int i;
uchar LR [ 8 ], key [ 8 ], CD [ 7 ], K [ 16 ][ 6 ], LRi [ 16 ][ 8 ], Rie [ 6 ], xorResult [ 6 ], sResult [ 4 ];
memcpy( LR , str , 8);
memcpy( key , password , 8);
//1、初始置換
ip( LR);
//2、置換選擇1
//密鑰産生,置換選擇1,64位->56位
pc_1( key , CD);
//3、依次産生16組密鑰
for( i = 0; i < 16; i ++ ){
//3.1、把CD分成兩個28位,并分别循環移位
lm( CD , LM [ i ]);
//3.2、經過置換選擇2,從56位選出48為的K
pc_2( CD , K [ i ]);
//輸入子密鑰
//printf("K%d=",i); printHex(K[i], 6);
}
//4、進行16輪的擴充置換和S盒子代換
for( i = 0; i < 16; i ++ ){
//4.1 設定Li = Ri-1
if( i == 0) {
memcpy( LRi [ 0 ], LR + 4 , 4);
} else {
memcpy( LRi [ i ], LRi [ i - 1 ] + 4 , 4); //Li=Ri-1
}
//4.2、擴充Ri
if( i == 0 ){
expansion( LR + 4 , Rie);
} else {
expansion( LRi [ i - 1 ] + 4 , Rie); //擴充Ri-1
}
//4.3、密鑰Ki與擴充後的分組異或
XOR( K [ i ], Rie , xorResult , 48);
//4.4、進行S盒子運算,将上步得到的48位的xorResult轉換成32位
sbox( xorResult , sResult);
//4.5、将上步得到的sResult做p盒子置換
pbox( sResult);
//4.6、繼續和Li-1做異或運算,結果儲存到Ri
if( i == 0 ){
XOR( sResult , LR , LRi [ 0 ] + 4 , 32);
} else {
XOR( sResult , LRi [ i - 1 ], LRi [ i ] + 4 , 32);
}
//輸出每輪的加密結果
//printf("i=%-2d:",i); printHex(LRi[i],8);
}
//5、需要把最後一輪的左右兩部分互換一下
uchar t_uchar [ 4 ];
memcpy( t_uchar , LRi [ 15 ], 4);
memcpy( LRi [ 15 ], LRi [ 15 ] + 4 , 4);
memcpy( LRi [ 15 ] + 4 , t_uchar , 4);
//6、逆初始置換
ip_1( LRi [ 15 ]);
uchar * EncryptStr = ( uchar *) malloc( 8);
memcpy( EncryptStr , LRi [ 15 ], 8);
return EncryptStr;
}
//DES解密
uchar * DES_1( const uchar str [ 8 ], const char password [ 8 ])
{
int i;
uchar LR [ 8 ], key [ 8 ], CD [ 7 ], K [ 16 ][ 6 ], LRi [ 16 ][ 8 ], Rie [ 6 ], xorResult [ 6 ], sResult [ 4 ];
memcpy( LR , str , 8);
memcpy( key , password , 8);
//1、初始置換
ip( LR);
//2、置換選擇1
//密鑰産生,置換選擇1,64位->56位
pc_1( key , CD);
//3、依次産生16組密鑰
for( i = 0; i < 16; i ++ ){
//3.1、把CD分成兩個28位,并分别循環移位
lm( CD , LM [ i ]);
//3.2、經過置換選擇2,從56位選出48為的K
pc_2( CD , K [ i ]);
//輸入子密鑰
//printf("K%d=",i); printHex(K[i], 6);
}
//4、進行16輪的擴充置換和S盒子代換
for( i = 0; i < 16; i ++ ){
//4.1 設定Li = Ri-1
if( i == 0) {
memcpy( LRi [ 0 ], LR + 4 , 4);
} else {
memcpy( LRi [ i ], LRi [ i - 1 ] + 4 , 4); //Li=Ri-1
}
//4.2、擴充Ri
if( i == 0 ){
expansion( LR + 4 , Rie);
} else {
expansion( LRi [ i - 1 ] + 4 , Rie); //擴充Ri-1
}
//4.3、密鑰Ki與擴充後的分組異或
XOR( K [ 15 - i ], Rie , xorResult , 48);
//4.4、進行S盒子運算,将上步得到的48位的xorResult轉換成32位
sbox( xorResult , sResult);
//4.5、将上步得到的sResult做p盒子置換
pbox( sResult);
//4.6、繼續和Li-1做異或運算,結果儲存到Ri
if( i == 0 ){
XOR( sResult , LR , LRi [ 0 ] + 4 , 32);
} else {
XOR( sResult , LRi [ i - 1 ], LRi [ i ] + 4 , 32);
}
//輸出每輪的加密結果
//printf("i=%-2d:",i); printHex(LRi[i],8);
}
//5、需要把最後一輪的左右兩部分互換一下
uchar t_uchar [ 4 ];
memcpy( t_uchar , LRi [ 15 ], 4);
memcpy( LRi [ 15 ], LRi [ 15 ] + 4 , 4);
memcpy( LRi [ 15 ] + 4 , t_uchar , 4);
//6、逆初始置換
ip_1( LRi [ 15 ]);
uchar * EncryptStr = ( uchar *) malloc( 8);
memcpy( EncryptStr , LRi [ 15 ], 8);
return EncryptStr;
}
int main()
{
char str [ 9 ], pass [ 9 ], str2 [ 9 ];
uchar * result , * result2;
while( 1 ){
memset( str , 0 , 9);
memset( str2 , 0 , 9);
memset( pass , 0 , 9);
scanf( "%s%s" , str , pass);
//加密
result = DES( str , pass);
//解密
result2 = DES_1( result , pass);
uchar t;
memcpy( & t , str , 8);
printf( "明文的16進制 :");
printHex( & t , 8); //輸出原文的16進制
printf( "密文的16進制 :");
printHex( result , 8); //輸出密文
printf( "解密後的16進制:");
printHex( result2 , 8); //輸出解密後的16進制
printf( "解密後的字元 :");
memcpy( str2 , result2 , 8); //輸出解密的結果(字元)
printf( "%s /n/n " , str2);
free( result2); result2 = NULL;
free( result); result = NULL;
}
return 0;
}