实验名称:

希尔密码的实现(c++版;本文只以26个大写英文字符作为加密后的密文的可选项)

实验原理:

引用知识:

记 Zm={0,1,2,...,m-1}

定义1:设A为定义在集合Zm 上的n阶方阵,若存在一个定义在Zm上的方阵B,使得

AB=BA=E(mod m)

则称A模m可逆,B为A的模m逆矩阵,记为

B=A^(-1)(modm)

定义2:设a ∈Zm若存在b∈Zm使得ab=1(mod m),则称b为a的模m倒数或乘法逆,记作

b = a^(-1) (mod m)

命题:定义在集合Zm上的n阶方阵A模m可逆的充要条件是:m和det(A)无公共素数因子,即m 与det(A)互素。

则在模运算下解方程组:AX=Y可得如下:

X=A^(-1)[1] (mod 26)* Y (mod 26)

下面求 A^(-1) (mod 26):

模m逆矩阵的计算:

由 |A|·A^(-1)=A* A为A的伴随矩阵

设B=KA
为A的模26逆,其中k为待定系数

即:

BA=K·|A|·E

BA=E(mod26)

k·|A|=1(mod26)

k=|A|^(-1)(mod26)

故由上述所得解密矩阵的计算是由以加密矩阵行列式的值作为分母;1作为分子的分数;mod26;再乘以加密矩阵的伴随矩阵得到的矩阵;最后mod26即得到解密矩阵。

算法分析:

加密:

本次实验加密矩阵根据用户输入的阶数由系统自动随机生成,并判断是否符合模逆矩阵的条件,如果不符合就生成新的加密矩阵,直到符合条件为止;

原文加密时生成的原文矩阵阶数由加密矩阵的阶数(记作n)和原文的长度决定,由原文的长度除以加密矩阵的阶数向上取整(记作x),原文长度不够的用字符A补全。然后将原文减去字符A;

即最后会生成一个x行n列的原文矩阵;

加密过程就是用原文矩阵乘以密文矩阵得到的结果mod26。然后用结果加上字符A得到密文。

int** makeMatrix(int param,int param1) {
int** mat = new int* [param];
for (int i = 0; i < param; i++)
{
mat[i] = new int[param1];
}
for (int i = 0; i < param; i++)
{
for (int j = 0; j < param1; j++)
{
mat[i][j] = 0;
}
}
return mat;
}
//矩阵与矩阵相乘
std::string multiply(int **param,int**param1,int param2,int param3){
std::string sum = "";
int** mat3 = makeMatrix(param2, param3);
for (int i = 0; i < param2; i++)
{
for (int j = 0; j <param3; j++)
{
for (int k = 0; k < param3; k++)
{ mat3[i][j] += param[i][k] * param1[k][j]; } mat3[i][j] = mat3[i][j] % 26;
sum += (int)mat3[i][j] + 'A'; }
}
return sum;
}
//数字与矩阵相乘
int** multiply(int param,int**param1) { //std::string sum="";
int col = _msize(param1[1]) / sizeof(int);
int** mat = makeMatrix(col, col);
for (int i = 0; i <col; i++)
{
for (int j = 0; j < col; j++)
{
mat[i][j] = ((param1[i][j]* param)%26+26)%26; } } return mat; }
//判断生成的矩阵是否合理
void judge(bool &param,int **param1,int param2) {
int det = caculate(param1,param2);
if (det%2==0||det%13==0||det<0)
{
param = true;
}
else {
param = false; } } //加密函数入口
void getCode() {
std::string orignal;
int num,zhong;
bool flag = true;
std::cout << "请输入原文:"<<std::endl;
std::cin >> orignal;
std::cout << "请选择生成的密钥矩阵的阶数" << std::endl;
std::cin >> num;
int len = orignal.length() % num == 0 ? orignal.length() / num : orignal.length() / num + 1;
int** mat1 = makeMatrix(num,num);//密码矩阵
int** mat2 = makeMatrix(len,num);//明文矩阵
//循环创建符合密码矩阵要求的秘钥
while (flag) {
Sleep(500);
srand(time(NULL));
for (int i = 0; i < num; i++)
{
for (int j = 0; j < num; j++)
{
zhong = rand() % 20;
mat1[i][j] = zhong == 0 ? 1 : zhong;
} }
judge(flag, mat1,num); }
//补充不能够形成矩阵的字符
int k = 0, le = num - orignal.length() % num;
for (int m = 0; m < le; m++)
{
orignal += "A";
}
//将字符转化为原文矩阵
for (int i = 0; i <len ; i++)
{
for (int j = 0; j < num; j++)
{
mat2[i][j] = (orignal[k]-'A');
k++;
}
}
//矩阵相乘
std::string mtext=multiply(mat2, mat1, len, num);
std::cout << "加密矩阵" << std::endl;
for (int i = 0; i < num; i++)
{
for (int j = 0; j < num; j++)
{
std::cout << mat1[i][j]<<" ";
}
std::cout << "" << std::endl;
}
std::cout << "密文:" << mtext << std::endl; }

