古典密码之希尔密码Cpp源码

希尔密码介绍

希尔(Hill)密码是1929年由数学家Lester Hill发明的,加密算法将m个连续的明文字母替换成m个密文字母,并且由m个线性等式决定变换的方式。在线性等式里字母与数值一对一映射,,例如当时系统可以表示为:



用列矢量和矩阵表示为:

上式可以表达为:
其中,c和p是长度为m的列矢量,分别代表密文和明文,K是一个矩阵,代表加密密钥,运算按模26执行。
解密过程是加密过程的逆过程,希尔密码算法的解密过程可以表示为:,其中是加密密钥的逆。
希尔密码算法在实际计算中字母与数字对应的多少是根据实际情况来确定的。在很多应用算法中,加入了“,”、“?”和空格“ ”,使得解密后得到的明文可以与原来的明文一致,其映射关系见下表。
a b c d e f g h i j k l m n o p q r s t u v w x y z . ? 空格
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
采用29个字母映射的加密方法与采用26个字母映射的计算方法是完全一致的。
希尔密码算法中涉及在模运算下计算矩阵的逆,因此,加密矩阵必须在模运算下可逆才能用于加密计算
希尔密码算法采用的加密和解密矩阵通常为矩阵,解密矩阵通过计算加密矩阵在模运算下的逆获得。如果加密矩阵为:,可逆,即,则其逆矩阵为:

在计算加密矩阵在模运算下的逆时,必须存在的乘法逆元。如果采用26个字母的映射,那么模26必须1,3,5,7,9,11,15,17,19,21,23或25中的一个;否则不能进行解密。
例子1:采用映射表为26个字母与数字的映射,加密矩阵为,试计算解密矩阵。
解:
由于17存在模26的乘法逆元,因此,加密矩阵的逆为:
计算得17模26的乘法逆元为23,即,于是有
对计算结果进行验算,有:
乘法逆元的计算方法参考扩展的欧几里得算法。
在程序设计过程中要注意除法问题,当存在除法时需要先计算分母的乘法逆元,将除法转换为乘法运算。否则,得不到正确的运算结果。
希尔密码算法在一般的情况下是采用二阶方阵作为加密密钥。采用二阶密钥隐蔽了明文的二元统计信息,若需要隐蔽二元以上的明文统计信息,则需要采用更高阶的方阵作为密钥。例如,有时候会采用三阶方阵作为加密密钥。
三阶以上的矩阵计算逆矩阵可以采用初等变换法或伴随矩阵法等。

2:采用映射表为26个字母与数字的映射,加密矩阵为,试采用初等变换方法计算解密矩阵。
计算方法为
\left[ \begin{matrix}<br />     1 & 2 & 3 & 1 & 0 & 0 \\<br />     0 & 1 & 4 & 0 & 1 & 0 \\<br />     5 & 6 & 0 & 0 & 0 & 1 \\<br />\end{matrix} \right] \rightarrow-5r_{1}+r_{3}\rightarrow<br />\left[ \begin{matrix}<br />     1 & 2 & 3 &  1 & 0 & 0 \\<br />     0 & 1 & 4  & 0 & 1 & 0 \\<br />     0 & -4 & -15 & -5 & 0 & 1 \\<br />\end{matrix} \right] \rightarrow 4r_{2}+r_{3}\rightarrow<br />\left[ \begin{matrix}<br />     1 & 2 & 3 & 1 & 0 & 0 \\<br />     0 & 1 & 4 & 0 & 1 & 0 \\<br />     0 & 0 & 1 & -5 & 4 & 1 \\<br />\end{matrix} \right] \rightarrow-2r_{2}+r_{1}\rightarrow<br />\left[ \begin{matrix}<br />     1 & 0 & -5 & 1 & -2 & 0 \\<br />     0 & 1 & 4 & 0 & 1 & 0 \\<br />     0 & 0 & 1 & -5 & 4 & 1 \\<br />\end{matrix} \right] \rightarrow(5r_{3}+r_{1})、(-4r_{3}+r_{2})\rightarrow<br />\left[ \begin{matrix}<br />     1 & 0 & 0 & -24 & 18 & 5 \\<br />     0 & 1 & 0 & 20 & -15 & -4 \\<br />     0 & 0 & 1 & -5 & 4 & 1 \\<br />\end{matrix} \right]

