您好,欢迎来到华佗小知识。
搜索
您的当前位置:首页密码学课程设计

密码学课程设计

来源:华佗小知识
中国矿业大学计算机学院

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 #include using namespace std;

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;ifor(i=0;i{cout<void JieMi(string m){ //解密 int k1,k2;

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 using namespace std;

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<bool x[8]={1,0,1,0,0,1,1,0}; //初始状态 for(int i=0;i<8;i++) 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 #include #include #define ENCRYPT 1 #define DECRYPT 0

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; ivoid Transform ( bool *Out, bool *In, const char *Table, int len ) { int i; static bool tmp[256];

for ( i=0; ivoid Xor ( bool *InA, const bool *InB, int len ) { int i; for ( i=0; ivoid RotateL ( bool *In, int len, int loop ) { static bool tmp[256]; // Sample: loop=2 memcpy ( tmp, In, loop ); // In=12345678 tmp=12 memcpy ( In, In+loop, len-loop ); // In=345678 memcpy ( In+len-loop, tmp, loop ); // In=34567812 }

// 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> ( i%8 ) ) & 1; } }

void BitToByte ( char *Out, const bool *In, int bits ) { int i;

memset ( Out, 0, ( bits+7 ) /8 ); for ( i=0; i2)截图

实验小结:这个实验我学习了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),<<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) 第二轮

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加密为另一个大数:

cmemodn

2. Bob收到Alice发来的大数c, 着手解密. 通过自己的私钥(n & d), 得到原来的大数m: mcdmodn

3.再把m转换为M, Bob即得到Alice的原始消息. 这个过程之所以能通过, 是因为有如下等式:

cd(me)dmedmodn

2)代码:

#include using namespace std; template

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)截图:

实验小结:公钥密码的学习让我掌握了相关知识,在编写过程中遇到了一些困难,但是在攻克来之后也让我获益良多。

实验心得:通过密码学课程设计,不仅巩固了课堂上学习的密码学理论知识,而且通过编写相关的程序增强自己的动手实践能力。在实验的后期遇到了很多难题,分组密码的理论与实践结合比较困难,但通过同学的帮助和在网络上查找资料最终解决了问题,这次实验让我获益良多,对于密码学有了一定的领悟,相信以后可以深入的学习密码学来不断充实自己的知识,增加自己的能力。

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- huatuo0.cn 版权所有 湘ICP备2023017654号-2

违法及侵权请联系:TEL:199 18 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务