13 级本科生课程报告
课程名称 密码学课程设计 报告时间 2016.1 学生姓名邱翔宇 学 号 08133609 班级信息安全13-3 任课教师李 昕
实验一:放射密码
一、实验目的
学习仿射密码的具体工作原理,理解仿射密码的计算过程,并根据所知的知识进行放射密码的编程,编写出其加密和解密函数。运行程序进行实践。 二、实验内容
加法密码和乘法密码结合构成仿射密码,仿射密码的加密和解密算法分别是: C= Ek(m)=(k1m+k2) mod n
M= Dk(c)=k3(c- k2) mod n(其中(k3 ×k1)mod26 = 1)
仿射密码具有可逆性的条件是(k1, n)=1。当k1=1时,仿射密码变为加法密码,当k2=0时,仿射密码变为乘法密码。
仿射密码中的密钥空间的大小为nφ(n),当n为26字母,φ(n)=12,因此仿射密码的密钥空间为12×26 = 312。 1)代码:
#include char v[26]={'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'}; char l[26]={'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'}; int Number(char x){ for(int i=0;i<26;i++) {if(x==l[i]) {return (i+1);}}} void JiaMi(string m){ //加密 int k1,k2; cout<<\"请输入明文:\"; cin>>m; cout<<\"请输入k1:\"; cin>>k1; cout<<\"请输入k2:\"; cin>>k2; int c1,c2; int mlen; mlen=m.length(); char *p,*q; p=new char[m.length()+1]; strcpy(p,m.c_str()); q=new char[m.length()]; int tmp; for(int i=0;i cout<<\"请输入密文:\"; cin>>m; cout<<\"请输入k1:\"; cin>>k1; cout<<\"请输入k2:\"; cin>>k2; int c1,c2; int j,tmp; char *p,*q; p=new char[m.length()+1]; strcpy(p,m.c_str()); q=new char[m.length()]; for(int i=0;i 实验二:序列密码 一、实验目的 学习线性反馈移位寄存器的具体工作原理,了解其计算方法步骤,并根据所知的知识进行线性反馈移位寄存器的编程,能够编写出其加密和解密函数。并且运行程序成功。 二、实验内容 1)代码 #include void yiwei(bool y[8]) //移位函数 {bool x=y[7]^y[5]^y[4]^y[0]; for(int i=0;i<7;i++) y[i]=y[i+1]; y[7]=x; cout< 实验三:分组密码 一、实验目的 学习DES的具体工作原理,了解其计算方法步骤,并根据所学的知识进行DES的编程,编写出其加密和解密函数。并且运行程序成功。 二、实验内容 1)过程: DES算法的入口参数有三个: Key, Data, Mode Key 为bit密钥, Data为bit数据,Mode为加密还是解密。 DES算法的过程: 1. 对输入的密钥进行变换。 用户的bit密钥,其中第8, 16, 24, 32, 40, 48, 56, 位是校验位, 使得每个密钥都有奇数个1。所以密钥事实上是56位。对这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, 表的意思是第57位移到第1位,第49位移到第2位,...... 以此类推。变换后得到56bit数据,将它分成两部分,C[0][28], D[0][28]。 2. 计算16个子密钥,计算方法C[i][28] D[i][28]为对前一个C[i-1][28], D[i-1][28]做循环左移操作。16次的左移位数如下表: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 (第i次) 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 (左移位数) 3. 串联计算出来的C[i][28] D[i][28] 得到56位,然后对它进行如下变换得到48位子密钥K[i][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, 表的意思是第14位移到第1位,第17位移到第2位,以此类推。在此过程中,发现第9,18,22,25, 35,38,43,54位丢弃。 4. 对bit的明文输入进行换位变换。换位表如下: 58, 50, 12, 34, 26, 18, 10, 2, 60, 52, 44, 36, 28, 20, 12, 4, 62, 54, 46, 38, 30, 22, 14, 6, , 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 表的意思就是第一次变换时,第58位移到第1位,第50位移到第2位,...... 依此类推。得到位数据,将这数据前后分成两块L[0][32], R[0][32]。 5. 加密过程,对R[i][32]进行扩展变换成48位数,方法如下, 记为E(R[i][32]) 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, 6. 将E(R[i][32])与K[i][48]作异或运算,得到48位数,将48位数顺序分成8份,6位一份, B[8][6]。 7. 使用S[i]替换B[i][6]。过程如下: 取出B[i][6]的第1位和第6位连成一个2位数m, m就是S[i]中对应的行数(0-3),取出B[i][6]的第2到第5位连成一个4位数n(0-15),n就是S[i]中对应的列数,用S[i][m][n]代替B[i][6]。S是4行16列的对应表,里面是4位的数,一共有8个S,定义如下: S[1]: 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, S[2]: 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, S[3]: 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, S[4]: 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, S[5]: 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, S[6]: 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, S[7]: 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, S[8]: 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, 8. 将从B[i][6]经过S得到的8个4位数连起来得到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, 得到的结果与L[i][32]作异或运算,把结果赋给R[i][32]。 9. 把R[i-1][32]的值赋给L[i],从5开始循环。直到K[16][48]结束。 10. 将最后的L,R合并成位,然后进行如下转化得到最后的结果。这是对第4步的一个逆变化。 40, 8, 48, 16, 56, 24, , 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 以上是Des的加密过程,解密过程同样,只需要把16个子密钥K[i][48]的顺序颠倒过来就行了。 代码: #include static void printHex ( char *cmd, int len ); static void printArray ( const char *In, int len ); static void F_func ( bool In[32], const bool Ki[48] ); // f函数 static void S_func ( bool Out[32], const bool In[48] ); // S盒代替 static void Transform ( bool *Out, bool *In, const char *Table, int len ); // 变换 static void Xor ( bool *InA, const 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 ); // 位组转换成字节组 // 16位子密钥 static bool SubKey[16][48]; // 位经过PC1转换为56位 (PC-1) const static char PC1_Table[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 }; // 左移 const static char LOOP_Table[16] = { 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 }; // 排列选择 2 (PC-2) const static char PC2_Table[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 }; // Ri_1(32位)经过变换E后膨胀为48位 (E) static const char E_Table[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 }; // 8个4比特合并为32比特的排列 P const static char P_Table[32] = { 16, 7, 20, 21, 29, 12, 28, 17, 1, 15, 23, 26, 5, 18, 31, 10, void F_func 2, 8, 24, 14, 32, 27, 3, 9, 19, 13, 30, 6, 22, 11, 4, 25, }; // 经过S盒 S-boxes const static char S_Box[8][4][16] = { { // 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, 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, 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, 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, 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, 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 { 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_Table[] = { 58, 50, 42, 34, 26, 18, 10, 2, 60, 52, 44, 36, 28, 20, 12, 4, 62, 54, 46, 38, 30, 22, 14, 6, , 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 }; // L16与R16合并后经过IP_1的最终排列 (IP**-1) const static char IPR_Table[] = { 40, 8, 48, 16, 56, 24, , 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 void Des_SetKey ( const char Key[8] ); //生成子密钥 void Des_Run ( char Out[8], char In[8], bool Type ); //DES算法 int main () { char key[12]={1,2,3,4,5,6,7,8}; char str[12]; char str2[12]; //printArray( PC2_Table, sizeof(PC2_Table)/sizeof(PC2_Table[0]) ); scanf(\"%s\ printf ( \"Before encrypting: \" ); puts ( str ); Des_SetKey ( key ); memset ( str2, 0, sizeof ( str2 ) ); Des_Run ( str2, str, ENCRYPT ); printf ( \"After encrypting: \" ); //printf(\"%s\\n\ printHex ( str2, 8 ); memset ( str, 0, sizeof ( str ) ); printf ( \"After decrypting: \" ); Des_Run ( str, str2, DECRYPT ); puts ( str ); return 0; } void Des_SetKey ( const char Key[8] ) { int i; static bool K[], *KL = &K[0], *KR = &K[28]; ByteToBit ( K, Key, ); //转换为二进制 Transform ( K, K, PC1_Table, 56 ); //比特的密钥K,经过PC-1后,生成56比特的串。 //生成16个子密钥 for ( i=0; i<16; i++ ) { //循环左移,合并 RotateL ( KL, 28, LOOP_Table[i] ); RotateL ( KR, 28, LOOP_Table[i] ); Transform ( SubKey[i], K, PC2_Table, 48 ); } } void Des_Run ( char Out[8], char In[8], bool Type ) { int i; static bool M[], tmp[32], *Li = &M[0], *Ri = &M[32]; //转换为位的数据块 ByteToBit ( M, In, ); //IP置换 (初始) Transform ( M, M, IP_Table, ); //该比特串被分为32位的L0和32位的R0两部分。 if ( Type == ENCRYPT ) { //16轮置换 for ( i=0; i<16; i++ ) { memcpy ( tmp, Ri, 32 ); // R[i] = L[i-1] xor f(R[i-1], K[i]) F_func ( Ri, SubKey[i] ); // 2.4.6 Exclusive-or the resulting value with L[i-1]. // R[I]=P XOR L[I-1] Xor ( Ri, Li, 32 ); // L[i] = R[i-1] memcpy ( Li, tmp, 32 ); } } else { // 如果解密则反转子密钥顺序 } for ( i=15; i>=0; i-- ) { memcpy ( tmp, Li, 32 ); F_func ( Li, SubKey[i] ); Xor ( Li, Ri, 32 ); memcpy ( Ri, tmp, 32 ); } //R16与L16合并成位的比特串。R16一定要排在L16前面。R16与L16合并后成的比特串,经过置换IP-1后所得的比特串就是密文。 Transform ( M, M, IPR_Table, ); BitToByte ( Out, M, ); } //将32比特的输入再转化为32比特的输出 void F_func ( bool In[32], const bool Ki[48] ) { static bool MR[48]; //输入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 ); } void S_func ( bool Out[32], const bool In[48] ) { char j,m,n; //膨胀后的比特串分为8组,每组6比特。 for ( j=0; j<8; j++,In+=6,Out+=4 ) { //在其输入In[0],In[1],In[2],In[3],In[4],In[5]中,计算出m=In[0]*2+In[5], n=In[4]+In[3]*2+In[2]*4+In[1]*8,再从Sj表中查出m行,n列的值Smn。将Smn化为二进制, 即得Si盒的输出。 m = ( In[0]<<1 ) + In[5]; n = ( In[1]<<3 ) + ( In[2]<<2 ) + ( In[3]<<1 ) + In[4]; ByteToBit ( Out, &S_Box[ ( int ) j][ ( int ) m][ ( int ) n], 4 ); } } // 打印指定位置指定长度HEX值 static void printHex ( char *cmd, int len ) { int i; for ( i=0; i static void printArray ( const char *In, int len ) { int i; char tmp[256]; memset ( tmp, 0, sizeof ( tmp ) ); for ( i=0; i for ( i=0; i // Sample: // In = [0x01] // Out = [0x01] [0x00] [0x00] [0x00] [0x00] [0x00] [0x00] [0x00] void ByteToBit ( bool *Out, const char *In, int bits ) { int i; for ( i=0; i void BitToByte ( char *Out, const bool *In, int bits ) { int i; memset ( Out, 0, ( bits+7 ) /8 ); for ( i=0; i 实验小结:这个实验我学习了DES的具体工作原理,能够了解其计算方法步骤,并根据所学的知识进行DES的编程,编写了出其加密和解密函数。并且运行程序成功了。但是这个程序超级长,在编写的过程中我回顾来很多C++的基础知识让我获益很多,在不懈的努力下终于成功了。 实验四 Hash函数 一、实验目的 学习Hash函数的具体工作原理,了解其计算原理过程,并能所知的知识进行Hash函数的编程,编写出其加密和解密函数。并且运行程序成功。 二、实验内容: 1)过程 对MD5算法简要的叙述可以为:MD5以512位分组来处理输入的信息,且每一分组又被划分为16个32位子分组,经过了一系列的处理后,算法的输出由四个32位分组组成,将这四个32位分组级联后将生成一个128位散列值。 第一步、填充:如果输入信息的长度(bit)对512求余的结果不等于448,就需要填充使得对512求余的结果等于448。填充的方法是填充一个1和n个0。填充完后,信息的长度就为N*512+448(bit); 第二步、记录信息长度:用位来存储填充前信息长度。这位加在第一步结果的后面,这样信息长度就变为N*512+448+=(N+1)*512位。 第三步、装入标准的幻数(四个整数):标准的幻数(物理顺序)是(A=(01234567)16,B=(ABCDEF)16,C=(FEDCBA98)16,D=(76543210)16)。如果在程序中定义应该是(A=0X67452301L,B=0XEFCDABL,C=0X98BADCFEL,D=0X10325476L)。 第四步、四轮循环运算:循环的次数是分组的个数(N+1) 1)将每一512字节细分成16个小组,每个小组位(8个字节) 2)先认识四个线性函数(&是与,|是或,~是非,^是异或) F(X,Y,Z)=(X&Y)|((~X)&Z) G(X,Y,Z)=(X&Z)|(Y&(~Z)) H(X,Y,Z)=X^Y^Z I(X,Y,Z)=Y^(X|(~Z)) 3)设Mj表示消息的第j个子分组(从0到15),<< a=GG(a,b,c,d,M1,5,0xf61e2562) b=GG(d,a,b,c,M6,9,0xc040b340) c=GG(c,d,a,b,M11,14,0x265e5a51) d=GG(b,c,d,a,M0,20,0xe9b6c7aa) a=GG(a,b,c,d,M5,5,0xd62f105d) b=GG(d,a,b,c,M10,9,0x02441453) c=GG(c,d,a,b,M15,14,0xd8a1e681) d=GG(b,c,d,a,M4,20,0xe7d3fbc8) a=GG(a,b,c,d,M9,5,0x21e1cde6) b=GG(d,a,b,c,M14,9,0xc33707d6) c=GG(c,d,a,b,M3,14,0xf4d50d87) d=GG(b,c,d,a,M8,20,0x455a14ed) a=GG(a,b,c,d,M13,5,0xa9e3e905) b=GG(d,a,b,c,M2,9,0xfcefa3f8) c=GG(c,d,a,b,M7,14,0x676f02d9) d=GG(b,c,d,a,M12,20,0x8d2a4c8a) 第三轮 a=HH(a,b,c,d,M5,4,0xfffa3942) b=HH(d,a,b,c,M8,11,0x8771f681) c=HH(c,d,a,b,M11,16,0x6d9d6122) d=HH(b,c,d,a,M14,23,0xfde5380c) a=HH(a,b,c,d,M1,4,0xa4beea44) b=HH(d,a,b,c,M4,11,0x4bdecfa9) c=HH(c,d,a,b,M7,16,0xf6bb4b60) d=HH(b,c,d,a,M10,23,0xbebfbc70) a=HH(a,b,c,d,M13,4,0x2b7ec6) b=HH(d,a,b,c,M0,11,0xeaa127fa) c=HH(c,d,a,b,M3,16,0xd4ef3085) d=HH(b,c,d,a,M6,23,0x04881d05) a=HH(a,b,c,d,M9,4,0xd9d4d039) b=HH(d,a,b,c,M12,11,0xe6db99e5) c=HH(c,d,a,b,M15,16,0x1fa27cf8) d=HH(b,c,d,a,M2,23,0xc4ac5665) 第四轮 a=II(a,b,c,d,M0,6,0xf4292244) b=II(d,a,b,c,M7,10,0x432aff97) c=II(c,d,a,b,M14,15,0xab9423a7) d=II(b,c,d,a,M5,21,0xfc93a039) a=II(a,b,c,d,M12,6,0x655b59c3) b=II(d,a,b,c,M3,10,0x8f0ccc92) c=II(c,d,a,b,M10,15,0xffeff47d) d=II(b,c,d,a,M1,21,0x85845dd1) a=II(a,b,c,d,M8,6,0x6fa87e4f) b=II(d,a,b,c,M15,10,0xfe2ce6e0) c=II(c,d,a,b,M6,15,0xa3014314) d=II(b,c,d,a,M13,21,0x4e0811a1) a=II(a,b,c,d,M4,6,0xf7537e82) b=II(d,a,b,c,M11,10,0xbd3af235) c=II(c,d,a,b,M2,15,0x2ad7d2bb) d=II(b,c,d,a,M9,21,0xeb86d391) 5)每轮循环后,将A,B,C,D分别加上a,b,c,d,然后进入下一循环。 报文摘要的产生后的形式为:A,B,C,D。也就是低位字节A开始,高位字节D结束。 2)代码 import java.util.*; public class MD5 { String hex_chr = \"01234567abcdef\"; private static Scanner input; private String rhex(int num) { String str = \"\"; for (int j = 0; j <= 3; j++) str = str + hex_chr.charAt((num >> (j * 8 + 4)) & 0x0F)+ hex_chr.charAt((num >> (j * 8)) & 0x0F); return str;} private int[] str2blks_MD5(String str) { int nblk = ((str.length() + 8) >> 6) + 1; int[] blks = new int[nblk * 16]; int i = 0; for (i = 0; i < nblk * 16; i++) {blks[i] = 0;} for (i = 0; i < str.length(); i++) {blks[i >> 2] |= str.charAt(i) << ((i % 4) * 8);} blks[i >> 2] |= 0x80 << ((i % 4) * 8); blks[nblk * 16 - 2] = str.length() * 8; return blks;} private int add(int x, int y) {return ((x & 0x7FFFFFFF) + (y & 0x7FFFFFFF)) ^ (x & 0x80000000)^ (y & 0x80000000);} private int rol(int num, int cnt) {return (num << cnt) | (num >>> (32 - cnt));} private int cmn(int q, int a, int b, int x, int s, int t) {return add(rol(add(add(a, q), add(x, t)), s), b);} private int ff(int a, int b, int c, int d, int x, int s, int t) {return cmn((b & c) | ((~b) & d), a, b, x, s, t);} private int gg(int a, int b, int c, int d, int x, int s, int t) {return cmn((b & d) | (c & (~d)), a, b, x, s, t);} private int hh(int a, int b, int c, int d, int x, int s, int t) {return cmn(b ^ c ^ d, a, b, x, s, t);} private int ii(int a, int b, int c, int d, int x, int s, int t) {return cmn(c ^ (b | (~d)), a, b, x, s, t);} public String calcMD5(String str) { int[] x = str2blks_MD5(str); int a = 0x67452301; int b = 0xEFCDAB; int c = 0x98BADCFE; int d = 0x10325476; for (int i = 0; i < x.length; i += 16) { int olda = a; int oldb = b; int oldc = c; int oldd = d; a = ff(a, b, c, d, x[i + 0], 7, 0xD76AA478); d = ff(d, a, b, c, x[i + 1], 12, 0xE8C7B756); c = ff(c, d, a, b, x[i + 2], 17, 0x242070DB); b = ff(b, c, d, a, x[i + 3], 22, 0xC1BDCEEE); a = ff(a, b, c, d, x[i + 4], 7, 0xF57C0FAF); d = ff(d, a, b, c, x[i + 5], 12, 0x4787C62A); c = ff(c, d, a, b, x[i + 6], 17, 0xA8304613); b = ff(b, c, d, a, x[i + 7], 22, 0xFD469501); a = ff(a, b, c, d, x[i + 8], 7, 0x698098D8); d = ff(d, a, b, c, x[i + 9], 12, 0x8B44F7AF); c = ff(c, d, a, b, x[i + 10], 17, 0xFFFF5BB1); b = ff(b, c, d, a, x[i + 11], 22, 0x5CD7BE); a = ff(a, b, c, d, x[i + 12], 7, 0x6B901122); d = ff(d, a, b, c, x[i + 13], 12, 0xFD987193); c = ff(c, d, a, b, x[i + 14], 17, 0xA679438E); b = ff(b, c, d, a, x[i + 15], 22, 0x49B40821); a = gg(a, b, c, d, x[i + 1], 5, 0xF61E2562); d = gg(d, a, b, c, x[i + 6], 9, 0xC040B340); c = gg(c, d, a, b, x[i + 11], 14, 0x265E5A51); b = gg(b, c, d, a, x[i + 0], 20, 0xE9B6C7AA); a = gg(a, b, c, d, x[i + 5], 5, 0xD62F105D); d = gg(d, a, b, c, x[i + 10], 9, 0x02441453); c = gg(c, d, a, b, x[i + 15], 14, 0xD8A1E681); b = gg(b, c, d, a, x[i + 4], 20, 0xE7D3FBC8); a = gg(a, b, c, d, x[i + 9], 5, 0x21E1CDE6); d = gg(d, a, b, c, x[i + 14], 9, 0xC33707D6); c = gg(c, d, a, b, x[i + 3], 14, 0xF4D50D87); b = gg(b, c, d, a, x[i + 8], 20, 0x455A14ED); a = gg(a, b, c, d, x[i + 13], 5, 0xA9E3E905); d = gg(d, a, b, c, x[i + 2], 9, 0xFCEFA3F8); c = gg(c, d, a, b, x[i + 7], 14, 0x676F02D9); b = gg(b, c, d, a, x[i + 12], 20, 0x8D2A4C8A); a = hh(a, b, c, d, x[i + 5], 4, 0xFFFA3942); d = hh(d, a, b, c, x[i + 8], 11, 0x8771F681); c = hh(c, d, a, b, x[i + 11], 16, 0x6D9D6122); b = hh(b, c, d, a, x[i + 14], 23, 0xFDE5380C); a = hh(a, b, c, d, x[i + 1], 4, 0xA4BEEA44); d = hh(d, a, b, c, x[i + 4], 11, 0x4BDECFA9); c = hh(c, d, a, b, x[i + 7], 16, 0xF6BB4B60); b = hh(b, c, d, a, x[i + 10], 23, 0xBEBFBC70); a = hh(a, b, c, d, x[i + 13], 4, 0x2B7EC6); d = hh(d, a, b, c, x[i + 0], 11, 0xEAA127FA); c = hh(c, d, a, b, x[i + 3], 16, 0xD4EF3085); b = hh(b, c, d, a, x[i + 6], 23, 0x04881D05); a = hh(a, b, c, d, x[i + 9], 4, 0xD9D4D039); d = hh(d, a, b, c, x[i + 12], 11, 0xE6DB99E5); c = hh(c, d, a, b, x[i + 15], 16, 0x1FA27CF8); b = hh(b, c, d, a, x[i + 2], 23, 0xC4AC5665); a = ii(a, b, c, d, x[i + 0], 6, 0xF4292244); d = ii(d, a, b, c, x[i + 7], 10, 0x432AFF97); c = ii(c, d, a, b, x[i + 14], 15, 0xAB9423A7); b = ii(b, c, d, a, x[i + 5], 21, 0xFC93A039); a = ii(a, b, c, d, x[i + 12], 6, 0x655B59C3); d = ii(d, a, b, c, x[i + 3], 10, 0x8F0CCC92); c = ii(c, d, a, b, x[i + 10], 15, 0xFFEFF47D); b = ii(b, c, d, a, x[i + 1], 21, 0x85845DD1); a = ii(a, b, c, d, x[i + 8], 6, 0x6FA87E4F); d = ii(d, a, b, c, x[i + 15], 10, 0xFE2CE6E0); c = ii(c, d, a, b, x[i + 6], 15, 0xA3014314); b = ii(b, c, d, a, x[i + 13], 21, 0x4E0811A1); a = ii(a, b, c, d, x[i + 4], 6, 0xF7537E82); d = ii(d, a, b, c, x[i + 11], 10, 0xBD3AF235); c = ii(c, d, a, b, x[i + 2], 15, 0x2AD7D2BB); b = ii(b, c, d, a, x[i + 9], 21, 0xEB86D391); a = add(a, olda); b = add(b, oldb); c = add(c, oldc); d = add(d, oldd); } return rhex(a) + rhex(b) + rhex(c) + rhex(d);} public static String MDString(String str) { MD5 md5 = new MD5(); return md5.calcMD5(str); } public static void main(String args[]) { String in = null; input = new Scanner(System.in); in = input.nextLine(); String s = MDString(in); System.out.println(s); } } 3)截图 实验小结:这个试验的编程让我学到了Hash函数的具体工作原理,并了解了其计算原理过程,让我能用所知的知识进行Hash函数的编程,编写出其加密和解密函数。并且运行程序成功。编写的时候有很多枯燥乏味的套用编写,但是为了最后程序的成功,我坚持下来了,短短的一个结果正是我的艰辛和努力。 实验五 公钥密码 一、实验目的 学习RSA密码的具体工作原理,能够了解其计算过程,并用所学的知识进行RSA密码的编程,编写出其加密和解密函数。并且运行程序成功。 二、实验内容: 1)过程: 1.使用publicKey可以对数据进行加密 2.使用Key才能对数据进行解密 用公钥加密的数据,只有私钥能解开(可用于加密);同时,使用私钥加密的数据,只有公钥能解开(签名)。但是速度很慢(比私钥加密慢100到1000倍),公钥的主要算法有RSA,还包括Blowfish,Diffie-Helman等。 一、公钥与私钥:权威数字认证机构(CA)给所有通信主体(个人或组织)颁发公钥和私钥,彼此配对,分别唯一。私钥好比数字指纹,同时具有解密和加密功能。个人保管,不公开。公钥好比安全性极高的挂号信箱地址,公开。 从以上步骤,我们知道: 1. 用公钥加密的密文能且只能用与其唯一配对的私钥才能解开。 2. 如果某份密文被解开,那么肯定是密文的目标信息主体解开的。 3. 私钥因其唯一标识所有者的属性,被用于数字签名,具有法律效力。 二、公私钥生成方法如下: 1.随机选定两个大素数p, q. 2.计算公钥和私钥的公共模数 n = pq . 3.计算模数n的欧拉函数 φ(n) . 4.选定一个正整数e, 使1 < e < φ(n) , 且e与φ(n)互质. 5.计算d, 满足 de ≡ 1 (mod φ(n) ), (k为某个正整数). 6.n与e决定公钥, n与d决定私钥. 三、加解密过程如下: 该过程为Alice给Bob发消息,公钥为Bob的公钥(n & e), 私钥为Bob的私钥(n & d). 1. Alice欲给Bob发一个消息M, 他先把M转换为一个大数m < n, 然后用Bob的公钥(n & e)把m加密为另一个大数: cmemodn 2. Bob收到Alice发来的大数c, 着手解密. 通过自己的私钥(n & d), 得到原来的大数m: mcdmodn 3.再把m转换为M, Bob即得到Alice的原始消息. 这个过程之所以能通过, 是因为有如下等式: cd(me)dmedmodn 2)代码: #include HugeInt Power( const HugeInt & x, const HugeInt & n, const HugeInt & p ) { if( n == 0 ) return 1; HugeInt tmp = Power( ( x * x ) % p, n / 2, p ); if( n % 2 != 0 ) tmp = ( tmp * x ) % p; return tmp;} template void fullGcd( const HugeInt & a, const HugeInt & b, HugeInt & x, HugeInt & y ) {HugeInt x1, y1; if( b == 0 ) {x = 1; y = 0;} else { fullGcd( b, a % b, x1, y1 ); x = y1; y = x1 - ( a / b ) * y1; }} template HugeInt inverse( const HugeInt & p, const HugeInt & q, const HugeInt & e ) { int fyn = ( 1 - p ) * ( 1 - q ); HugeInt x, y; fullGcd( fyn, e, x, y ); return x > 0 ? x : x + e;} int main( ) { cout <<\"Please input the plaintext: \"<< endl; int m; cin >> m; cout <<\"Please input p,q and e: \"<< endl; int p, q, e; cin >> p >> q >> e; int n = p * q; int d = inverse( p, q, e ); int C = Power( m, e, n ); cout <<\"The ciphertext is: \"<< C << endl; cout <<\"\\n\\nPlease input the ciphertext: \"<< endl; cin >> C; cout <<\"\\n\\nPlease input p, q and d: \"<< endl; cin >> p >> q >> d; n = p * q; m = Power( C, d, n ); cout <<\"The plaintext is: \"<< m << endl << endl; return 0;} 3)截图: 实验小结:公钥密码的学习让我掌握了相关知识,在编写过程中遇到了一些困难,但是在攻克来之后也让我获益良多。 实验心得:通过密码学课程设计,不仅巩固了课堂上学习的密码学理论知识,而且通过编写相关的程序增强自己的动手实践能力。在实验的后期遇到了很多难题,分组密码的理论与实践结合比较困难,但通过同学的帮助和在网络上查找资料最终解决了问题,这次实验让我获益良多,对于密码学有了一定的领悟,相信以后可以深入的学习密码学来不断充实自己的知识,增加自己的能力。 void JieMi(string m){ //解密 int k1,k2;
FF(a,b,c,d,Mj,s,ti)表示a=b+((a+F(b,c,d)+Mj+ti)<<GG(a,b,c,d,Mj,s,ti)表示a=b+((a+G(b,c,d)+Mj+ti)<<a=FF(a,b,c,d,M0,7,0xd76aa478) b=FF(d,a,b,c,M1,12,0xe8c7b756) c=FF(c,d,a,b,M2,17,0x242070db) d=FF(b,c,d,a,M3,22,0xc1bdceee) a=FF(a,b,c,d,M4,7,0xf57c0faf) b=FF(d,a,b,c,M5,12,0x4787c62a) c=FF(c,d,a,b,M6,17,0xa8304613) d=FF(b,c,d,a,M7,22,0xfd469501) a=FF(a,b,c,d,M8,7,0x698098d8) b=FF(d,a,b,c,M9,12,0x8b44f7af) c=FF(c,d,a,b,M10,17,0xffff5bb1) d=FF(b,c,d,a,M11,22,0x5cd7be) a=FF(a,b,c,d,M12,7,0x6b901122) b=FF(d,a,b,c,M13,12,0xfd987193) c=FF(c,d,a,b,M14,17,0xa679438e) d=FF(b,c,d,a,M15,22,0x49b40821) 第二轮
因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- huatuo0.cn 版权所有 湘ICP备2023017654号-2
违法及侵权请联系:TEL:199 18 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务