于是得到解密矩阵:


在本示例中,正好为1,若为非1整数,则需要计算的乘法逆元,将转换为1,这样可以在后续计算中避免计算过多的乘法逆元,而降低计算速度。

Cpp源码

Hill.h的源码如下:
#ifndef HILL_H
#define HILL_H
#include <string>
#include <vector>

using namespace std;

struct ExtEuc{
	int d;
	int s;
	int t;
	
	ExtEuc(){
	}
	
	ExtEuc(int dd,int ss,int tt){
		d = dd;
		s = ss;
		t = tt;
	}
};

class Hill{
	private:
		int key[2][2];					//加密密钥
		int decKey[2][2];				//解密密钥
		int det;						//密钥的行列式
		string plainText;				//加密前明文
		vector<char> cipherText;		//加密后密文
		vector<char> vinText;			//临时存储明文数据
		vector<char> decText;			//解密后的文件数据
	public:
		Hill() ;
		void init();					//初始化密钥、明文
		void cutPlainText();			//分割明文存储到向量
		void getDecKey();				//获取解密密钥
		void encryption();				//加密明文
		void decryption();				//解密密文
		void showResult();				//显示计算结果
		int gcd(int n, int k);			//计算最大公因子
		ExtEuc* ExtEuclid(int a, int b);	//用于计算乘法逆元的函数
};
#endif
Hill.cpp的源码如下:
#include "Hill.h"
#include <iostream>

using namespace std;

void Hill::init(){
	int i,j;
	while(1){
		cout<<"Input the key:"<<endl;
		for(i=0;i<2;i++){
			for(j=0;j<2;j++){
				cin>>key[i][j];
			}
		}
		det=key[0][0] * key[1][1]-key[0][1] * key[1][0];
		if((det==0) | (gcd(det,26)!=1)){
			cout<<"The key can't be inversed, reinput the key!"<<endl;
		}else{
			break;
		}
	}
	getDecKey();
	cout<<"Input the plaintext:"<<endl;
	cin>>plainText; 
}

Hill::Hill(){
	init();
}

void Hill::getDecKey(){
	ExtEuc* eu;
	int inverseDet;			//det的乘法逆元 
	int i,j;
	eu=ExtEuclid(det,26);
	inverseDet=eu->s;		//获得det的乘法逆元 
	decKey[0][0]= key[1][1];
	decKey[0][1]= -key[0][1];
	decKey[1][0]= -key[1][0];
	decKey[1][1]= key[0][0];
	for(i=0;i<2;i++){
		for(j=0;j<2;j++){
			decKey[i][j]=(decKey[i][j]*inverseDet)%26;
			if(decKey[i][j]<0){
				decKey[i][j]+=26;
			}
		}
	}
}

void Hill::cutPlainText(){
	int i;
	if(plainText.length()%2==1){
		plainText+="z";
		for(i=0;i<plainText.length();i++){
			vinText.push_back(plainText[i]);
		}
	}
}

void Hill::encryption(){
	cutPlainText(); 
	int ciphText[2]={0,0};		//处理临时密文数据
	int plaiText[2]={0,0};		//处理临时明文数据
	int i,j,k;
	for(i=0; i<vinText.size(); i+=2){
		plaiText[1%2] = int(vinText[i])-int('a');
		plaiText[(i+1)%2] = int(vinText[i+1])-int('a');
		for(j=0; j<2; j++){
			for(k=0; k<2; k++){
				ciphText[j] += key[j][k] * plaiText[k];
			}
		}
		for (j=0;j<2;j++){
			ciphText[j] = ciphText[j]%26;
			cipherText.push_back(char(ciphText[j]+int('a')));
			ciphText[j]=0;		//还原临时数据
		}
	}
}
		
