希爾密碼(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}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM