实验 1-古典密码算法
一、 实验目的
通过编程实现替代密码算法和置换密码算法,加深对古典密码体系的了解,为以后深入
学习密码学奠定基础。
二、 实验原理
古典密码算法曾被广泛应用,大都比较简单。它的主要应用对象是文字信息,利用密码
算法实现文字信息的加密和解密。其中替代密码和置换密码是具有代表性的两种古典密
码算法。
1、 替代密码
替代密码算法的原理是使用替代法进行加密,就是将明文中的字符用其他字符替代后形
成密文。例如,明文字母 a、b、c、d,用 D、E、F、G 做对应替换后形成密文。
最早的替代密码是由 Julius Caesar 发明的 Caesar (恺撒)密码,又叫循环移位密码。
它的加密过程可以表示为下面的函数:
E(m) = (m+k ) mod n
其中,m 为明文字母在字母表中的位置数;n 为字母表中的字母个数;k 为密钥;E(m)为密
文字母在字母表中对应的位置数。
例如,对于明文字母 H,其在字母表中的位置数为 8,设 k=4,则按照上式计算出来的
密文为 L,计算过程如下:
解密算法是:m = D(L) =(L-k)mod 26
E(8) = (m+k ) mod n = (8+4 ) mod 26 = 12 = L
2、 置换密码
置换密码算法的原理是不改变明文字符,只将字符在明文中的排列顺序改变,从而实现
明文信息的加密。置换密码又称为换位密码。
矩阵换位法是实现置换密码的一种常用方法。它将明文中的字母按照给定的顺序安排在
一个矩阵中,然后又根据密钥提供的顺序重新组合矩阵中的字母,从而形成密文。例如,明
文为 attack begins at five ,密钥为 cipher ,将明文按照每行 6 个字母的形式排在矩
阵中,形成如下形式:
t
a
b e
a t
t
g
f
a
i
i
c
n
v
k
s
e
根据密钥 cipher 中各字母在字母表中出现的先后顺序,得到给定的一个置换:
f = 1 4 5 3 2 6
因此有:
密钥: 1 4
明文: a t
b e
a t
5
t
g
f
3
a
i
i
2
c
n
v
6
k
s
e
根据上面的置换,将原有矩阵中的字母按照第 1 列、第 4 列、第 5 列、第 3 列、第 2
列、第 6 列的顺序排列、则有下面的形式:
a a
b i
a i
t
e
t
从而得到密文:aacttkbingesaivfte
其解密过程是根据密钥的字母数作为列数,将密文按照列、行的顺序写出,再根据由
k
s
e
c
n
v
t
g
f
密钥给出的矩阵置换产生新的矩阵,从而恢复明文。
三、 实验环境
PC 机,C 或 C++编译环境
四、 实验内容和步骤
1、根据实验原理部分对替代密码算法的介绍,同时查找和学习相关知识,自己创建明文信
息,并选择一个密钥,编写替代密码算法的实现程序,实现加密和解密操作。
2、根据实验原理部分对置换密码算法的介绍,同时查找和学习相关知识,自己创建明文信
息,并选择一个密钥,编写置换密码算法的实现程序,实现加密和解密操作。
五、 算法设计
1、 替代密码
2、 置换密码
六、 程序流程图
七、 测试结果截图
图 1 替代密码测试结果
八、 总结体会
图 2 置换密码测试结果
1、 很久没有用到 C 语言了,这次再用 C 编写程序,有些生疏。写的代码不多,编译的
时候却会出现很多的错误。而且本次实验对字符,字符串,一维,二维数组用的比
较多,在使用的过程中经常需要查阅书籍才能保证程序不会出错。
2、 代码写好后我有将自己的代码给同学看,同学对我的程序的风格提出了几点很好的
建议:第一个,最重要的,写程序不要用 goto,那些标号会大大降低程序的可读性;
第二个, define 后面声明的常量最好全部大写,这样变量和常量就一目了然了;
第三个,声明变量的时候别偷懒,用 a 啊,b 啊这样一个字母的,写程序最重要的
就是自己思路要清晰,特别是大的工程,变量名太短了有时候写着写着自己都想不
起来那个变量是干什么的。密钥就用 key,矩阵就用 matrix。
九、 回答问题:试分析两种密码算法的安全性。
替代密码算法的安全性低于置换密码算法的安全性。替代密码是将字母的顺序循环
的移位,想要破解并不难。最多只需要尝试 25 次,就可以把原文解密出来了。而置换
密码算法比较复杂,密钥的改变,矩阵的行、列的大小的改变都会引起加密的方式的改
变,想要破解会比较麻烦。所以安全性要高很多。
十、 程序代码
1、替代密码
#include
#include
#define n 26
#define k 4
int main()
{
start:char c1[100];
char c2[100];
int i,c,len;
printf("please choose encode or deconde:1 for enconde,2 for decode,0 for exit\n");
scanf("%d",&c);
if (c==1)
{
//encode
pri1:
printf("please input the string:\n");
scanf("%s",c1);
len=strlen(c1);
for(i=0;i96)
c2[i]=(c1[i]+k-96) % n+96;
else if (c1[i]<91&&c1[i]>64)
c2[i]=(c1[i]+k-64) % n+64;
else if(c1[i]==' ')
c2[i]=c1[i];
else
{
printf("input error!please input again!");
goto pri1;
}
}
printf("output the string :");
puts(c2);
}
else if(c==2)
{
//decode
pri2:printf("please input the string:\n");
scanf("%s",c2);
len=strlen(c2);
for(i=0;i96)
c1[i]=(c2[i]-k-96+n) % n+96;
else if (c2[i]<91&&c2[i]>64)
c1[i]=(c2[i]-k-64+n) % n+64;
else if(c2[i]==' ')
c1[i]=c2[i];
else
{
printf("input error!please input again!");
goto pri2;
}
}
printf("output the string:");
puts(c1);
//退出
}
else if(c==0)
goto end;
else
printf("input error! please input again\n");
goto start;
//输入错误,重新输入
end:return 0;
}
2、置换密码
#include
#include
#define a 3
#define b 6
#define m a*b
int main()
{
//宏定义数组的行数为 a+1
//宏定义数组的列数为 b+1 ,也是密钥的数组的长度
//宏定义存放待解密的数组的大小为 a*b
char k[b];
char r[b];
char e[a][b];
char d[a][b];
char t,txt[m];
int c,f,i,j,o=0,len;
int s[b],s2[b];
数
//用于存放初始密钥字符串
//用于存放排序后的密钥字符串
//用于存放待加密的字符串
//用于存放待解密的字符串
//按照密钥字符出现的先后顺序对应存放二维数组的列
//输入密钥字符串,对密钥进行处理,得到密钥中各字母在字母表中出现的先后顺序
printf("输入密钥:");
gets(k);
for(i=0;i