解密:

由上述的引用知识点知:解密矩阵由加密矩阵的行列式分之一mod26然后乘以加密矩阵的伴随矩阵得到的结果mod26得到。

①分数求模

对于分数求模,我借用了mod运算的分配律

(a×b) mod c=(a mod c * b mod c) mod c

即把分数求模转化为了整数求模,借助于少于30次的的循环,即可得出结果,代码如下。

注释:param参数为行列式的值mod26得到的值

int gradeMode(int param) {

for (int i = 1; ; )
{
if ((26 * i+1) % param == 0)
{
return (26*i+1)/param;
break;
}
i += 1;
} }

②伴随矩阵的求解

本次实验我是用了求行列式calaulate()函数和求代数余子式surplus()函数的函数递归得到,两函数代码如下:。

int caculate(int **param,int param1){
int row = param1;
if (row==2)
{
return param[0][0]*param[1][1]-param[0][1]*param[1][0];
}
else {
int sum = 0;
for (int i = 0; i < row; i++)
{
sum += param[0][i]*surplus(param,0,i,param1);
}
return sum;
}
} int surplus(int **param,int x,int y,int param1) {
if (param1==2)
{
return pow(-1, x + y + 2)*param[1-x][1-y];
}
else { int row = param1, col = param1;
int xflag = 0, yflag = 0;
int** mat = makeMatrix(row - 1, col - 1);
for (int i = 0; i < row; i++)
{
if (i!=x)
{
yflag = 0;
for (int j = 0; j < col; j++)
{
if (j != y )
{
mat[xflag][yflag] = param[i][j];
yflag++;
} }
xflag++;
} }
return pow(-1, x + y + 2) * caculate(mat, param1 - 1); } }

借助①②即可得到解密的矩阵:具体代码如下:

void putcode() {
int num;
std::string dense;
std::cout << "请输入密文" << std::endl;
std::cin >> dense;
std::cout << "请输入阶数:" << std::endl;
std::cin >> num;
int** mat1 = makeMatrix(num,num);//接受加密矩阵
int** mat2 = makeMatrix(dense.length() / num, num);//密文矩阵
int** mat3 = makeMatrix(num,num);// std::cout << "请输入加密矩阵:" << std::endl;
//获取加密矩阵
for (size_t i = 0; i < num; i++)
{
for (size_t j = 0; j < num; j++)
{
std::cin >> mat1[i][j];
}
} //转换密文维密文矩阵
int k=0;
for (size_t i = 0; i < dense.length()/num; i++)
{
for (size_t j = 0; j < num; j++)
{
mat2[i][j] = (dense[k] - 'A');
k++;
}
} //算密码矩阵的伴随矩阵
for (int k = 0; k < num; k++)
{
for (int j = 0; j < num; j++)
{
mat3[k][j] = surplus(mat1, j, k, num);
}
} int num1=caculate(mat1,num)%26;//计算行列式
int** mat4 = multiply(gradeMode(num1), mat3);//解码矩阵 for (int k = 0; k < num; k++)
{
for (int j = 0; j < num; j++)
{
std::cout<<mat4[k][j]<<" " ;
}
std::cout << "" << std::endl;
} std::string original = multiply(mat2, mat4,dense.length()/num,num); //原文 std::cout << "解密结果为:"<<original; }

程序实现界面:

主程序部分代码:

#include "decode.h"
#include "Encryption.h" void main() {
while (true)
{
system("cls");
int select=0;
std::cout << "加密--1;解密--2" << std::endl;
std::cin >> select;
switch (select)
{
case 1:
getCode();
system("pause");
break;
case 2:
putcode();
system("pause");
break;
default:
break;
} } }

加密:

解密:


  1. 这表示A的逆

