zoukankan      html  css  js  c++  java
  • 希尔密码(Hill Cipher)的实现

    原理应该不用多讲了,自己百度就可以。

    C++实现:

      1 #include <iostream>
      2 #include <string>
      3 #include <memory.h>
      4 #include <cstdlib>
      5 #include <ctime>
      6 #include <cstdio>
      7 #include <cmath>
      8 using namespace std;
      9 
     10 //定义一些常变量
     11 const int M = 26;   //定义集合{a,b,...,z}的26个英文字母
     12 
     13 //行和列均为5
     14 const int ROW = 5;
     15 const int COL = 5;   
     16 
     17 //定义5*5的加密矩阵
     18 int K[ROW][COL];
     19 
     20 //定义5*5的解密矩阵
     21 int D[ROW][COL];
     22 
     23 int P[ROW];  //明文单元
     24 int C[ROW];  //密文单元
     25 int F[ROW];  //密文解密后的单元
     26 
     27 //三元组gcd(a,b) = ax + by = d
     28 struct GCD
     29 {
     30     int x;
     31     int y;
     32     int d;
     33 };
     34 
     35 class Hill_Cipher
     36 {
     37 public:
     38     //产生随机矩阵
     39     void random_Matrix();
     40     //求矩阵的行列式
     41     int Det(int matrix[ROW][ROW],int row);
     42 
     43     //求两个数的最大公约数
     44     int gcd(int a,int b);
     45 
     46     /*
     47      *判断矩阵K是否在模26的情况下可逆
     48      *因为矩阵在模26的情形下存在可逆矩阵的充分必要条件是
     49      *gcd(det K,26) = 1
     50      */
     51     bool Inverse(int matrix[ROW][ROW]);
     52 
     53     //矩阵相乘
     54     void multiphy(int matrix[ROW][ROW],int p[ROW],int row);
     55 
     56     //求出伴随矩阵
     57     void adjoint_matrix(int matrix[ROW][ROW],int row);
     58 
     59     //将明文加密为密文
     60     string encryption(string plaintext);
     61 
     62     //将密文解密为明文(为了辨识清楚,我们统一以小写字母作为明文,大写字母作为密文)
     63     string deciphering(string ciphertext);
     64 
     65     //欧几里得算法求模的逆
     66     GCD extended_Euclid(int a,int b);
     67 
     68     //模逆运算
     69     int inverse(int a,int m);
     70 
     71     //由于C++不存在负数取模的内置函数,现在自己设定一个
     72     //定义一个模M的值
     73     int Mod(int a);
     74 };
     75 
     76 void Hill_Cipher::random_Matrix()
     77 {
     78     int i,j;
     79     for(i = 0;i < ROW;i++)
     80     {
     81         for(j = 0;j < COL;j++)
     82         {  
     83             K[i][j] = rand() % 26;  //产生一个5*5模26的矩阵
     84         }
     85     }
     86     cout << "随机产生5*5的矩阵:" << endl;
     87     for(i = 0;i < ROW;i++)
     88     {
     89         for(j = 0;j < COL;j++)
     90         {
     91             printf("%2d  ",K[i][j]);
     92         }
     93         cout << endl;
     94     }
     95 }
     96 
     97 //求矩阵的行列式
     98 int Hill_Cipher::Det(int matrix[ROW][ROW],int row)
     99 {
    100     int i,j;            
    101     int cofa[ROW][ROW];            //用于存放余子阵
    102     int l;   //l为所递归的余子阵的行
    103     int p = 0,q = 0;
    104     int sum=0;
    105     
    106     //由于行和列相同(方阵),所以行列式的值一定存在,故不需要判断是否为方阵
    107     
    108     //递归基
    109     if(row == 1) 
    110         return matrix[0][0];
    111    for(i = 0;i < row; i++)
    112    {
    113      for(l = 0;l < row - 1;l++)
    114      {
    115        if(l < i)  
    116            p=0;
    117        else  
    118            p=1;
    119        for(j = 0;j< row - 1;j++)
    120        {
    121          cofa[l][j] = matrix[l + p][j + 1];
    122        }
    123      }
    124      //相当于(-1)^i
    125      if(i % 2 == 0)  
    126          q=1;
    127      else 
    128          q=(-1);
    129      sum = sum + matrix[i][0] * q * Det(cofa,row - 1);
    130    }
    131    return sum;
    132 }
    133 
    134 //求两个数的最大公约数
    135 int Hill_Cipher::gcd(int a,int b)
    136 {
    137     int temp;
    138     //交换两个数的大小,使得a为较大数
    139     if(a < b)
    140     {
    141         temp = a;
    142         a = b;
    143         b = temp;
    144     }
    145     while(a % b)
    146     {
    147         temp = b;
    148         b = a % b;
    149         a = temp;
    150     }
    151     return b;
    152 }
    153 
    154 /*
    155  *判断矩阵K是否在模26的情况下可逆
    156  *因为矩阵在模26的情形下存在可逆矩阵的充分必要条件是
    157  *gcd(det K,26) = 1
    158  */
    159 bool Hill_Cipher::Inverse(int matrix[ROW][ROW])
    160 {
    161     if(gcd(Det(matrix,ROW),M) == 1)
    162         return true;
    163     else
    164         return false;
    165 }
    166 
    167 void Hill_Cipher::multiphy(int matrix[ROW][ROW],int p[ROW],int row)
    168 {
    169     int i,j;
    170     //先将密文单元清零
    171     memset(C,0,sizeof(C));
    172     for(i = 0;i < ROW;i++)
    173     {
    174         for(j = 0;j < ROW;j++)
    175         {
    176             C[i] += P[j] * K[j][i];
    177         }
    178     }
    179 }
    180 
    181 //将明文加密为密文
    182 string Hill_Cipher::encryption(string plaintext)
    183 {
    184     int i;
    185     string ciphertext;
    186     //将字符串转化为明文数组
    187     for(i = 0;i < ROW;i++)
    188     {
    189         P[i] = plaintext[i] - 'a';
    190     }
    191     multiphy(K,P,ROW);
    192     //将密文数组转化为密文
    193     for(i = 0;i < ROW;i++)
    194         //这里先将其模26,再翻译为对应的字母
    195     {
    196         C[i] =Mod(C[i]);
    197         ciphertext += C[i] + 'A';
    198     }
    199     return ciphertext;
    200 }
    201 
    202 //求出伴随矩阵
    203 void Hill_Cipher::adjoint_matrix(int matrix[ROW][ROW],int row)
    204 {
    205     int i,j,k,l;
    206     int p,q;
    207     p = q = 0;
    208     int temp[ROW][ROW];
    209     for(i = 0;i < ROW;i++)
    210     {
    211         for(j = 0;j < ROW;j++)
    212         {
    213             for(k = 0;k < ROW - 1;k++)
    214             {
    215                 if(k < i)
    216                     p = 0;
    217                 else
    218                     p = 1;
    219                 for(l = 0;l < ROW - 1;l++)
    220                 {
    221                     if(l < j)
    222                         q = 0;
    223                     else
    224                         q = 1;
    225                     temp[k][l] = matrix[k+p][l+q];
    226                 }
    227             }
    228             D[j][i] = (int)pow(-1,(double)i+j)*Det(temp,ROW-1);
    229             D[j][i] = Mod(D[j][i]);
    230         }
    231     }
    232 }
    233 
    234 //将密文解密为明文(为了辨识清楚,我们统一以小写字母作为明文,大写字母作为密文)
    235 string Hill_Cipher::deciphering(string ciphertext)
    236 {
    237     //求出矩阵的逆
    238     string text;
    239     int determinant = Det(K,ROW);
    240     int inver = inverse(determinant,26);
    241     adjoint_matrix(K,ROW);   //伴随矩阵
    242     cout << "行列式的值: " << determinant << endl;
    243     int i,j;
    244     memset(F,0,sizeof(F));
    245     for(i = 0;i < ROW;i++)
    246     {
    247         for(j = 0;j < ROW;j++)
    248         {
    249             F[i] += C[j] * D[j][i];
    250         }
    251         F[i] *= inver;
    252         F[i] = Mod(F[i]);   //算到的结果要模去26
    253     }
    254     for(i = 0;i < ROW;i++)
    255         text += F[i] + 'a';
    256     return text;
    257 }
    258 
    259 GCD Hill_Cipher::extended_Euclid(int a,int b)
    260 {
    261     GCD aa,bb;
    262     if(b == 0)
    263     {
    264         aa.x = 1;
    265         aa.y = 0;
    266         aa.d = a;
    267         return aa;
    268     }
    269     else
    270     {
    271         bb = extended_Euclid(b,a%b);
    272         aa.x = bb.y;
    273         aa.y = bb.x - (a / b) * bb.y;
    274         aa.d = bb.d;
    275     }
    276     return aa;
    277 }
    278 
    279 int Hill_Cipher::inverse(int a,int m)
    280 {
    281     GCD aa;
    282     aa = extended_Euclid(a,m);
    283     return aa.x;
    284 }
    285 
    286 int Hill_Cipher::Mod(int a)
    287 {
    288     return a >= 0 ? a % M : (M + a % M);
    289 }
    290 
    291 int main()
    292 {
    293     int i,j;
    294     Hill_Cipher hh;
    295     cout << "使用希尔密码进行消息的加解密:" << endl;
    296 
    297     //srand()函数产生一个以当前时间开始的随机种子.以保证每次产生的随机数矩阵都不相同
    298     srand((unsigned)time(0));   
    299     hh.random_Matrix();
    300     while(!hh.Inverse(K))
    301     {
    302         cout << "该矩阵模26不可逆,不可以作为密钥!" << endl;
    303         cout << endl;
    304         hh.random_Matrix();
    305     }
    306     cout << "该矩阵模26可逆,因此可以作为密钥." << endl;
    307     cout << endl;
    308     
    309     //利用所选密钥,对给定的5元明文信息进行加解密
    310     string plaintext,ciphertext;
    311     cout << "请输入5元明文信息:" << endl;
    312     cin >> plaintext;
    313     ciphertext = hh.encryption(plaintext);
    314     cout << endl;
    315     cout << "该明文通过希尔密码法加密过后,输出的密文消息为:" << endl;
    316     cout << ciphertext << endl;
    317     cout << endl;
    318 
    319     cout << "***输入0:退出          ***" << endl;
    320     cout << "***输入1:查看明文空间对***" << endl;
    321     cout << "***输入2:查看密文空间对***" << endl;
    322     cout << "***输入3:查看密钥      ***" << endl;
    323     cout << "***输入4:将消息解密    ***" << endl;
    324     cout << "***输入5:查看菜单      ***" << endl;
    325 
    326     char c;
    327     while(cin >> c)
    328     {
    329         if(c == '0')
    330         {
    331             cout << endl;
    332             cout << "退出" << endl;
    333             break;
    334         }
    335         else if(c == '1')
    336         {
    337             cout << "明文空间:" << endl;
    338             for(i = 0;i < ROW;i++)
    339                 cout << P[i] << "  ";
    340             cout << endl;
    341             cout << endl;
    342         }
    343         else if(c == '2')
    344         {
    345             cout << "密文空间:" << endl;
    346             for(i = 0;i < ROW;i++)
    347                 cout << C[i] << "  ";
    348             cout << endl;
    349             cout << endl;
    350         }
    351         else if(c == '3')
    352         {
    353             cout << "密钥:" << endl;
    354             for(i = 0;i < ROW;i++)
    355             {
    356                 for(j = 0;j < ROW;j++)
    357                 {
    358                     printf("%2d  ",K[i][j]);
    359                 }
    360                 cout << endl;
    361             }
    362             cout << endl;
    363         }
    364         else if(c == '4')
    365         {
    366             hh.adjoint_matrix(K,ROW);
    367             string ss;
    368             ss = hh.deciphering(ciphertext);
    369             cout << "该密文解密过后,显示的原来的明文消息:" << endl;
    370             cout << ss << endl;
    371             cout << endl;
    372         }
    373         else
    374         {
    375             cout << "***输入0:退出          ***" << endl;
    376             cout << "***输入1:查看明文空间对***" << endl;
    377             cout << "***输入2:查看密文空间对***" << endl;
    378             cout << "***输入3:查看密钥      ***" << endl;
    379             cout << "***输入4:将消息解密    ***" << endl;
    380             cout << "***输入5:查看菜单      ***" << endl;
    381         }
    382     }
    383     return 0;
    384 }

    Mathematica 9.0实现:

     1 Print["请输入你要输入的5元明文数组:"];
     2 
     3 A = {}
     4 For[i = 0, i < 5, i++, AppendTo[A, Input[]]]
     5 
     6 请输入你要输入的5元明文数组:
     7 
     8 {}
     9 
    10 Print["请输入你要输入的5元明文数组:"];
    11 
    12 A = {}
    13 For[i = 0, i < 5, i++, AppendTo[A, Input[]]]
    14 
    15 Print["产生5*5的随机数组"];
    16 
    17 While[True, B = RandomInteger[{0, 25}, {5, 5}];
    18  If[Det[B] != 0, Break[]];]
    19 Print["A=", A]
    20 Print["B=", B]
    21 
    22 请输入你要输入的5元明文数组:
    23 
    24 {}
    25 
    26 产生5*5的随机数组
    27 
    28 A={1,2,3,4,5}
    29 
    30 B={{0,10,0,3,9},{22,18,0,17,4},{5,1,1,10,11},{8,8,13,16,15},{10,9,23,21,5}}
    31 
    32 
    33 
    34 
    35 d = A.B
    36 
    37 {141, 126, 170, 236, 135}
    38 
    39 Print["d=", d]
    40 
    41 d={141,126,170,236,135}
    42 
    43 e = Mod[d, 26]
    44 Print["加密后的密文为:", e]
    45 
    46 {11, 22, 14, 2, 5}
    47 
    48 加密后的密文为:{11,22,14,2,5}
    49 
    50 f = d.Inverse[B]
    51 
    52 Print["解密后的密文为:", f]
    53 
    54 {1, 2, 3, 4, 5}
    55 
    56 解密后的密文为:{1,2,3,4,5}
  • 相关阅读:
    windos下安装多个mysql服务
    mysql 提示too many connections”的解决办法
    python打包成exe
    对于点击后需要等待一段时间才会有的元素的操作
    python自动化报错
    自动化测试中对不能输入的框体的处理
    对于下拉框的处理方法
    selenium自动化遇见Cannot find class in classpath问题
    企业如何留住人才
    如何成为一名优秀的前端工程师
  • 原文地址:https://www.cnblogs.com/sysu-blackbear/p/3358124.html
Copyright © 2011-2022 走看看