*欢迎阅读小明哥的博客*
这里主要介绍的是:古典密码之 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__
#include<iostream>
using namespace std;
#include<assert.h>
#include <iomanip>
#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 << "行密钥("<<ROW<<"个数):";
for (size_t j = 0; j < COV; j++)
{
cin >> 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密码的一部分,上述代码还有很多需要完善的地方,欢迎各位大神指点,恳请各位批评指正,谢谢
转载于:https://blog.51cto.com/xmwen1/1751672