古典密码之hill密码的加密与解密程序实现

*欢迎阅读小明哥的博客*

这里主要介绍的是:古典密码之 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)解密:明文=密文*密钥矩阵的逆 (注:要求与加密过程相同)

加密解密过程如下图:

wKiom1boxprjDe_VAAAZKXwEiBU284.png

例:

wKioL1box_iQAR_KAABY49UTUXI528.png

wKiom1box_uhu0vvAABDW--g6Ds013.png

加密过程:

wKiom1boyGCShMdqAABOMysHfaA697.png

解密:

wKiom1boyJ6BiUN0AABUhBw0uyc397.png

wKioL1bo0P2A6pBAAAA1WEF6DDQ054.png

对上述过程进行编程,主要的函数声明如下:

/*
*
*  头文件名称: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;
}

程序运行结果:

wKioL1bozYHDHhlNAAAgPVqMJxk248.png

选择:1

wKiom1bozY7Bl8wjAAAftuVnUPQ208.png

选择:y

wKiom1bozgDA25DfAAAiYiG2Ohk216.png

选择:n

wKiom1bozlSRqoLeAAAhtOqSI9U425.png

选择 2.明文加密:

wKiom1bozs_gpwobAAAej9bk6zA287.png

选择 3.密文解密:

wKioL1boz8vSv20WAAAmikEJ8Qw938.png

选择 4.退出:

wKiom1boz3ezokj0AAAdJ8dnSG0186.png


限于目前的水平,仅写出上述函数,欢迎大家阅读,加密解密函数,我只写了hill密码的一部分,上述代码还有很多需要完善的地方,欢迎各位大神指点,恳请各位批评指正,谢谢

本文出自 “分享中进步” 博客,请务必保留此出处http://xmwen1.blog.51cto.com/10730069/1751672

  • 9
    点赞
  • 50
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值