现代密码学实验报告1——仿射密码加、解密算法实现 C语言

实验地点:E楼III区503 实验时间:2018.11.10
一、实验室名称:攻防实验室
二、实验项目名称:仿射密码算法实现
三、实验学时:2 学时
四、实验原理:
仿射变换:
加密:在这里插入图片描述
解密:在这里插入图片描述
其中a, b为密钥,在这里插入图片描述,且gcd(a, 26)=1
五、实验目的:
1、熟悉仿射密码算法;
2、理解明文(plaintext)、密文(ciphertext)、加密密钥(encryption key)、解密密钥(decryption key)、加密算法(encryption algorithm)、解密算法(decryption algorithm)。
六、实验内容:
1)用VC++\Python等语言实现仿射变换加/解密算法;
2)加/解密程序对任意满足条件的a、b都能够处理。
七、实验器材(设备、元器件):
学生每人一台PC,安装Windows 7操作系统及VC++\Python开发环境。
八、实验步骤:
1.参数选取与密钥生成
参数就是a与b,也就是本次实验中的密钥。密钥的选取是随机生成的,这里使用 srand(time(0))来重置随机数种子,以当前时间为参数,这样可以使每次使用该仿射密码加密时都可以有不同的密钥对,实现一次一密。
同时,随机生成的a、b需要满足,且gcd(a, 26)=1的条件。这里的26是因为有26个字母,每个字母对应一个数值,一共有26个数值。当a=1时,仿射密码变为加法密码,当a=0时,仿射密码变为乘法密码。

srand(time(0));
do{
	a=rand()%26;
}while(gcd(a,26)!=1||a==0||a==1);     //随机生成符合条件的密钥a 

do{
	b=rand()%26;
}while(b==0);                     //随机生成符合条件的密钥b 

在这里,涉及到gcd()这个子函数,这是个求最大公因数的子函数,在这里使用是为了判断a与26是否互素。
2. 加密
加密的公式是在这里插入图片描述,m[]是明文序列。以下子函数是加密函数,加密算法部分。其中,m[]字符串在主函数中从文件中读入,a,b在主函数中生成。

//加密算法
void enc(char m[MAX],int a,int b) 
{
	char c[MAX];
	int length,j=0;
	FILE *fp3;
    length = strlen(m);
   	printf("Encrypted :\n");
    for(j=0;j<length-1;j++)
    {
    	if(m[j]>64&&m[j]<91)            //区分明文的大小写         
		c[j]=(a*(m[j]-65)+b)%26 +65;      //对大写字母进行加密
		else  
		c[j]=(a*(m[j]-97)+b)%26 +97;       //对小写字母进行加密   
	
		printf("%c",c[j]);               //输出密文 
	}
    fp3=fopen("output.txt","w");    //将密文存储在output.txt 中,便于后续解密        
    int i=0;
    for(i=0;i<length-1;i++)
    	{
    		fprintf(fp3,"%c",c[i]);
		}
	printf("\n");
}

由于输入的明文字符串可能存在大小写都有,而我们这里仅接受26个字符,所以我们需要把大写改成小写或者把小写改成大写,让大小写在数值上是保持一致,这是我刚开始的想法,即将所有大写字符转化成小写字母,然后再进行运算加密,加密后无论明文大小写,密文统一为小写字母。但是这样对于解密算法,需要解密的密文就全部为小写,这种情况下,解密算法解出的明文就无法将大小写区分。也就是如果我们加密前输入的明文是区分大小写的一串字符,在经过仿射密码的加密和解密后,就会统一为大写或小写。
为了解决这个问题,在加密时,我对大小写进行了区分,通过使用if语句对m[j]值的范围进行判断,对大写字母和小写字母分别进行加密,如果m[j]>64&&m[j]<91,即大写字母进行加密, c[j]=(a*(m[j]-65)+b)%26 +65,否则是对小写字母进行加密,c[j]=(a*(m[j]-97)+b)%26 +97。大小写加密的区别在于这26个连续的字符中最小的是以“A”还是“a”开始。
对于加密后的密文,我不仅让它在命令行中显示,还将密文储存在另一个文本文件output.txt中,这样有助于后续的解密工作。
3. 解密
我在主函数中设置了一个switch语句,运行后会先问“e or d?”,此时,输入e,进入加密部分,如上文加密部分所述,而输入d则进入解密部分。我设置这样一个选择是考虑到这个程序的实用性,这个选择可以让解密独立使用。如果我们拿到的是一段密文,只要知道密钥就可以直接进入解密流程。选择解密后,会提示输入密钥,这也是为了让解密与加密独立开使用而设置的,自主输入,而不是直接将之前生成的a、b搬下来使用。当然,如果本次解密的密文就是使用此程序加密而得到的,那要记住刚刚随机生成的a、b密钥。
解密公式:在这里插入图片描述,其中,c[]是密文,默认从加密程序产生的output.txt文件中读入,a、b是随机密钥。

