古典密码学.docx
《古典密码学.docx》由会员分享,可在线阅读,更多相关《古典密码学.docx(20页珍藏版)》请在冰豆网上搜索。
![古典密码学.docx](https://file1.bdocx.com/fileroot1/2023-1/30/7cfe5f65-d736-4a2b-8154-2edb9de52e0e/7cfe5f65-d736-4a2b-8154-2edb9de52e0e1.gif)
古典密码学
现代密码学与加解密技术实验报告
实验名称
Vigenere和Columnpermutationcipher的编程实现
班级
学号
姓名
日期
成绩
评阅人
软件学院
一、实验目的与意义
实验目的:
通过编程实现Vigenerecipher和Columnpermutationcipher的加、解密算法,加深对古典密码体制的了解,为深入学习密码学奠定基础。
实验意义:
通过本次实验验证学习过的理论知识,更进一步的了解替代密码的加密过成功,更重要的是通过实验加强实验手段与实践技能,培养分析问题、解决问题、应用知识的能力和创新精神,全面提高综合素质
二、实验环境
操作系统:
Windows7
调试软件名称及版本号:
VC++6.0
上机地点:
综合楼311
三、实验的预习内容
1、Vigenercipher
实验前预习主要内容:
(1)预习有关Vigenerecipher加密和解密的原理。
(2)预习二维数组的操作,利用二维数组将表显示出来。
(3)找到将关键字重复写在明文上的过程。
实验思路:
(1)加密过程为输入明文和密钥,将明文和密钥的长度进行比较,根据情况将密钥进行扩展,之后按照Vieneretable进行查表找到相对应的密文。
(2)解密过程和加密过程的原来基本相同,在这不进行赘述。
程序框图:
加/解密
Y
2、Columnpermutationcipher
实验前预习内容:
(1)预习有关Columnpermutationcipher加密和解密的原理。
(2)掌握二维数组的操作,利用二维数组将明文存放在矩阵当中。
(3)掌握排序算法,将密钥字母进行排序找到输出列的顺序。
实验思路:
(1)加密过程,将明文和密钥输入,将明文放入到矩阵当中,并且计算是否需要添加无效字符‘q’。
之后利用冒泡排序将密钥字符进行排序,得到读取列的顺序,进而将密文输出。
(2)解密过程,将密文和密钥输入,将密文排序以便恢复明文矩阵,之后进行列读取将明文矩阵恢复。
该过程和加密过程相似。
程序框图:
加/解密
四、实验的步骤与调试方法
1、Vigenerecipher
实验步骤:
(1)建立win32consoleapplication工作空间。
(2)建立源文件。
(3)构建Vigenere表。
for(i=0;i<26;i++)
{
for(j=0;j<26;j++)
{
table[i][j]=a[(j+i)%26];
}
}
(4)根据密钥和明文的长度情况扩展密钥。
if(key_len{
for(i=key_len;i{
key[i]=key[(i%key_len)];
}
}
(5)根据密钥和明文的对应情况,查表得到结果。
for(i=0;i<26;i++)
{
for(j=0;j<26;j++)
{
table[i][j]=a[(j+i)%26];
}
}
(6)解密过程和加密过程相似,只是在查表的时候为逆查表。
for(i=0;i{
//在表中进行逆查表找到明文字母
for(j=0;j<26;j++)
{
if(table[(key[i]-97)][j]==str[i])
printf("%c",table[0][j]);
}
}
(7)进行编译、链接、执行,按照提示输入密钥和明文(密文)。
遇到的问题和调试方法:
(1)在实验进行加密操作显示Vigeneretable时,总是出错,经过检查发现我忽略了在字母表移位过程后需要进行一次模操作,经过修改,Vigenertable正常显示。
2、Columnpermutationcipher
实验步骤:
(1)建立win32consoleapplication工作空间。
(2)建立源文件。
(3)确定矩阵的形状以及是否需要填充无效字符。
//计算矩阵的行数以及是否需要填充无效字符
t3=str_len%key_len;//多出来的字符
if(t3==0)
{
line=str_len/key_len;//明文矩阵的行数
add=0;//需要填充的无效字符的个数
}
else
{
line=str_len/key_len+1;//明文矩阵的行数
add=key_len-t3;//需要填充的无效字符的个数
}
(4)处理密钥,得到列读取顺序。
for(i=0;i{
num[i]=0;
for(j=0;j{
if(key[j]<=key[i])
{
num[i]=num[i]+1;
}
if(key[j]==key[i]&&j>i)//字符相同的情况
num[i]=num[i]-1;
}
}
(5)将明文填充到矩阵当中,如果需要补充无效字符。
if(add!
=0)
{
for(i=0;i{
str[str_len+i]='q';
}
}
for(i=0;i{
for(j=0;j{
a[i][j]=str[i*key_len+j];
}
}
(6)之后按照列的顺序读取密文。
(7)解密过程和加密过程相似,只是恢复明文矩阵时为按列恢复。
for(i=0;i{
for(j=0;j{
a[j][num[i]-1]=str[i*line+j];
}
}
(8)进行编译、链接、执行,按照提示输入密钥和明文(密文)。
遇到的问题和调试方法:
(1)在开始确定明文是否需要补充无效字符时,发现无法在矩阵最后加入无效字符,执行时发现程序中间便终止,无法正常进行,最后发现在补充无效字符时出现逻辑错误,将无效字符添加到了矩阵外,因而出现了错误,最后我将无效字符直接添加到了明文中,这样便可以直接将其填入明文矩阵。
五、实验数据与实验结果
1、Vigenerecipher
程序开始的界面,如果加密则选择1,如果要进行解密操作选择2。
之后进行加密操作,密钥为cipher,明文为vigenerecipher。
进行解密过程,密钥为cipher,密文为xqvlrvtmrptygz(上文密文)。
经过上述过程,发现结果相同,因此,实验过程正确。
2、Columnpermutationcipher
程序开始的界面,如果加密则选择1,如果要进行解密操作选择2。
之后进行加密操作,密钥为cipher,明文为columnpermutation,得到的密文为cpaumomunlrioetntq
进行解密,密钥为cipher,密文为cpaumomunlrioetntq(上文密文)。
经过上述过程,发现结果相同,因此,实验过程正确。
六、实验用程序清单(要有注释)
1、Vigenerecipher
#include
#include
#include
voidencryption()
{
inti,j;
charkey[20];//密钥
charstr[100];//明文
intkey_len,str_len;//密钥长度
chartable[26][26];//表
chara[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'};
printf("请输入密钥:
");
scanf("%s",&key);
printf("请输入明文:
");
scanf("%s",&str);
key_len=strlen(key);//密钥长度
str_len=strlen(str);//明文长度
if(key_len{
for(i=key_len;i{
key[i]=key[(i%key_len)];
}
printf("扩展密钥为:
");
for(i=0;i{
printf("%c",key[i]);
}
}
for(i=0;i<26;i++)
{
for(j=0;j<26;j++)
{
table[i][j]=a[(j+i)%26];
}
}
/*printf("\n显示表:
\n");
for(i=0;i<26;i++)
{
for(j=0;j<26;j++)
{
printf("%c",table[i][j]);
}
printf("\n");
}*/
printf("\n密文:
");
for(i=0;i{
printf("%c",table[(str[i]-97)][(key[i]-97)]);
}
printf("\n");
}
voiddecryption()
{
inti,j;
intkey_len,str_len;//密钥长度,密文长度
charkey[20];//密钥
charstr[100];//密文
chartable[26][26];//表
chara[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'};
printf("请输入密钥:
");
scanf("%s",&key);
printf("请输入密文:
");
scanf("%s",&str);
key_len=strlen(key);//密钥长度
str_len=strlen(str);//密文长度
if(key_len{
for(i=key_len;i{
key[i]=key[(i%key_len)];
}
printf("扩展密钥为:
");
for(i=0;i{
printf("%c",key[i]);
}
}
for(i=0;i<26;i++)
{
for(j=0;j<26;j++)
{
table[i][j]=a[(j+i)%26];
}
}
printf("\n明文:
");
for(i=0;i{
//在表中进行逆查表找到明文字母
for(j=0;j<26;j++)
{
if(table[(key[i]-97)][j]==str[i])
printf("%c",table[0][j]);
}
}
printf("\n");
}
voidmenu()
{
printf("********************VigenereCipher加解密过程********************\n");
printf("1.加密\n");
printf("2.解密\n");
}
voidmain()
{
inti;
menu();
printf("请选择你要进行的操作:
\n");
scanf("%d",&i);
if(i==1)
{
system("cls");
encryption();
}
else
{
system("cls");
decryption();
}
}
2、Columnpermutationcipher
#include
#include
#include
//加密过程
voidencryption()
{
charkey[20];//密钥
charstr[100];//明文
intnum[20];//确定密文读取列数的顺序
chara[20][20];//保存明文的矩阵
intkey_len,str_len;///密钥和明文的长度
intline,t3,add;//填充的行数和需要补充的无效字符的个数
inti=0,j=0;
printf("请输入密钥:
");
scanf("%s",&key);
printf("请输入明文:
");
scanf("%s",&str);
key_len=strlen(key);//密钥长度
str_len=strlen(str);//明文长度
//计算矩阵的行数以及是否需要填充无效字符
t3=str_len%key_len;//多出来的字符
if(t3==0)
{
line=str_len/key_len;//明文矩阵的行数
add=0;//需要填充的无效字符的个数
}
else
{
line=str_len/key_len+1;//明文矩阵的行数
add=key_len-t3;//需要填充的无效字符的个数
}
//处理密钥,确定读取密文读取顺序
for(i=0;i{
num[i]=0;
for(j=0;j{
if(key[j]<=key[i])
{
num[i]=num[i]+1;
}
if(key[j]==key[i]&&j>i)//字符相同的情况
num[i]=num[i]-1;
}
}
printf("密文列的读取顺序:
");
for(i=0;iprintf("%d",num[i]);//输出密钥结果
printf("\n");
//将明文填充到矩阵当中
//如果需要在矩阵中添加无效字符q
if(add!
=0)
{
for(i=0;i{
str[str_len+i]='q';
}
}
for(i=0;i{
for(j=0;j{
a[i][j]=str[i*key_len+j];
}
}
printf("将明文装填到矩阵当中\n");//打印装填后的矩阵
for(i=0;i{
for(j=0;j{
printf("%c",a[i][j]);
}
printf("\n");
}
printf("密文为:
");
for(i=0;i{
for(j=0;j{
printf("%c",a[j][(num[i]-1)]);
}
}
printf("\n");
}
//解密过程
voiddecryption()
{
charkey[20];//密钥
charstr[100];//密文
intkey_len,str_len;///密钥和密文的长度
intnum[20];//确定读取列数的顺序
chara[20][20];//明文矩阵
intline;//行数
inti,j;
printf("请输入密钥:
");
scanf("%s",&key);
printf("请输入密文:
");
scanf("%s",&str);
key_len=strlen(key);//密钥长度
str_len=strlen(str);//密文长度
line=str_len/key_len;//行数
//处理密钥,确定读取密文读取顺序,以便恢复明文矩阵
for(i=0;i{
num[i]=0;
for(j=0;j{
if(key[j]<=key[i])
{
num[i]=num[i]+1;
}
if(key[j]==key[i]&&j>i)//字符相同的情况
num[i]=num[i]-1;
}
}
printf("密文列的读取顺序:
");
for(i=0;iprintf("%d",num[i]);//输出密钥结果
printf("\n");
//恢复明文矩阵
for(i=0;i{
for(j=0;j{
a[j][num[i]-1]=str[i*line+j];
}
}
printf("明文为");
for(i=0;i{
for(j=0;j{
printf("%c",a[i][j]);
}
}
printf("\n");
}
voidmenu()
{
printf("********************列置换密码加解密********************\n");
printf("1.加密\n");
printf("2.解密\n");
}
voidmain()
{
inti;
menu();
printf("请选择你要进行的操作:
\n");
scanf("%d",&i);
if(i==1)
{
system("cls");
encryption();
}
else
{
system("cls");
decryption();
}
}
七、思考题(必需回答)写明如下问题
1、Vigenere密码的原理是什么?
答:
原理是多表替代。
2、Vigenere密码的主要缺陷有哪些?
答:
主要缺陷是密钥的重复书写和密钥短。
3、对Vigenere密码的分析方法有哪几种?
答:
分析方法主要是Kasiski测试法和重合指数法。
4、对Vigenere密码的改进方法是什么?
答:
对Vigenere密码的改进方法是Autokey密码。
5、Columnpermutationcipher的原理是什么?
答:
原理是置换。
6、给定关键字为“experiment”,加密矩阵将包括几列,以及列置换的次序是什么?
答:
加密矩阵有10列,列置换的顺序为第1,10,7,2,8,4,5,3,6,9列。
7、简述对Columnpermutationcipher的分析方法。
答:
首先通过密文字符的长度确定矩阵的形状,之后进行频率分析来还原列的顺序。
8、Columnpermutationcipher的安全性增强方法是什么?
答:
使用Double-Transposition密码。
八、结束语
通过本次试验我对Vigenere加密算法和Columnpermutation密码有了更加全面深入的认识,以前的学习只是停留在理论层面,而这次课程给了我实践的机会。
通过实验很好的把古典密码应用于现代密码加解密技术中。
在这个过程中我也学到了很多关于编程方面的知识,提高了自己的编程水平。
九、参考文献
1、RichardJ.Spillman:
《CLASSICAL AND CONTEMPORARY CRYPTOLOGY》,清华大学出版社,2005-7
实验成绩
考查内容
分数
得分
做好实验内容的预习,写出预习报告
10
了解实验题目的调试方法
10
按实验要求预先设计好程序
10
认真记录实验数据并分析实验结果
10
实验后按要求书写实验报告,记录实验用数据及运行结果
30
创新能力强,在实验中设计的程序有一定的通用性,算法优化
20
实验过程中,具有严谨的学习态度,认真、踏实、一丝不苟的科学作风
10