*欢迎阅读小明哥的博客*
这里主要介绍的是:古典密码之 hill密码加密解密过程的编程实现。
首先,请看对我对hill密码做的简单介绍。
hill密码是古典密码中多表代换密码部分的重要一环,以下的介绍节选自百度,想要深入了解的请查阅书籍补充相关知识。
原理:希尔密码(Hill Password)是运用基本矩阵论原理的替换密码,由Lester S. Hill在1929年发明。每个字母当作26进制数字:A=0, B=1, C=2... 一串字母当成n维向量,跟一个n×n的矩阵相乘,再将得出的结果模26。注意用作加密的矩阵(即密匙)在\mathbb_^n必须是可逆的,否则就不可能译码。只有矩阵的行列式和26互质,才是可逆的。
需要的知识储备:
1)线性代数基础知识.
2) 初等数论基础知识.
约定:
1)希尔密码常使用Z26字母表,在此贴中,我们也以Z26最为字母表进行讲解.在附带源码中有两种字母表选择.
2) 大家都知道最小的质数是2,1 既不是质数也不是合数. 在此我们定义1对任何质数的模逆为其本身.
因为对于任意质数n,有: 1*1 % n = 1 的. 也应该是很好理解的.
过程:
1)加密:密文=明文*密钥矩阵 (注:明文要被分割成与密钥维数相同的一维行列式)
2)解密:明文=密文*密钥矩阵的逆 (注:要求与加密过程相同)
加密解密过程如下图:
例:
加密过程:
解密:
对上述过程进行编程,主要的函数声明如下:
/* * * 头文件名称:hillcrypto.h * 实现文件名称:hillcrypto.cpp * 项目名称:多表代换密码之hill密码 * 作者:邹明 * 完成时间:2016.3.14 * */ #ifndef __HILLCRTPTO_H__ #define __HILLCRTPTO_H__ #includeusing namespace std; #include #include #define ROW 4 //密钥行数为4 #define COV 4 //密钥列数为4 void InputKeys(float keys[ROW][COV]); //输入密钥 void InputWords(char *words); //输入明文 void InputObwords(char *words); //输入密文 void PopKeys(float keys[ROW][COV]); //输出密钥 void Encryption(float keys[ROW][COV], char *words, char *crypto); //明文加密 void Decode(float keys[ROW][COV], char *words, char *crypto); //密文解密 bool Gauss(float A[ROW][COV], float B[ROW][COV], int n); //高斯消去法求逆矩阵 void ObMatrix(float a[ROW][COV], float b[ROW][COV], int n); //求密钥逆矩阵 void menu(); //菜单 #endif
函数实现过程中的主函数实现以及菜单函数实现如下:
/* 实现文件名称:hillcrypto.cpp */ #include"hillcrypto.h" int main() { menu(); //菜单+选择 system("pause"); return 0; } void menu() { float keys[ROW][COV] = { 8, 6, 9, 5, 6, 9, 5, 10, 5, 8, 4, 9, 10, 6, 11, 4 }; //加密矩阵(默认密钥) float obkeys[ROW][COV] = { 0 }; //解密矩阵 (密钥逆矩阵) char words[100] = { 0 }; char crypto[100] = { 0 }; char obwords[100] = { 0 }; bool flag = true; //菜单选择 bool chose = false; //密钥选择 char cn = 0; while (flag) { int n = 0; cout << endl; cout << "\t~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" << endl; cout << "\t\t\t1.输入密钥" << endl; cout << "\t\t\t2.明文加密" << endl; cout << "\t\t\t3.密文解密" << endl; cout << "\t\t\t4.退出" << endl << endl; cout << "\t~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" << endl; cout << "请选择->:"; cin >> n; switch (n) { case 1: system("cls"); cout << "默认密钥为:"; PopKeys(keys); cout << "请问您要重新输入密钥? y/n" << endl << "请选择->:"; cin >> cn; if ((cn == 'y') || (cn == 'Y')) { InputKeys(keys); //输入密钥 } else if ((cn == 'n') || (cn == 'N')) { cout << "感谢您选择使用默认密钥!" << endl; } else cout << "输入有误,请重新选择!" << endl; system("pause"); break; case 2: system("cls"); InputWords(words); //输入明文 Encryption(keys, words, crypto); //加密 cout << "密文是->:" << crypto << endl; system("pause"); break; case 3: system("cls"); InputObwords(crypto); //输入密文 ObMatrix(keys, obkeys, COV); //计算解密矩阵 Decode(obkeys, obwords, crypto); //解密 cout << "明文是->:" << obwords << endl; system("pause"); break; case 4: system("cls"); cout << endl << endl << endl; cout << setw(15) << "谢谢使用!" << endl; flag = false; system("pause"); break; default: cout << "选择有误,请重新选择!" << endl; system("pause"); break; } } }
输入明文函数和输入密文函数:
void InputWords(char *words) //输入明文 { assert(words); cout << "请输入明文:"; char *start = words; int flag = 1; getchar(); while (flag) { *words = getchar(); words++; if (*(words - 1) == '\n') { *words = '\0'; flag = 0; } } words = start; while (*start) { if (('A' <= *start) && (*start <= 'Z')) { *words = *start; words++; } else if (('a' <= *start) && (*start <= 'z')) { *words = *start - 32; words++; } start++; } *words = '\0'; cout << "输入成功 !" << endl; } void InputObwords(char *words) //输入密文 { assert(words); cout << "请输入密文:"; char *start = words; int flag = 1; getchar(); while (flag) { *words = getchar(); words++; if (*(words - 1) == '\n') { *words = '\0'; flag = 0; } } words = start; while (*start) { if (('A' <= *start) && (*start <= 'Z')) { *words = *start; words++; } else if (('a' <= *start) && (*start <= 'z')) { *words = *start - 32; words++; } start++; } *words = '\0'; cout << "输入成功 !" << endl; }
输入密钥与输出密钥函数:
void InputKeys(float keys[ROW][COV]) //输入密钥 { cout << "请输入密钥:" << endl; for (size_t i = 0; i < ROW; i++) { cout << "请输入第" << i << "行密钥("<> keys[i][j]; } } cout << "输入成功 !" << endl; } void PopKeys(float keys[ROW][COV]) //输出密钥 { cout << "密钥为:" << endl; for (size_t i = 0; i < ROW; i++) { for (size_t j = 0; j < COV; j++) { cout << keys[i][j] << " "; } cout << endl; } }
加密函数:
void Encryption(float keys[ROW][COV], char *words, char *crypto) //加密函数 { assert(words); int len = strlen(words); char *start = words; while (len > 0) { int matrix[ROW] = { 0 }; for (int i = 0; i < ROW; i++) { if (*start) matrix[i] = *start - 'A'; else matrix[i] = 0; start++; } len -= ROW; int cry[ROW] = { 0 }; for (int i = 0; i < ROW; i++) { int temp = 0; for (int j = 0; j < COV; j++) { temp = matrix[j] * keys[j][i] + temp; } cry[i] = temp % 26; *crypto = 'A' + cry[i]; //计算密文 crypto++; } } }
解密函数,以及求逆矩阵函数:
void Decode(float obkeys[ROW][COV], char *words, char *crypto)//解密函数 { assert(crypto); int len = strlen(crypto); char *start = crypto; while (len > 0) { int matrix[ROW] = { 0 }; for (int i = 0; i < ROW; i++) { if (*start) matrix[i] = *start - 'A'; else matrix[i] = 0; start++; } len -= ROW; int cry[ROW] = { 0 }; for (int i = 0; i < ROW; i++) { int temp = 0; for (int j = 0; j < COV; j++) { temp = matrix[j] * obkeys[j][i] + temp; } cry[i] = temp % 26; *words = 'A' + cry[i]; //计算明文 words++; } } } void ObMatrix( float a[ROW][COV], float b[ROW][COV], int n) //求逆矩阵函数 { int i, j; //定义矩阵的行列式 if (Gauss(a, b, n)) { cout << "该方阵的逆矩阵为: \n"; for (i = 0; i < n; i++) { cout << setw(4); for (j = 0; j < n; j++) { int temp =b[i][j]/ 1; float num = b[i][j] - temp; if (fabs(num) < 0.50) b[i][j] = (int)temp; else b[i][j] = temp + (int)(num * 2); cout << b[i][j] << setw(10); } cout << endl; } } cout << "逆矩阵(mod26):" << endl; for (int i = 0; i < ROW; i++) { cout << setw(4); for (int j = 0; j < COV; j++) { if (b[i][j] >= 0) { b[i][j] = (int)b[i][j] % 26; } else { b[i][j] = 26 + (int)b[i][j] % 26; } cout << b[i][j] << setw(6); } cout << endl; } } bool Gauss(float A[ROW][COV], float B[ROW][COV], int n) //高斯消去法 { int i, j, k; float max, temp; float t[ROW][COV]; //临时矩阵 //将A矩阵存放在临时矩阵t[n][n]中 for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { t[i][j] = A[i][j]; } } //初始化B矩阵为单位阵 for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { B[i][j] = (i == j) ? (int)1 : 0; } } for (i = 0; i < n; i++) { //寻找主元 max = t[i][i]; k = i; for (j = i + 1; j < n; j++) { if (fabs(t[j][i]) > fabs(max)) { max = t[j][i]; k = j; } } //如果主元所在行不是第i行,进行行交换 if (k != i) { for (j = 0; j < n; j++) { temp = t[i][j]; t[i][j] = t[k][j]; t[k][j] = temp; //B伴随交换 temp = B[i][j]; B[i][j] = B[k][j]; B[k][j] = temp; } } //判断主元是否为0, 若是, 则矩阵A不是满秩矩阵,不存在逆矩阵 if (t[i][i] == 0) { cout << "There is no inverse matrix!"; return false; } //消去A的第i列除去i行以外的各行元素 temp = t[i][i]; for (j = 0; j < n; j++) { t[i][j] = t[i][j] / temp; //主对角线上的元素变为1 B[i][j] = B[i][j] / temp; //伴随计算 } for (j = 0; j < n; j++) //第0行->第n行 { if (j != i) //不是第i行 { temp = t[j][i]; for (k = 0; k < n; k++) //第j行元素 - i行元素*j列i行元素 { t[j][k] = t[j][k] - t[i][k] * temp; B[j][k] = B[j][k] - B[i][k] * temp; } } } } return true; }
程序运行结果:
选择:1
选择:y
选择:n
选择 2.明文加密:
选择 3.密文解密:
选择 4.退出:
限于目前的水平,仅写出上述函数,欢迎大家阅读,加密解密函数,我只写了hill密码的一部分,上述代码还有很多需要完善的地方,欢迎各位大神指点,恳请各位批评指正,谢谢