//解密操作
 void dnc(char c[MAX],int a,int b) 
{
	int m[MAX];
	int length;
    length = strlen(c);
    printf("Decrypted :\n");
    for(int j=0;j<length-1;j++){
    	if(c[j]>64&&c[j]<91) {               //对大写密文进行解密 
    	    m[j]=(NI(a)*((c[j]-65)-b))%26+65;   //解密算法 m[i]=a逆*(c[i]-b)mod 26
     	    if(NI(a)*((c[j]-65)-b)<0){      //修正 NI(a)*((c[j]-65)-b)结果为负数的情况 
		      m[j]=m[j]+26;       
		    } 
	    }
	    else{                     //对小写密文进行解密 
	    	m[j]=(NI(a)*((c[j]-97)-b))%26+97;   //解密算法 m[i]=a逆*(c[i]-b)mod 26
     	    if(NI(a)*((c[j]-97)-b)<0){      //修正 NI(a)*((c[j]-97)-b)结果为负数的情况 
		      m[j]=m[j]+26;       
		    } 
		}
		    printf("%c",m[j]);           //输出解密后的明文 
	}
	printf("\n");
}

其中涉及到子函数NI(),它的功能是求一个数mod26下的逆。解密过程,和加密类似也是对密文进行大小写区分解密。在调试过程中,我发现NI(a)((c[j]-97)-b)可能存在小于0的时候,这种情况是无法正确解密的,所以需要使用if函数,在NI(a)((c[j]-97)-b)<0的时,将NI(a)*((c[j]-97)-b)+26,直到变成正数,这个过程与m[j]+26得到的结果相同,可以用m[j]=m[j]+26代替。同样,对于大写字母也有类似的操作。
九、实验数据及结果分析:
(1)实验参考代码:

完整代码请移步资源区下载

(2) 加密及解密实例结果截图:
加密:
明文:plain.txt
在这里插入图片描述
选择“e”(加密),生成随机密钥并加密。
在这里插入图片描述
解密:
选择“d”(解密),输入密钥,解密。
在这里插入图片描述
十、实验结论:
熟悉仿射密码算法并用C语言实现了仿射密码的加密和解密过程,理解明文、密文、加密密钥、解密密钥的概念与它们之间的逻辑关系,对仿射密码的加密算法、解密算法有了较之前不一样的理解。完成了一个具有实用性的仿射密码加密与解密程序。
十一、总结及心得体会:
这次实验让我熟悉了仿射密码算法的原理,一点点分析算法,一步步去理清逻辑。通过使用C语言去将加密算法与解密算法逐步实现,去思考每一条公式和每一个循环嵌套,也让我对使用C语言处理问题增加了信心,同时在实践中也得到了一些处理问题的经验。当大体的框架实现后,我又对这个程序进行美化与完善,列如对加密与解密的选择,来让解密更具有实用性,能够应对多种情况。列如将加密后的密文输出到output.txt文本文件中,而解密时直接打开文件进行解密,让程序更加流畅。列如区分大小写的加密和解密过程,来还原最初文件的字符串。这些东西看似没有什么特别关键的作用,但是在对程序完善的过程中我也学到了很多。
十二、对本实验过程及方法、手段的改进建议:
本次实验主要是将加密算法和解密算法分别使用两个子函数实现,在主函数中,先使用switch语句选择加密或解密工作,在加密中,随机生成加密密钥,从文本文件中读入明文字符串,调用加密子函数进行加密,加密后的密文输出并存储在output.txt文本文件中。在解密中,手动输入解密秘钥,读入密文字符串,调用解密子函数进行解密并输出解密所得明文。
这是本次实验的基本逻辑,最终实现的代码与刚开始写成的代码已经有了很大的改进,但是仍然是不完美的,最明显的一点就是有些繁琐,尤其是大小写是否真的有必要区分,后来我又想解密者不会因为一个字母大小写不分就不认识这个字母了,区分大小写会让代码更加繁琐。

报告评分:
指导教师签字:

  • 15
    点赞
  • 114
    收藏
    觉得还不错? 一键收藏
  • 18
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 18
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值