密码学--仿射密码

一、实验目的

1、通过实现简单的古典密码算法,理解密码学的相关概念

2、理解明文、密文、加密密钥、解密密钥、加密算法、解密算法、流密码与分组密码等。

二、实验内容

1、题目内容描述

①随机生成加密密钥,并验证密钥的可行性

②从plain文件读入待加密明文

③进行仿射密码加密

④将加密后得到的密文放入cipher文件

⑤根据加密密钥计算解密密钥

⑥进行解密运算

⑦将解密后的文本放入plain_decrypted文件,与明文进行对比

2、关键代码的设计、实现与执行

设计思路:

先以时间产生随机数作为加密密钥a,b,但是这里要通过求最大公因数的方式来验证加密密钥a的可行性,即密钥a和N的最大公因数为1,即a,N互质(其中N为定义在Zn上的N):

下面代码是运用Euclid算法计算最大公因数的关键代码:

while(b!=0)//此处的b是N,也就是此实验的26,

{

temp=a%b;//得到的余数部分

a=b;//b做被模数

b=temp;//得到的余数做模数

}

return a;//求得的最大公因数

下面代码是随机生成密钥a,并通过调用最大公因数的函数验证密钥a可行性的关键代码部分:
while(gcd(a,N)!=1)//循环判断密钥a的可行性

{

srand(time(NULL));//以时间随机生成种子

a=rand()%N; //a随机生成,b也以同样的方式生成,但是不用判断可行性,只需进行一次随机生成

}

得到加密密钥后,从文件读入已经准备好的加密明文(也可通过记事本修改),下面代码是以读的方式打开文件,并判断是否在文件夹中存在命名的文件的关键代码部分:

FILE *plain_file = fopen("plain.txt", "r");//以读的方式打开

if (plain_file == NULL) {

printf("无法打开明文文件!\n");//判断无法打开给出提示

exit(1);//无法打开只能以异常终止结束运行

}

其中分析明文中的大小写字母,大写字母的ASCII码是从65到90,小写字母的ASCII码是从97到122,如实符号则不进行加密解密,直接返回,对字母利用放射加密y=ax+b mod q进行加密,下面代码是根据ASCII码将大小写代码转换,并进行加密的关键代码部分:

if(ch>='a'&&ch<='z')//ascii码转换,ch>=97&&ch<=122

{

ch-=97;

}

else if(ch>='A'&&ch<='Z')//ascii码转换,ch>=65&&ch<=90

{

ch-=65;

}

else

return ch;//如果是字符就直接跳过加密解密部分

return (ch*a+b)%N+97;//最后解密后的文件得到小写的字母

在得到加密后的密文后放入密文cipher文件,关键代码部分如下:

while ((ch = fgetc(plain_file)) != EOF) {

cipher_text=(char)encrypt(ch,a,b); //加密后直接将返回的密文放入文件中

fputc(cipher_text, cipher_file);

运用扩展Euclid算法求逆元a1,就可以得到解密密钥a模N的逆元a1,以及密钥c=b*a1

下面代码是运用扩展Euclid算法求a的逆元a1的关键代码部分:

while(b!=0) {//此处最开始的b也是N,就是此实验的26

int r = a%b;

int q = (a-r)/b;

int x2 = x0-x1*q;

int y2 = y0-y1*q;

a=b;

b=r;

x0=x1;

y0=y1;

x1=x2;

y1=y2;

}//当b==0时,判断是否a2>b2,若是,逆元应该是y0,若不是逆元应该是x0

最后对密文进行解密,步骤基本一样,只是密钥变成了a1和c。

最后将解密得到的文本放入plain_decrypted文件中,关键代码部分如下:

while ((ch = fgetc(cipher_file)) != EOF)

{

plain_text = (char)encrypt(ch,a1,c);

fputc(plain_text, plain_file);

}

实验结果截图:

  1. 实验结果分析

首先测试结果可见上图,可以看到对明文的加密结果以及对密文的解密结果,解密结果和明文是一致的,证明中间算法没有问题,然后在运行中也给了相关信息,如加密密钥和解密密钥以及文件命名等,且在明文中可以任意输入大小写字母,最后统一为小写字母,即最后return时加上97,结果如下:

当然也可以不统一为小写,或者统一为大写字母,只需要在加密encrypt函数处分类返回就行,也就是在小写字母处返回多加97,在大写字母处返回多加65,此处只是为了好看。

也可同一为大写字母如下,且有符号位:

对密文的解密也可以不统一为大写或小写,只需要各自return就行,得到结果如下:

特别的是关于符号以及空格等处理,并未对它们进行处理,而是相应的直接返回原始值,不对它们进行任何加密解密操作。

三、实验思考

1、实验过程总结

在刚开始进行编写程序的时候,由于基础理论知识不扎实,误将加密密钥直接代入解密式子中进行计算,一直出错,后来发现并及时解决了。特别是在符号及空位等的处理方式上,最开始是直接在代码中列出了常见符号的ASCII码,把它们从明文中单独提出来,然后不对它们进行加密解密操作,后来仔细看了实验视频,才发现直接用一个else就可以直接避免对所有的字符进行加密解密。

通过此次实验使我加深了对仿射密码的理解,也更清晰仿射密码加密解密每一步的原理,也加强了我自己的代码能力。

2、回答实验指导书最后提出的问题

①改进将仿射密码定义在Z29上,明密文空间除26个英文字母还包括空格、句号和引号。

这个方案与传统定义在Z26上的仿射密码相比有何优点?

②如果要实现此方案,你的程序应该如何进行调整?

①相对引用Z(26)的仿射密码Z(29)的仿射密码覆盖的范围更广,范围更广也就意味着有着更大的加密范围,意味着算法的安全性更高。

②首先要将宏定义的N改为29,然后加/解密过程对多出来的三个特殊符号进行单独的加/解密。

相关推荐
CD-i3 小时前
密码学实验:凯撒密码
网络·密码学
weixin_387002152 天前
使用GmSSL v3.1.1实现SM2证书认证
算法·安全·区块链·密码学·ssl
泡泡_02246 天前
密码学--AES
c++·安全·密码学
泡泡_02247 天前
密码学--RSA
c++·密码学
apcipot_rain7 天前
【应用密码学】实验四 公钥密码1——数学基础
密码学
_AaRong_7 天前
经典密码学算法实现
算法·密码学
搬砖魁首8 天前
密码学系列 - SR25519与ED25519
密码学
胡耀超9 天前
对称加密算法(AES、ChaCha20和SM4)Python实现——密码学基础(Python出现No module named “Crypto” 解决方案)
开发语言·python·密码学·数据安全·aes·sm4·chacha
敲上瘾10 天前
从明文裸奔到密钥长城:HTTPS加密全链路攻防与CA信任锚点构建
服务器·网络·网络协议·http·网络安全·https·密码学