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