希尔密码(Hill Cipher)的实现
原理应该不用多讲了,自己百度就可以。
C++实现:
#include <iostream>
#include <string>
#include <memory.h>
#include <cstdlib>
#include <ctime>
#include <cstdio>
#include <cmath>
using namespace std; //定义一些常变量
const int M = ; //定义集合{a,b,...,z}的26个英文字母 //行和列均为5
const int ROW = ;
const int COL = ; //定义5*5的加密矩阵
int K[ROW][COL]; //定义5*5的解密矩阵
int D[ROW][COL]; int P[ROW]; //明文单元
int C[ROW]; //密文单元
int F[ROW]; //密文解密后的单元 //三元组gcd(a,b) = ax + by = d
struct GCD
{
int x;
int y;
int d;
}; class Hill_Cipher
{
public:
//产生随机矩阵
void random_Matrix();
//求矩阵的行列式
int Det(int matrix[ROW][ROW],int row); //求两个数的最大公约数
int gcd(int a,int b); /*
*判断矩阵K是否在模26的情况下可逆
*因为矩阵在模26的情形下存在可逆矩阵的充分必要条件是
*gcd(det K,26) = 1
*/
bool Inverse(int matrix[ROW][ROW]); //矩阵相乘
void multiphy(int matrix[ROW][ROW],int p[ROW],int row); //求出伴随矩阵
void adjoint_matrix(int matrix[ROW][ROW],int row); //将明文加密为密文
string encryption(string plaintext); //将密文解密为明文(为了辨识清楚,我们统一以小写字母作为明文,大写字母作为密文)
string deciphering(string ciphertext); //欧几里得算法求模的逆
GCD extended_Euclid(int a,int b); //模逆运算
int inverse(int a,int m); //由于C++不存在负数取模的内置函数,现在自己设定一个
//定义一个模M的值
int Mod(int a);
}; void Hill_Cipher::random_Matrix()
{
int i,j;
for(i = ;i < ROW;i++)
{
for(j = ;j < COL;j++)
{
K[i][j] = rand() % ; //产生一个5*5模26的矩阵
}
}
cout << "随机产生5*5的矩阵:" << endl;
for(i = ;i < ROW;i++)
{
for(j = ;j < COL;j++)
{
printf("%2d ",K[i][j]);
}
cout << endl;
}
} //求矩阵的行列式
int Hill_Cipher::Det(int matrix[ROW][ROW],int row)
{
int i,j;
int cofa[ROW][ROW]; //用于存放余子阵
int l; //l为所递归的余子阵的行
int p = ,q = ;
int sum=; //由于行和列相同(方阵),所以行列式的值一定存在,故不需要判断是否为方阵 //递归基
if(row == )
return matrix[][];
for(i = ;i < row; i++)
{
for(l = ;l < row - ;l++)
{
if(l < i)
p=;
else
p=;
for(j = ;j< row - ;j++)
{
cofa[l][j] = matrix[l + p][j + ];
}
}
//相当于(-1)^i
if(i % == )
q=;
else
q=(-);
sum = sum + matrix[i][] * q * Det(cofa,row - );
}
return sum;
} //求两个数的最大公约数
int Hill_Cipher::gcd(int a,int b)
{
int temp;
//交换两个数的大小,使得a为较大数
if(a < b)
{
temp = a;
a = b;
b = temp;
}
while(a % b)
{
temp = b;
b = a % b;
a = temp;
}
return b;
} /*
*判断矩阵K是否在模26的情况下可逆
*因为矩阵在模26的情形下存在可逆矩阵的充分必要条件是
*gcd(det K,26) = 1
*/
bool Hill_Cipher::Inverse(int matrix[ROW][ROW])
{
if(gcd(Det(matrix,ROW),M) == )
return true;
else
return false;
} void Hill_Cipher::multiphy(int matrix[ROW][ROW],int p[ROW],int row)
{
int i,j;
//先将密文单元清零
memset(C,,sizeof(C));
for(i = ;i < ROW;i++)
{
for(j = ;j < ROW;j++)
{
C[i] += P[j] * K[j][i];
}
}
} //将明文加密为密文
string Hill_Cipher::encryption(string plaintext)
{
int i;
string ciphertext;
//将字符串转化为明文数组
for(i = ;i < ROW;i++)
{
P[i] = plaintext[i] - 'a';
}
multiphy(K,P,ROW);
//将密文数组转化为密文
for(i = ;i < ROW;i++)
//这里先将其模26,再翻译为对应的字母
{
C[i] =Mod(C[i]);
ciphertext += C[i] + 'A';
}
return ciphertext;
} //求出伴随矩阵
void Hill_Cipher::adjoint_matrix(int matrix[ROW][ROW],int row)
{
int i,j,k,l;
int p,q;
p = q = ;
int temp[ROW][ROW];
for(i = ;i < ROW;i++)
{
for(j = ;j < ROW;j++)
{
for(k = ;k < ROW - ;k++)
{
if(k < i)
p = ;
else
p = ;
for(l = ;l < ROW - ;l++)
{
if(l < j)
q = ;
else
q = ;
temp[k][l] = matrix[k+p][l+q];
}
}
D[j][i] = (int)pow(-,(double)i+j)*Det(temp,ROW-);
D[j][i] = Mod(D[j][i]);
}
}
} //将密文解密为明文(为了辨识清楚,我们统一以小写字母作为明文,大写字母作为密文)
string Hill_Cipher::deciphering(string ciphertext)
{
//求出矩阵的逆
string text;
int determinant = Det(K,ROW);
int inver = inverse(determinant,);
adjoint_matrix(K,ROW); //伴随矩阵
cout << "行列式的值: " << determinant << endl;
int i,j;
memset(F,,sizeof(F));
for(i = ;i < ROW;i++)
{
for(j = ;j < ROW;j++)
{
F[i] += C[j] * D[j][i];
}
F[i] *= inver;
F[i] = Mod(F[i]); //算到的结果要模去26
}
for(i = ;i < ROW;i++)
text += F[i] + 'a';
return text;
} GCD Hill_Cipher::extended_Euclid(int a,int b)
{
GCD aa,bb;
if(b == )
{
aa.x = ;
aa.y = ;
aa.d = a;
return aa;
}
else
{
bb = extended_Euclid(b,a%b);
aa.x = bb.y;
aa.y = bb.x - (a / b) * bb.y;
aa.d = bb.d;
}
return aa;
} int Hill_Cipher::inverse(int a,int m)
{
GCD aa;
aa = extended_Euclid(a,m);
return aa.x;
} int Hill_Cipher::Mod(int a)
{
return a >= ? a % M : (M + a % M);
} int main()
{
int i,j;
Hill_Cipher hh;
cout << "使用希尔密码进行消息的加解密:" << endl; //srand()函数产生一个以当前时间开始的随机种子.以保证每次产生的随机数矩阵都不相同
srand((unsigned)time());
hh.random_Matrix();
while(!hh.Inverse(K))
{
cout << "该矩阵模26不可逆,不可以作为密钥!" << endl;
cout << endl;
hh.random_Matrix();
}
cout << "该矩阵模26可逆,因此可以作为密钥." << endl;
cout << endl; //利用所选密钥,对给定的5元明文信息进行加解密
string plaintext,ciphertext;
cout << "请输入5元明文信息:" << endl;
cin >> plaintext;
ciphertext = hh.encryption(plaintext);
cout << endl;
cout << "该明文通过希尔密码法加密过后,输出的密文消息为:" << endl;
cout << ciphertext << endl;
cout << endl; cout << "***输入0:退出 ***" << endl;
cout << "***输入1:查看明文空间对***" << endl;
cout << "***输入2:查看密文空间对***" << endl;
cout << "***输入3:查看密钥 ***" << endl;
cout << "***输入4:将消息解密 ***" << endl;
cout << "***输入5:查看菜单 ***" << endl; char c;
while(cin >> c)
{
if(c == '')
{
cout << endl;
cout << "退出" << endl;
break;
}
else if(c == '')
{
cout << "明文空间:" << endl;
for(i = ;i < ROW;i++)
cout << P[i] << " ";
cout << endl;
cout << endl;
}
else if(c == '')
{
cout << "密文空间:" << endl;
for(i = ;i < ROW;i++)
cout << C[i] << " ";
cout << endl;
cout << endl;
}
else if(c == '')
{
cout << "密钥:" << endl;
for(i = ;i < ROW;i++)
{
for(j = ;j < ROW;j++)
{
printf("%2d ",K[i][j]);
}
cout << endl;
}
cout << endl;
}
else if(c == '')
{
hh.adjoint_matrix(K,ROW);
string ss;
ss = hh.deciphering(ciphertext);
cout << "该密文解密过后,显示的原来的明文消息:" << endl;
cout << ss << endl;
cout << endl;
}
else
{
cout << "***输入0:退出 ***" << endl;
cout << "***输入1:查看明文空间对***" << endl;
cout << "***输入2:查看密文空间对***" << endl;
cout << "***输入3:查看密钥 ***" << endl;
cout << "***输入4:将消息解密 ***" << endl;
cout << "***输入5:查看菜单 ***" << endl;
}
}
return ;
}
Mathematica 9.0实现:
Print["请输入你要输入的5元明文数组:"];
A = {}
For[i = 0, i < 5, i++, AppendTo[A, Input[]]]
请输入你要输入的5元明文数组:
{}
Print["请输入你要输入的5元明文数组:"];
A = {}
For[i = 0, i < 5, i++, AppendTo[A, Input[]]]
Print["产生5*5的随机数组"];
While[True, B = RandomInteger[{0, 25}, {5, 5}];
If[Det[B] != 0, Break[]];]
Print["A=", A]
Print["B=", B]
请输入你要输入的5元明文数组:
{}
产生5*5的随机数组
A={1,2,3,4,5}
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}}
d = A.B
{141, 126, 170, 236, 135}
Print["d=", d]
d={141,126,170,236,135}
e = Mod[d, 26]
Print["加密后的密文为:", e]
{11, 22, 14, 2, 5}
加密后的密文为:{11,22,14,2,5}
f = d.Inverse[B]
Print["解密后的密文为:", f]
{1, 2, 3, 4, 5}
解密后的密文为:{1,2,3,4,5}
希尔密码(Hill Cipher)的实现的更多相关文章
- c++实现希尔密码
实验名称: 希尔密码的实现(c++版;本文只以26个大写英文字符作为加密后的密文的可选项) 实验原理: 引用知识: 记 Zm={0,1,2,...,m-1} 定义1:设A为定义在集合Zm 上的n阶方阵 ...
- CTF中那些脑洞大开的加密(1)
0x01 目录 各种文本加密 Shell 1 2 3 4 5 6 7 8 9 10 11 12 换位加密: 1.栅栏密码(Rail-fence Cipher) ...
- CTF中那些脑洞大开的编码和加密
0x00 前言 正文开始之前先闲扯几句吧,玩CTF的小伙伴也许会遇到类似这样的问题:表哥,你知道这是什么加密吗?其实CTF中脑洞密码题(非现代加密方式)一般都是各种古典密码的变形,一般出题者会对密文进 ...
- CTF密码学总结
CTF中那些脑洞大开的编码和加密 摘自:https://www.cnblogs.com/mq0036/p/6544055.html 0x00 前言 正文开始之前先闲扯几句吧,玩CTF的小伙伴也许会遇到 ...
- CTF中编码与加解密总结
CTF中那些脑洞大开的编码和加密 转自:https://www.cnblogs.com/mq0036/p/6544055.html 0x00 前言 正文开始之前先闲扯几句吧,玩CTF的小伙伴也许会遇到 ...
- [CTF]中那些脑洞大开的编码和加密
[CTF]中那些脑洞大开的编码和加密 摘自:https://www.cnblogs.com/mq0036/p/6544055.html 0x00 前言 正文开始之前先闲扯几句吧,玩CTF的小伙伴也许会 ...
- javascript实现playfair和hill密码算法
时至期末,补习信息安全概论作业.恰巧遇古典密码学算法中的playfair算法和hill算法,用javascript语言实现起来是在有趣,边查百度边编码,顺便好好补习一下javascript基础. pl ...
- Hill密码
希尔密码(Hill Password)是运用基本矩阵论原理的替换密码,由Lester S. Hill在1929年发明.每个字母当作26进制数字:A=, B=, C=... 一串字母当成n维向量,跟一个 ...
- FCC JS基础算法题(13):Caesars Cipher(凯撒密码)
题目描述: 下面我们来介绍风靡全球的凯撒密码Caesar cipher,又叫移位密码.移位密码也就是密码中的字母会按照指定的数量来做移位.一个常见的案例就是ROT13密码,字母会移位13个位置.由'A ...
随机推荐
- 深入理解JAVA I/O系列五:对象序列化
序列化 对象序列化的目标是将对象保存到磁盘中,或者允许在网络中直接传输对象.对象序列化机制允许把内存中的JAVA对象转换成跟平台无关的二进制流,从而允许将这种二进制流持久地保存在磁盘上,通过网络将这种 ...
- 使用keep-alive 实现 页面回退不刷新内容
遇到问题,是从详情页面会到列表页,列表页会刷新.每个不同栏目的列表页面切换也会刷新 用keep-alive 可以缓存页面 <keep-alive><router-view>&l ...
- debug阶段团队贡献分分配
小组名称:飞天小女警 项目名称:礼物挑选小工具 小组成员:沈柏杉(组长).程媛媛.杨钰宁.谭力铭 debug阶段各组员的贡献分分配如下: 姓名 团队贡献分 程媛媛 5.8 沈柏杉 6.5 谭力铭 3. ...
- 微信小程序 功能函数 定时震动
ffn: function () { let nnn = this.data.nnn nnn += 1; this.setData({ nnn: nnn }); if (nnn > 10) { ...
- zookeeper如何实现负载均衡的?(具体连接哪一个zookeeper服务器的选择?)阿里面试
如果想了解web 6大负载均衡算法,参考:六大Web负载均衡原理与实现 主要是三点:负载均衡算法,健康检查和会话保持 1:首先,我们要了解,我们的应用程序,比如java web程序,里面配置了10个z ...
- line search中的重要定理 - 梯度与方向的点积为零
转载请注明出处:http://www.codelast.com/ 对精确的line search(线搜索),有一个重要的定理: ∇f(xk+αkdk)Tdk=0 这个定理表明,当前点在dk方向上移动到 ...
- BZOJ3270 博物馆(高斯消元+概率期望)
将两个人各自所在点视为状态,新建一个图.到达某个终点的概率等于其期望次数.那么高斯消元即可. #include<iostream> #include<cstdio> #incl ...
- poj 2185
http://poj.org/problem?id=2185 题意:求最小的模式块,使其无限扩展后包含给你的矩阵块(看别人题解才懂的题意): 分析:假设存在一个模式块可以满足上述条件,那么必然存在一个 ...
- win7下解决烦人的管理员权限问题
禁不住诱惑,用上win7了.可是,对system下的文件进行编辑时候,老是碰到什么必须拥有管理员权限才能进行操作,删除文件或者文件夹也遇到一样的问题.我就纳闷了,我不就是超级管理员吗?我怎么就没有权限 ...
- 【uoj131】 NOI2015—品酒大会
http://uoj.ac/problem/131 (题目链接) 题意 给出一个字符串,每个后缀有一个权值${a_i}$,这些后缀两两之间存在公共前缀.问能够组成长度从0~n-1的公共前缀的后缀的方案 ...