c++实现希尔密码的更多相关文章

  1. 希尔密码(Hill Cipher)的实现

    原理应该不用多讲了,自己百度就可以. C++实现: #include <iostream> #include <string> #include <memory.h> ...

  2. Hill密码

    希尔密码(Hill Password)是运用基本矩阵论原理的替换密码,由Lester S. Hill在1929年发明.每个字母当作26进制数字:A=, B=, C=... 一串字母当成n维向量,跟一个 ...

  3. CTF中常见密码题解密网站总结

    0x00.综合 网站中包含大多编码的解码. http://web2hack.org/xssee/ https://www.sojson.com/ http://web.chacuo.net/ 0x01 ...

  4. javascript实现playfair和hill密码算法

    时至期末,补习信息安全概论作业.恰巧遇古典密码学算法中的playfair算法和hill算法,用javascript语言实现起来是在有趣,边查百度边编码,顺便好好补习一下javascript基础. pl ...

  5. ctf古典密码从0到

    本文首发于“合天智汇”公众号 作者:淡灬看夏丶恋雨 古典密码和现代密码的区别: 代换密码 单表代换密码 字符或数学型 凯撒密码 仿射密码 四方密码 培根密码 图表 标准银河字母 圣堂武士密码 猪圈密码 ...

  6. CTF中那些脑洞大开的加密(1)

    0x01 目录 各种文本加密             Shell   1 2 3 4 5 6 7 8 9 10 11 12 换位加密:     1.栅栏密码(Rail-fence Cipher)    ...

  7. CTF中那些脑洞大开的编码和加密

    0x00 前言 正文开始之前先闲扯几句吧,玩CTF的小伙伴也许会遇到类似这样的问题:表哥,你知道这是什么加密吗?其实CTF中脑洞密码题(非现代加密方式)一般都是各种古典密码的变形,一般出题者会对密文进 ...

  8. ctf之加密

    from:http://drops.wooyun.org/tips/10002 0x01 Base64 Base64:ZXZhbCgkX1BPU1RbcDRuOV96MV96aDNuOV9qMXVfU ...

  9. 2016 西普杯丶天津CTF预选赛(3/6)

    哆啦A梦(图片隐写) 格式:SimCTF{ } 解:放到kail中binwalk一下(Binwalk是一个固件的分析工具,旨在协助研究人员对固件非分析,提取及逆向工程用处.简单易用,完全自动化脚本,并 ...

随机推荐

  1. [Java] 数据分析--统计

    二项分布 需求:5个四面体筛子,筛子三面绿色,一面红色,模拟1000000次,统计每次试验红色落地筛子个数的分布 实现:用循环实现5个筛子和1000000次试验,定义函数numRedDown模拟5个筛 ...

  2. [DB] MapReduce

    概述 大数据计算的核心思想:移动计算比移动数据更划算 MapReduce既是一个编程模型,又是一个计算框架 包含Map和Reduce两个过程 终极目标:用SQL语句分析大数据(Hive.SparkSQ ...

  3. 记一次MySQL(5.7版本)数据库的主从同步和备份

    我遇到的问题 我先后在BAT三大云服务器商购买了学生机,配置如下 百度云2核/4G 阿里云1核/2G 腾讯云1核/2G 我的解决方案 由于我不知道百度云的续费规则,导致买了2核/4G的服务器之后以为像 ...

  4. STM32F4-IAP学习笔记--(转)

    花了断断续续两天时间在STM32上面写了一个IAP(In Application Programing)Boot,期间多多少少还是遇到的了不少问题.现在就花点时间把这两天写的东西整理一下,就当是学习笔 ...

  5. ifconfig显示的网卡信息和我的配置文件名不符

    比如我的配置文件, cd /etc/sysconfig/network-scripts/ifcfg-Auto_eth0是这个名称,但是我使用ifconfig显示的信息却是 eth6   Link en ...

  6. Linux下记录登录用户历史操作

    前言:众所周知Linux是一个可以同时让多个用户登录的操作系统,每个用户的操作都影响着Linux运行,除了要做好安全工作以外,防止人为恶意损坏也是很关键的,比如有人恶意执行危险命令,要查找就得记录所有 ...

  7. win7 32位系统 安装node.js最新版本遇到的问题

    win7   32位是安装不了10.0以上版本的node.js的 ,因为10.0以上版本的node.js已经不对win7 32位的电脑进行维护更新了,如果你的电脑是win7 32位系统的话,只能下载安 ...

  8. Hadoop 基石HDFS 一文了解文件存储系统

    @ 目录 前言:浅谈Hadoop Hadoop的发展历程 1.1 Hadoop产生背景 1.引入HDFS设计 1.1 HDFS主要特性 2.HDFS体系结构 HDFS工作流程机制 1.各个节点是如何互 ...

  9. Go语言网络通信---TCP通信上传一个小文件

    server: package main import ( "fmt" "net" "os" ) func SHandleError(err ...

  10. win10家庭中文版CUDA+CUDNN+显卡GPU使用tensorflow-gpu训练模型安装过程(精华帖汇总+重新修改多次复现)

    查看安装包 pip list 本帖提供操作过程,具体操作网上有好多了,不赘述.红色字体为后来复现出现的问题以及批注 题外话: (1)python 的环境尽量保持干净,尽量单一,否则容易把自己搞晕,不知 ...