希尔密码(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}
原文地址:https://www.cnblogs.com/sysu-blackbear/p/3358124.html