原理應該不用多講了,自己百度就可以。
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}