密码学课程设计

 中国矿业大学计算机学院

 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)

仿射密码具有可逆性的条件是gcd(k1, n)=1。当k1=1时,仿射密码变为加法密码,当k2=0时,仿射密码变为乘法密码。

仿射密码中的密钥空间的大小为nφ(n),当n为26字母,φ(n)=12,因此仿射密码的密钥空间为12×26 = 312。

1)代码:

#include<iostream>

#include<string>

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;i<m.length();i++)

         {   tmp=Number(p[i]);

                   c1=tmp*k1+k2;

                   c2=c1%26;

                   q[i]=v[c2-1];}

         for(i=0;i<m.length();i++)

         {cout<<q[i]<<" ";}

         cout<<endl;}

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<m.length();i++)

         {for(j=0;j<26;j++)

                   {        tmp=Number(l[j]);

                       c1=tmp*k1+k2;

                       c2=c1%26;

                            if(v[c2-1]==p[i]){q[i]=l[j];break;}}}

         for(i=0;i<m.length();i++)

         {cout<<q[i]<<" ";}

         cout<<endl;}

int main(){

         string m;

         JiaMi(m);

         JieMi(m);

         return 0;}

2)截图:

实验小结:这个实验我学习仿射密码的具体工作原理,理解了仿射密码的计算过程,在根据所知的知识理解后进行放射密码的编程,编写出其加密和解密函数。运行程序进行实践。仿射密码是比较简单的一个试验了,但是也让我学习了很多。

实验二:序列密码

一、实验目的

学习线性反馈移位寄存器的具体工作原理,了解其计算方法步骤,并根据所知的知识进行线性反馈移位寄存器的编程,能够编写出其加密和解密函数。并且运行程序成功。

二、实验内容

1)代码

#include<iostream>

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<<x;}

int main()

{ int n=1;

bool x[8]={1,0,1,0,0,1,1,0};               //初始状态

                            for(int i=0;i<8;i++)

                            cout<<x[i];

         do{n++;

                   yiwei(x);

         }while((x[0]&&(!x[1])&&x[2]&&(!x[3])&&(!x[4])&&x[5]&&x[6]&&(!x[67]))==false);

cout<<"  "<<"T="<<n<<endl;

return 0;}

2)截图

实验小结:通过这一个实验的编程与学习,我学习了线性反馈移位寄存器的具体工作原理,并清晰了解其计算方法步骤,在根据所知的知识进行实践编写线性反馈移位寄存器的代码,能够编写出其加密和解密函数。并且能运行程序成功。这个实验比较短小,但是也汇聚了平时所学与实践的结合,我也在实验的过程中学到来很多。

实验三:分组密码

一、实验目的

学习DES的具体工作原理,了解其计算方法步骤,并根据所学的知识进行DES的编程,编写出其加密和解密函数。并且运行程序成功。

实验内容

1)过程:

DES算法的入口参数有三个:

 Key, Data, Mode

Key 为64bit密钥, Data为64bit数据,Mode为加密还是解密。

DES算法的过程:

1. 对输入的密钥进行变换。

    用户的64bit密钥,其中第8, 16, 24, 32, 40, 48, 56, 64位是校验位, 使得每个密钥都有奇数个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. 对64bit的明文输入进行换位变换。换位表如下:

58, 50, 12, 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

表的意思就是第一次变换时,第58位移到第1位,第50位移到第2位,...... 依此类推。得到64位数据,将这数据前后分成两块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合并成64位,然后进行如下转化得到最后的结果。这是对第4步的一个逆变化。

 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

以上是Des的加密过程,解密过程同样,只需要把16个子密钥K[i][48]的顺序颠倒过来就行了。

代码:

#include <stdlib.h>

#include <stdio.h>

#include <string.h>

#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];

// 64位经过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)  void F_func

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,

         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[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

};

// L16与R16合并后经过IP_1的最终排列 (IP**-1)

const static char IPR_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

};

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",&str);

         printf ( "Before encrypting: " );

         puts ( str );

         Des_SetKey ( key );

         memset ( str2, 0, sizeof ( str2 ) );

         Des_Run ( str2, str, ENCRYPT );

         printf ( "After  encrypting: " );

         //printf("%s\n",str2);

         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[64], *KL = &K[0], *KR = &K[28];

         ByteToBit ( K, Key, 64 );   //转换为二进制

         Transform ( K, K, PC1_Table, 56 );   //64比特的密钥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[64], tmp[32], *Li = &M[0], *Ri = &M[32];

         //转换为64位的数据块

         ByteToBit ( M, In, 64 );

         //IP置换 (初始)

         Transform ( M, M, IP_Table, 64 );

         //该比特串被分为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合并成64位的比特串。R16一定要排在L16前面。R16与L16合并后成的比特串,经过置换IP-1后所得的比特串就是密文。

         Transform ( M, M, IPR_Table, 64 );

         BitToByte ( Out, M, 64 );

}

//将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<len; i++ )

         {

                   printf ( "[%02X]", ( unsigned char ) cmd[i] );

         }

         printf ( "\n" );

}

// 打印数组测试用

static void printArray ( const char *In, int len )

{

         int   i;

         char tmp[256];

         memset ( tmp, 0, sizeof ( tmp ) );

         for ( i=0; i<len; i++ )

         {

                   tmp[ ( int ) In[i]]=In[i];

         }

         for ( i=0; i<len; i++ )

         {

                   printf ( "[%02d]", ( unsigned char ) tmp[i] );

         }

         printf ( "\n" );

}

void Transform ( bool *Out, bool *In, const char *Table, int len )

{

         int i;

         static bool tmp[256];

         for ( i=0; i<len; i++ )

         {

                   tmp[i] = In[ Table[i]-1 ];

         }

         memcpy ( Out, tmp, len );

}

void Xor ( bool *InA, const bool *InB, int len )

{

         int i;

         for ( i=0; i<len; i++ )

         {

                   InA[i] ^= InB[i];

         }

}

void 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<bits; i++ )

         {

                   // In[i]的第N位右移N位并和0x01按位"与"运算(N=1~8)

                   Out[i] = ( In[i/8]>> ( i%8 ) ) & 1;

         }

}

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

{

         int i;

         memset ( Out, 0, ( bits+7 ) /8 );

         for ( i=0; i<bits; i++ )

         {

                   Out[i/8] |= In[i]<< ( i%8 );

         }

}

2)截图

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

     第二步、记录信息长度:用64位来存储填充前信息长度。这64位加在第一步结果的后面,这样信息长度就变为N*512+448+64=(N+1)*512位。

     第三步、装入标准的幻数(四个整数):标准的幻数(物理顺序)是(A=(01234567)16,B=(89ABCDEF)16,C=(FEDCBA98)16,D=(76543210)16)。如果在程序中定义应该是(A=0X67452301L,B=0XEFCDAB89L,C=0X98BADCFEL,D=0X10325476L)。

     第四步、四轮循环运算:循环的次数是分组的个数(N+1) 

     1)将每一512字节细分成16个小组,每个小组64位(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),<<<s表示循环左移s位,则四种操作为:

  FF(a,b,c,d,Mj,s,ti)表示a=b+((a+F(b,c,d)+Mj+ti)<<<s)

  GG(a,b,c,d,Mj,s,ti)表示a=b+((a+G(b,c,d)+Mj+ti)<<<s)

  HH(a,b,c,d,Mj,s,ti)表示a=b+((a+H(b,c,d)+Mj+ti)<<<s)

  II(a,b,c,d,Mj,s,ti)表示a=b+((a+I(b,c,d)+Mj+ti)<<<s)

    4)四轮运算

第一轮

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,0x895cd7be)

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,0x289b7ec6)

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 = "0123456789abcdef";

         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 = 0xEFCDAB89;

                   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, 0x895CD7BE);

                            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, 0x289B7EC6);

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

                            

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

                          

3.再把m转换为M, Bob即得到Alice的原始消息.

这个过程之所以能通过, 是因为有如下等式:

                             

2)代码:

#include <iostream>

using namespace std;

template <class HugeInt>

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 <class HugeInt>

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 <class HugeInt>

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

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

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

相关推荐