1、DES的加密过程可分为加密处理,加密变换和子密钥生成几个部分组成。 1.加密处理过程 (1)初始变换。加密处理首先要对64位的明文按表1所示的初始换位表IP进行变换。表中的数值表示输入位被置换后的新位置。例如输入的第58位,在输出的时候被置换到第1位;输入的是第7位,在输出时被置换到第64位。(2)加密处理。上述换位处理的输出,中间要经过16轮加密变换。初始换位的64位的输出作为下一次的输入,将64位分为左、右两个32位,分别记为L0和R0,从L0、R0到L16、R16,共进行16轮加密变换。其中,经过n轮处理后的点左右32位分别为Ln和Rn,则可做如下定义:Ln=Rn-1 Rn=Ln-1 其
2、中,kn是向第n轮输入的48位的子密钥,Ln-1和Rn-1分别是第n-1轮的输出,f是Mangler函数。(3)最后换位。进行16轮的加密变换之后,将L16和R16合成64位的数据,再按照表2所示的最后换位表进行IP-1的换位,得到64位的密文,这就是DES算法加密的结果。2.加密变换过程 通过重复某些位将32位的右半部分按照扩展表3扩展换位表扩展为48位,而56位的密钥先移位然后通过选择其中的某些位减少至48位,48位的右半部分通过异或操作和48位的密钥结合,并分成6位的8个分组,通过8个S-盒将这48位替代成新的32位数据,再将其置换一次。这些S-盒输入6位,输出4位。3.子密钥生成过程
3、钥通常表示为64位的自然数,首先通过压缩换位PC-1去掉每个字节的第8位,用作奇偶校验,因此,密钥去掉第8、16、2464位减至56位,所以实际密钥长度为56位,而每轮要生成48位的子密钥。4.解密处理过程 从密文到明文的解密过程可采用与加密完全相同的算法。不过解密要用加密的逆变换,就是把上面的最后换位表和初始换位表完全倒过来变换。这里不再赘述。1.3关键算法解析算法实现过程中主要用到了一下几个函数: int CharToNum(char c)/将字符转化成数字。 char* encrypt(char pw,char key,bool jiami);/加密函数/参数:char pw明文,cha
4、r key密钥,bool jiami标志为(1表示加密,0表示解密) char* HexToStr(char ch) /16进制转化成字符串 bool IsNum(char c) /判断一个字符是否是数字的形式 void LS(int n) /密钥左移函数,参数n是左移多少位 char NumToHex(int x) /转化成16进制 char *StrToHex(char *ch) /字符串转化为16进制1.4实验代码/Main.cpp : 实现DES加密与解密算法#include stdio.hstring.h#define ENCRYPT 1#define DECRYPT 0static
5、 void printHex( char *cmd, int len );static void printArray( const char *In, int len );static void F_func(bool In32, const bool Ki48); /f函数static void S_func(bool Out32, const bool In48); /S盒变换static void Transform(bool *Out, bool *In, const char *Table, int len); /变换static void Xor(bool *InA, const
6、 bool *InB, int len); /异或运算static void RotateL(bool *In, int len, int loop); /循环左移static void ByteToBit(bool *Out, const char *In, int bits); /字节转换为位static void BitToByte(char *Out, const bool *In, int bits); /位转换为字节void Des_SetKey(const char Key8); /生成子密钥void Des_Run(char Out8, char In8, bool Type)
7、; /DES算法static bool SubKey1648;/16位子密钥/64位经过PC-1置换后为56位 const static char PC1_Table56 = 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,
8、 4;/左移const static char LOOP_Table16 = 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1/PC-2排列选择const static char PC2_Table48 = 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
9、, 29, 32/Ri_1(32位)经过扩展置换后为48位 static const char E_Table48 = 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盒const static char P_Table32 = 16, 7, 20, 21, 29, 12, 28, 17,
10、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盒const static char S_Box8416 = / S1 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,
11、 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13 , / S2 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 / S3 10, 0, 9, 14, 6, 3, 15, 5,
12、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 / S4 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
13、, 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 , / S5 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,
14、1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3 / S6 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 / S7 4, 11, 2, 14, 15, 0, 8, 13, 3, 12
15、, 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 / S8 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 ,
16、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 / 初始IP置换const static char IP_Table64 = 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,
17、 59, 51, 43, 35, 27, 19, 11, 3, 61, 53, 45, 37, 29, 21, 13, 5, 63, 55, 47, 39, 31, 23, 15, 7/ L16与R16合并后经过IP逆置换const static char IPR_Table64 = 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
18、, 3, 43, 11, 51, 19, 59, 27, 34, 2, 42, 10, 50, 18, 58, 26, 33, 1, 41, 9, 49, 17, 57, 25/主函数void main(int argc, char *argv) char key10; char str110; char str210; printf(=DES加密与解密=n); /输入密钥,密钥为8位十进制数请输入初始密钥:n scanf(%s,key); /输入明文,明文长度不多于8位请输入明文:,str1); /实现加密n解密前的明文: n%sn Des_SetKey(key); memset(str2,
19、 0, sizeof(str2); Des_Run(str2, str1, ENCRYPT); /密文为十六进制输出加密后的密文: n printHex( str2, 8 ); /实现解密解密前的密文: memset(str1, 0, sizeof(str1);解密后的明文: Des_Run(str1, str2, DECRYPT); puts(str1);/生成子密钥void Des_SetKey(const char Key8) int i; static bool K64, *KL = &K0, *KR = &K28; ByteToBit(K, Key, 64);/转换为二进制 Tran
20、sform(K, K, PC1_Table, 56);/64比特的密钥K,经过PC-1后,生成56比特的串。 /生成16个子密钥 for(i=0; i=0; i-) memcpy(tmp, Li, 32); F_func(Li, SubKeyi); Xor(Li, Ri, 32); memcpy(Ri, tmp, 32); /R16与L16合并成64位的比特串。R16一定要排在L16前面。R16与L16合并后成的比特串,经过置换IP-1后所得的比特串就是密文。 Transform(M, M, IPR_Table, 64); BitToByte(Out, M, 64);/F函数:将32比特的输入
21、再转化为32比特的输出void F_func(bool In32, const bool Ki48) static bool MR48; /输入Ri-1(32比特)经过变换E后,扩展为48比特 Transform(MR, In, E_Table, 48); /异或 Xor(MR, Ki, 48); /扩展后的比特串分为8组,每组6比特。各组经过各自的S盒后,又变为4比特,合并后又成为32比特。 S_func(In, MR); /该32比特经过P变换后,输出的比特串才是32比特的f (Ri-1,Ki)。 Transform(In, In, P_Table, 32);/S盒变换void S_fun
22、c(bool Out32, const bool In48) char j,m,n; for(j=0; j8; j+,In+=6,Out+=4) /在其输入In0,In1,In2,In3,In4,In5中,计算出m=In0*2+In5, n=In4+In3*2+In2*4+In1*8, /再从Sj表中查出m行,n列的值Smn。将Smn化为二进制,即得Si盒的输出。 m = (In01) + In5; n = (In13) + (In22) + (In31) + In4; ByteToBit(Out, &S_Box(int)j(int)m(int)n, 4);/打印指定位置指定长度HEX值sta
23、tic void printHex( char *cmd, int len )len;%02x ,(unsigned char)cmdi);/打印数组static void printArray( const char *In, int len ) char tmp256; memset(tmp, 0, sizeof(tmp); tmp(int)Ini=Ini; %02d ,(unsigned char)tmpi);/变换void Transform(bool *Out, bool *In, const char *Table, int len) static bool tmp256; tmpi = In Tablei-1 ; memcpy(Out, tmp, len);/异或运算void Xor(bool *InA, const bool *InB, int len) InAi = InBi;/ 循环左移void RotateL(bool *In, int len, int loop) memcpy(tmp, In, loop); memcpy(In, In+loop, len-loop);
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1