void Hill::decryption(){
	int ciphText[2] = {0,0};		//处理临时密文数据
	int plaiText[2] = {0,0};		//处理临时明文数据
	int i,j,k;
	for(i=0; i<cipherText.size(); i+=2){
		ciphText[i%2]= int (cipherText[i])-int('a');
		ciphText[(i+1)%2]= int(cipherText[i+1])-int('a');
		for(j=0;j<2;j++){
			for(k=0;k<2;k++){
				plaiText[j]+=decKey[j][k]*ciphText[k];
			}
		}
		for(j=0;j<2;j++){
			plaiText[j]=plaiText[j]%26;
			decText.push_back(char(plaiText[j]+int('a')));
			plaiText[j]=0;
		}
	}
}

int Hill::gcd(int n, int k){
	if(n == 0){
		return k;
	}
	if(k == 0){
		return n;
	}
	return gcd(k, n%k); 
}

ExtEuc* Hill::ExtEuclid(int a, int b){
	if(b==0){
		ExtEuc* res = new ExtEuc(a,1,0);
		return res;
	}
	
	ExtEuc* ans = ExtEuclid(b, a%b);
	int d = ans->d;
	int s = ans->t;
	int t = ans->s-(a/b)*ans->t;
	return new ExtEuc(d,s,t);
}

void Hill::showResult(){
	for (vector<char>::const_iterator i = cipherText.begin(); i != cipherText.end(); i++) {
		cout << *i;
	}
	cout<<endl;
}
main.cpp源码如下:
#include <iostream>
#include "Hill.h"

/* run this program using the console pauser or add your own getch, system("pause") or input loop */

int main(int argc, char** argv) {
	Hill* h = new Hill();
	h->encryption();
	h->showResult();
	h->decryption();
	return 0;
}
执行效果:


全部评论

相关推荐

不愿透露姓名的神秘牛友
05-29 22:21
Offer1:小马智行,深圳,测试开发工程师,17.0k*16.0,Offer2:追觅科技,深圳,嵌入式工程师,18.0k*15.0,
嵌软狗都不学:各位base深圳的同事,作为也是并肩作战的一员,今天想站在管理视角,和大家开诚布公地聊一聊:从近几个月的上下班数据对比看来,我们发现一个明显的差异:深圳同事的在岗时间普遍比苏州同事短。很多深圳同事早上9点之后才到公司,晚上不到 20 点就下班了;而总部那边,20点半甚至 22 点后还有不少同事在办公室忙碌,特别是研发团队,加班更是常态。相信去过苏州的同事,对这种场景都不陌生。我很好奇,这是因为苏州工作任务太重还是咱们深圳同事效率真的高到能在更短时间内完成工作?MOVA在深圳成立分公司是为了吸引更优秀的人才贡献更多更高质的价值,公司管理层给我反馈的是深圳招到的多是行业的专家大拿,大部分都是薪资比苏州高的,而且我们办公的租金等也远高于苏州的..MOVA虽脱胎于强壮的集团母体不久,各业务板块尚未实现全面盈利,虽说公司管理层目光长远,不纠结当下的人才投入,但行业内的普遍标准是,员工创造的价值要达到公司雇佣成本的 15 倍以上。大家不妨自我审视一下,自己是否达到了这个标准?如果是抱着划水、按时打卡走人拿毛爷爷的心态那不适合来MOVA,那样过下去不但自己过得尴尬也会影响MOVA这个大船的攻城略地的速度.我并非鼓励大家盲目加班,而是倡导高效工作,拒绝无效忙碌,不要让项目进度因低效受影响,也别把精力浪费在和苏州同事拼打卡时长上,提倡更高的人效比;考虑到两地地域和交通差异,相信大家会找最适合自己发挥的工作方式(比如按时下班后1小时到家晚饭后继续未竟工作等..)大家在遵守公司规章的情况下尽情地体现自己的能力价值,为MOV!和深圳公司争光我们在这边才能更安心更有信心的工作下去;请客BU长、名部门长、项目管理和各业务单元负责人,全面梳理团队情况,及时评估成员工作负荷与成果质量,坚决清退划水害虫痕疫,践行公司价值观,相互监督,防止管理漏洞及渎职。感谢人家的理解,也请人家多担待我的直言不讳……
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务