当前位置:   article > 正文

希尔密码(原理+代码)_hill密码原理

hill密码原理

目录

希尔密码

1、原理

2、流程图

3、编程实现

4、总结


希尔密码

1、原理

        希尔密码是一种运用基本矩阵论原理的代换密码,由Lester S. Hill在1929年发明。

        首先将字母转换为数字,将字母分成多个n维向量,跟一个n×n的矩阵相乘,再将得出的结果模26。需要注意的是密钥矩阵必须是可逆的,即矩阵的行列式和26互质。

        Hill密码能较好地抵抗统计分析法,对抗唯密文攻击的强度较高,但易受到已知明文攻击。

2、流程图

3、编程实现

        难点:如何根据密钥矩阵求密钥逆矩阵

        行列式可逆的充分条件:方阵的行列式不等于零 在这里行列式的值还需要和26互质 矩阵求逆可以使用伴随矩阵法LU分解法

        为了减少计算量和实现难度,这里使用3*3的密钥矩阵。同时伴随矩阵法求逆一般使用下面公式

                                                                        K^{-1}=d^{-1}\times adj(K)(行列式值的逆乘以伴随矩阵)

        参考:希尔密码  矩阵求逆

        具体代码如下:

        默认输入小写英文字母明文不带空格,以及3*3的密钥矩阵存在逆矩阵且为正整数。(因为这样实现简单。。。)

        主函数:

  1. #include"Hill.h"
  2. int main() {
  3. while (1) {
  4. show(); //菜单界面
  5. keyDown(); //按键处理
  6. system("pause");
  7. system("cls");
  8. }
  9. }

          Hill.h

  1. #pragma once
  2. #include<cstdio>
  3. #include<iostream>
  4. #include<cstring>
  5. #include<Windows.h>
  6. #include<vector>
  7. using namespace std;
  8. void init();
  9. void show();
  10. void keyDown();
  11. void readFile();
  12. void saveFile();
  13. void encrypt();
  14. void decrypt();
  15. int gcd(int a, int b, int& x, int& y);
  16. int getInv(int a, int m);
  17. void getAntiKey(int key[][3]);

        Hill.cpp 

  1. #include "Hill.h"
  2. string fileStr = "";
  3. string finalStr = "";
  4. int x = 0, y = 0;
  5. int antikey[3][3];//密钥的逆
  6. int key[3][3];//密钥
  7. /*
  8. 0 11 15
  9. 7 0 1
  10. 4 19 0
  11. */
  12. void init()//初始化
  13. {
  14. x = 0;
  15. y = 0;
  16. fileStr = "";
  17. finalStr = "";
  18. memset(antikey, 0, sizeof(antikey));
  19. memset(key, 0, sizeof(key));
  20. }
  21. void show()
  22. {
  23. cout << "*****************希尔密码*****************" << endl;
  24. cout << "\t\t1.加密文件" << endl;
  25. cout << "\t\t2.解密文件" << endl;
  26. cout << "\t\t3.退出" << endl;
  27. cout << "******************************************" << endl;
  28. }
  29. void keyDown()//按键处理
  30. {
  31. int userkey = 0;
  32. cin >> userkey;
  33. switch (userkey) {
  34. case 1:
  35. cout << "-----------------加密文件-----------------" << endl;
  36. readFile();
  37. encrypt();
  38. saveFile();
  39. init();
  40. break;
  41. case 2:
  42. cout << "-----------------解密文件-----------------" << endl;
  43. readFile();
  44. decrypt();
  45. saveFile();
  46. init();
  47. break;
  48. case 3:
  49. exit(0);
  50. break;
  51. }
  52. }
  53. void readFile()//读取文件
  54. {
  55. cout << "请输入文件名:" << endl;
  56. string fileName;
  57. cin >> fileName;
  58. FILE* fp = fopen(fileName.c_str(), "r+");
  59. if (fp == nullptr) {
  60. cout << "未找到相关文件" << endl;
  61. return;
  62. }
  63. else {
  64. cout << "成功打开文件" << endl;
  65. }
  66. char ch;
  67. int pos = 0;
  68. while ((ch = fgetc(fp)) != EOF) {
  69. fileStr += ch;
  70. }
  71. cout << endl << "待处理的文件为:" << endl;
  72. cout << fileStr << endl;
  73. fclose(fp);
  74. }
  75. void saveFile()//保存文件
  76. {
  77. string fileName;
  78. cout << endl << "请输入要保存信息的文件名:" << endl;
  79. cin >> fileName;
  80. FILE* fp = fopen(fileName.c_str(), "w+");
  81. if (fp == nullptr) {
  82. cout << endl << "保存文件失败" << endl;
  83. return;
  84. }
  85. else {
  86. cout << endl << "保存成功" << endl;
  87. }
  88. fprintf(fp, "%s", finalStr.c_str());
  89. fclose(fp);
  90. }
  91. void encrypt()//加密文件
  92. {
  93. vector< vector<int> > c;//明文矩阵
  94. vector< vector<int> > a;//密文矩阵
  95. if (fileStr.size() % 3 == 1)fileStr += "xx";//补充两个
  96. if (fileStr.size() % 3 == 2)fileStr += "x";
  97. int* m = new int[fileStr.size()];//明文按列分组并转化为数字
  98. //分成多个3个字母的列向量
  99. for (int i = 0; i < fileStr.size(); i++) {
  100. m[i] = fileStr[i] - 'a';
  101. }
  102. for (int i = 0; i < fileStr.size(); i += 3) {
  103. vector<int> temp = { m[i],m[i + 1],m[i + 2] };
  104. c.push_back(temp);
  105. }
  106. cout << endl << "明文矩阵为:" << endl;
  107. for (int i = 0; i < 3; i++) {
  108. for (int j = 0; j < c.size(); j++) {
  109. cout << c[j][i] << " ";//明文矩阵
  110. }
  111. cout << endl;
  112. }
  113. cout << endl;
  114. for (int i = 0; i < 3; i++) {
  115. for (int j = 0; j < c.size(); j++) {
  116. cout << char(c[j][i] + 97) << " ";//明文矩阵
  117. }
  118. cout << endl;
  119. }
  120. cout << endl;
  121. cout << "请输入密钥矩阵(默认矩阵可逆且为整数)" << endl;
  122. for (int i = 0; i < 3; i++) {
  123. for (int j = 0; j < 3; j++) {
  124. cin >> key[i][j];
  125. }
  126. }
  127. cout << endl << "按下任意键进行加密" << endl;
  128. char ch = getchar(); ch = getchar();
  129. //矩阵乘法
  130. for (int i = 0; i < c.size(); i++) {//矩阵的列数
  131. vector<int> temp;
  132. for (int j = 0; j < 3; j++) {
  133. int pos = 0;
  134. for (int k = 0; k < 3; k++) {
  135. pos += key[j][k] * c[i][k];
  136. }
  137. temp.push_back((pos) % 26);
  138. }
  139. a.push_back(temp);
  140. }
  141. cout << "密文矩阵" << endl;
  142. for (int i = 0; i < 3; i++) {
  143. for (int j = 0; j < a.size(); j++) {
  144. cout << a[j][i] << " ";//密文矩阵
  145. }
  146. cout << endl;
  147. }
  148. cout << endl;
  149. for (int i = 0; i < a.size(); i++) {
  150. for (int j = 0; j < a[0].size(); j++) {
  151. finalStr += char(a[i][j] + 97);
  152. }
  153. }
  154. delete[]m;
  155. cout << endl << "得到的密文为:" << endl;
  156. cout << finalStr << endl;
  157. }
  158. void decrypt()//解密文件
  159. {
  160. vector< vector<int> > c;//密文矩阵
  161. vector< vector<int> > a;//明文矩阵
  162. int* m = new int[fileStr.size()];//密文按列分组并转化为数字
  163. //分成多个3个字母的列向量
  164. for (int i = 0; i < fileStr.size(); i++) {
  165. m[i] = fileStr[i] - 'a';
  166. }
  167. for (int i = 0; i < fileStr.size(); i += 3) {
  168. vector<int> temp = { m[i],m[i + 1],m[i + 2] };
  169. c.push_back(temp);
  170. }
  171. cout << endl << "密文矩阵为:" << endl;
  172. for (int i = 0; i < 3; i++) {
  173. for (int j = 0; j < c.size(); j++) {
  174. cout << c[j][i] << " ";//密文矩阵
  175. }
  176. cout << endl;
  177. }
  178. cout << endl;
  179. for (int i = 0; i < 3; i++) {
  180. for (int j = 0; j < c.size(); j++) {
  181. cout << char(c[j][i] + 97) << " ";//密文矩阵
  182. }
  183. cout << endl;
  184. }
  185. cout << endl;
  186. cout << "请输入密钥矩阵(默认矩阵可逆且为整数)" << endl;
  187. for (int i = 0; i < 3; i++) {
  188. for (int j = 0; j < 3; j++) {
  189. cin >> key[i][j];
  190. }
  191. }
  192. getAntiKey(key);//求逆矩阵
  193. cout << endl << "成功求出密钥矩阵的逆" << endl;
  194. //密钥矩阵的逆矩阵
  195. for (int i = 0; i < 3; i++) {
  196. for (int j = 0; j < 3; j++) {
  197. cout << antikey[i][j] << " ";
  198. }
  199. cout << endl;
  200. }
  201. cout << endl << "按下任意键进行解密" << endl;
  202. char ch = getchar(); ch = getchar();
  203. //矩阵乘法
  204. for (int i = 0; i < c.size(); i++) {//矩阵的列数
  205. vector<int> temp;
  206. for (int j = 0; j < 3; j++) {
  207. int pos = 0;
  208. for (int k = 0; k < 3; k++) {
  209. pos += antikey[j][k] * c[i][k];
  210. }
  211. temp.push_back((pos) % 26);
  212. }
  213. a.push_back(temp);
  214. }
  215. cout << "解密后的矩阵" << endl;
  216. for (int i = 0; i < 3; i++) {
  217. for (int j = 0; j < a.size(); j++) {
  218. cout << a[j][i] << " ";
  219. }
  220. cout << endl;
  221. }
  222. cout << endl;
  223. for (int i = 0; i < a.size(); i++) {
  224. for (int j = 0; j < a[0].size(); j++) {
  225. finalStr += char(a[i][j] + 97);
  226. }
  227. }
  228. delete[]m;
  229. cout << endl << "得到的明文为:" << endl;
  230. cout << finalStr << endl;
  231. }
  232. int gcd(int a, int b, int& x, int& y)//求最大公约数
  233. {
  234. if (b == 0) {
  235. x = 1;
  236. y = 0;
  237. return a;
  238. }
  239. int g = gcd(b, a % b, x, y);
  240. int temp = x;
  241. x = y;
  242. y = temp - (a / b) * y;
  243. return g;
  244. }
  245. int getInv(int a, int m)//求乘法逆元
  246. {
  247. gcd(a, m, x, y);
  248. return (x % m + m) % m;
  249. }
  250. void getAntiKey(int key[][3]) {
  251. //求行列式值
  252. int v1 = key[0][0] * (key[1][1] * key[2][2] - key[1][2] * key[2][1]);
  253. int v2 = -key[0][1] * (key[1][0] * key[2][2] - key[2][0] * key[1][2]);
  254. int v3 = key[0][2] * (key[1][0] * key[2][1] - key[1][1] * key[2][0]);
  255. //cout<<v1<<" "<<v2<<" "<<v3<<endl;
  256. int d = (v1 + v2 + v3) % 26;
  257. //cout<<d<<endl;
  258. int dinv = getInv(d, 26);
  259. //cout<<dinv<<endl;
  260. //求伴随矩阵
  261. int temp[4];
  262. for (int i = 0; i < 3; i++) {
  263. for (int j = 0; j < 3; j++) {
  264. memset(temp, 0, sizeof(temp));
  265. int pos = 0;
  266. for (int x = 0; x < 3; x++) {
  267. for (int y = 0; y < 3; y++) {
  268. if (x != i && y != j) {
  269. temp[pos++] = key[x][y];
  270. }
  271. }
  272. }
  273. int cur = pow(-1, i + 1 + j + 1) * (temp[0] * temp[3] - temp[2] * temp[1]);
  274. antikey[j][i] = (dinv * (cur % 26 + 26)) % 26;
  275. }
  276. }
  277. }

4、总结

        通过采用线性代数中的矩阵乘法运算和逆运算,能够较好地抵抗频率分析,很难被攻破。当加密矩阵的阶数n越大,破译的难度就会增大,此时计算量也大。

        希尔密码体系为破译者至少设置了三道关口,加大了破译难度。破译希尔密码的关键是猜测文字被转换成几维向量(列矩阵的行数)、所对应的字母表是怎样排列的,更为重要的是要设法获取加密矩阵A。要破解密码,向量的维数、字母的排列表和加密矩阵三者缺一不可。(百度百科)

声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号