一、实验内容
掌握多表古典加密方法,能用高级语言实现古典加密方法。多表古典加密方法主要有Playfair(替换)体制、Vigenere(维热纳尔密码-维热纳尔)体制、Beaufor()体制、Vernam体制和Hill体制,用高级语言实现所有体制的加密和解密算法。
二、多表古典加密算法的基本原理及其算法流程
根据密码算法加解密时使用替换表多少的不同,替代密码又可分为单表替代密码和多表替代密码。
单表替代密码的密码算法加解密时使用一个固定的替换表。单表替代密码又可分为一般单表替代密码、移位密码、仿射密码、密钥短语密码。
多表替代密码的密码算法加解密时使用多个替换表。 多表替代密码有弗吉尼亚密码、希尔(Hill)密码、一次一密钥密码、Playfair密码。
单表替代密码单表替代密码对明文中的所有字母都使用一个固定的映射(明文字母表到密文字母表)。设A={a0, a1,…, an-1}为包含了n个字母的明文字母表;
B={b0, b1,…, bn-1} 为包含n个字母的密文字母表,单表替代密码使用了A到B的映射关系:f:A→B, f ( ai )= bj
一般情况下,f 是一一映射,以保证加密的可逆性。加密变换过程就是将明文中的每一个字母替换为密文字母表的一个字母。而单表替代密码的密钥就是映射f或密文字母表。经常密文字母表与明文字母表的字符集是相同的,这时的密钥就是映射f。下面给出几种典型的单表替代密码。
⒈一般单表替代密码
一般单表替代密码的原理是以26个英文字母集合上的一个置换π为密钥,对明文消息中的每个字母依次进行变换。可描述为:明文空间M和密文空间C都是26个英文字母的集合,密钥空间K={π:Z26→Z26|π是置换},是所有可能置换的集合。
对任意π∈K,定义:
加密变换:eπ(m)=π(m)=c
解密变换:dπ(c) = π-1(c)=m, π-1是π的逆置换。
例:设置换π的对应关系如下:
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
q w e r t y u i o p a s d f g h j k l z x c v b n m
试用单表替代密码以π为密钥对明文消息message加密,然后写出逆置换 ,并对密文解密。
解:以π为密钥用单表替代密码对明文消息message加密,所得
密文消息为: π(m) π(e) π(s) π(s) π(a) π(g) π(e)=dtllqut
一般单表替代密码算法特点:
▲密钥空间K很大,|K|=26!=4×1026 ,破译者穷举搜索计算不可行,1微秒试一个密钥,遍历全部密钥需要1013 年。
▲移位密码体制是替换密码体制的一个特例,它仅含26个置换做为密钥空间。
密钥π不便记忆。
▲针对一般替换密码密钥π不便记忆的问题,又衍生出了各种形式单表替代密码。
⒉移位密码
明文空间M、密文空间C都是和密钥空间K满足,即把26个英文字母与整数0,1,2,…,25一一对应。
加密变换,E={E:Z26→Z26, Ek (m) = m + k (mod26)| m∈M, k∈K }
解密变换,D={D:Z26→Z26, Dk (c) = c-k (mod26)| c∈C, k∈K }
解密后再把Z26中的元素转换英文字母。
显然,移位密码是前面一般单表替代密码的一个特例。当移位密码的 密钥k=3时,就是历史上著名的凯撒密码(Caesar)。根据其加密函数特 点,移位密码也称为加法密码。
⒊仿射密码
仿射密码也是一般单表替代密码的一个特例,是一种线性变换。仿射密码的明文空间和密文空间与移位密码相同,但密钥空间为 K={(k1,k2)| k1,k2∈Z26,gcd(k1,26)=1}
对任意m∈M,c∈C,k = (k1,k2)∈K,定义加密变换为 c = Ek (m) = k1 m +k2 (mod 26)
相应解密变换为: m = Dk (c) = k1 (c-k2) (mod 26)
其中,K1 k1=1mod26 。很明显,k1=1时即为移位密码,而k2=1则称为乘法密码。
⒋密钥短语密码
选用一个英文短语或单词串作为密钥,去掉其中重复的字母得到一个无重复字母的字符串,然后再将字母表中的其它字母依次写于此字母串后,就可构造出一个字母替代表。当选择上面的密钥进行加密时,若明文为“china”,则密文为“yfgmk”。显然,不同的密钥可以得到不同的替换表,对于明文为英文单词或短语的情况时,密钥短语密码最多可能有26!=4×1026个不同的替换表。
多表替代密码
单表替代密码表现出明文中单字母出现的频率分布与密文中相同, 多表替代密码使用从明文字母到密文字母的多个映射来隐藏单字母出现 的频率分布,每个映射是简单替代密码中的一对一映射多表替代密码将 明文字母划分为长度相同的消息单元,称为明文分组,对明文成组地进 行替代,同一个字母有不同的密文,改变了单表替代密码中密文的唯一 性,使密码分析更加困难。
多表替代密码的特点是使用了两个或两个以上的替代表。著名的维吉尼亚密码和Hill密码等均是多表替代密码。
⒈维吉尼亚密码
维吉尼亚密码是最古老而且最著名的多表替代密码体制之一,与位移密码体制相似,但维吉尼亚密码的密钥是动态周期变化的。
该密码体制有一个参数n。在加解密时,同样把英文字母映射为0-25的数字再进行运算,并按n个字母一组进行变换。明文空间、密文空间及密钥空间都是长度为n的英文字母串的集合,因此可表示
加密变换定义如下:
设密钥 k=(k1,k2,…,kn), 明文m=(m1,m2,…,mn), 加密变换为:
Ek(m)=(c1,c2,…,cn),
其中ci(mi + ki)(mod26),i =1,2,…,n
对密文 c=(c1,c2,…,cn), 解密变换为:
Dk(c)=(m1,m2,…,mn), 其中 mi=(ci -ki)(mod26),i =1,2,…,n
三、设计要求:
编程实现移位密码、仿射密码、维吉尼亚密码和置换密码,要求如下:
1、程序输入为明文和密钥(对于仿射密码应该检查密钥的合法性);
2、执行加密和解密过程;
3、输出加密的密文和解密恢复的明文,并和开始输入的明文进行比较。
四、设计步骤:
程序在JAVA环境中实现,由于编程基础不够扎实可能程序没有明显的体现出面向对象的风格,期望老师见谅。
先设计一个图形界面。
在同一个类中加入各个算法即可。
详细情况可以参考源代码
1.5实验小结
本次实验难度不大,只是要对各个算法有一个比较深刻的认识即可。
在实验中,为了兼顾图形界面,我编写了较长时间。
部分源代码:
- public void ywjiami(){
- String s1;
- String s2;
- String es="";
- char zifu[];
- s1=t1.getText();//输入明文
- s2=t4.getText();//输入密钥
- int key;
- key=Integer.parseInt(s2);
- zifu = s1.toCharArray();
- /*for (int i = 0;i<zifu.length ;i++ )
- {
- zifu[i]=(char)(((zifu[i]-97+a)%26)+97);
- }*/
- for(int i=0;i<zifu.length;i++) {
- char c=zifu[i];//=zifu.charAt(i);
- if(c>='a' && c<='z') // 是小写字母
- {
- c+=key%26; //移动key%26 位
- if(c<'a') c+=26; // 向左超界
- if(c>'z') c-=26; // 向右超界
- }
- else if(c>='A' && c<='Z') // 是大写字母
- {
- c+=key%26;
- if(c<'A') c+=26;
- if(c>'Z') c-=26;
- }
- es+=c;
- }
- String s3=new String(es);
- s3s3=s3.toUpperCase();
- t2.setText(s3);
- }
- /*移位解密算法*/
- public void ywjiemi(){
- String s1;
- String s2,es="";
- char zifu[];
- s1=t2.getText();
- s2=t4.getText();
- int bb,key;
- bb=Integer.parseInt(s2);
- key=-bb;
- zifu = s1.toCharArray();
- /*for (int i = 0;i<zifu.length ;i++ )
- {
- zifu[i]=(char)(((zifu[i]-97-a)%26)+97);
- }*/
- for(int i=0;i<zifu.length;i++) {
- char c=zifu[i];//=zifu.charAt(i);
- if(c>='a' && c<='z') // 是小写字母
- {
- c+=key%26; //移动key%26 位
- if(c<'a') c+=26; // 向左超界
- if(c>'z') c-=26; // 向右超界
- }
- else if(c>='A' && c<='Z') // 是大写字母
- {
- c+=key%26;
- if(c<'A') c+=26;
- if(c>'Z') c-=26;
- }
- es+=c;
- }
- String s3=new String(es);
- s3s3=s3.toLowerCase();
- t3.setText(s3);
- }
- /*求最大公约数-辗转相除法*/
- int gcd(int a, int b)
- {
- int k = 0;
- do
- {
- k = a%b;
- a = b;
- b = k;
- }while(k!=0);
- return a;
- }
- /*求模逆*/
- int Ni(int a, int b)
- {
- int i = 0;
- while(a*(++i)%b!=1);
- return i;
- }
- /*仿射加密算法*/
- public void fcjiami(){
- int i=0, a=0, b=0, tmp;
- String s1;
- String s2;
- char zifu[];
- s1=t1.getText();
- s2=t4.getText();
- a=Integer.parseInt(s2)/10;
- b=Integer.parseInt(s2)%10;
- zifu = s1.toCharArray();
- /*如果输入密钥不合法则显示密钥错误*/
- if(gcd(a,26)!=1)
- {
- String s3=new String();
- s3="密钥错误";
- t3.setText(s3);//密钥
- }
- for(i=0; i<zifu.length; i++)
- {
- if(zifu[i]>96&&zifu[i]<123)
- zifu[i] = (char)((a*(zifu[i]-97)+b)%26+65);
- else if(zifu[i]>64&&zifu[i]<91)
- zifu[i] = (char)((a*(zifu[i]-65)+b)%26+65);
- }
- String s4=new String(zifu);
- t2.setText(s4);
- }
- /*仿射解密算法*/
- public void fcjiemi(){
- int i=0, a=0, b=0, tmp;
- String s1;
- String s2;
- char zifu[];
- s1=t1.getText();
- s2=t4.getText();
- /*在密钥输入文本框中输入2位密钥首先转换成2位整数在利用‘/’和‘%’算法求出2个合法密钥在进行计算*/
- a=Integer.parseInt(s2)/10;
- b=Integer.parseInt(s2)%10;
- zifu = s1.toCharArray();
- for(i=0; i<zifu.length; i++){
- if(zifu[i]>64&&zifu[i]<91)
- {
- tmp = Ni(a,26)*((zifu[i]-65)-b);
- if(tmp<0)
- zifu[i] = (char)(tmp%26+26+97);
- else
- zifu[i] = (char)(tmp%26+97);
- }
- }
- String s4=new String(zifu);
- t3.setText(s4);
- }
- /*维吉尼亚加密算法*/
- public void wjnyjiami()
- {
- int i,j,s=0;
- int k=0 ;
- String s1;
- String s2;
- char zifu[],miyao[];
- s1=t1.getText();//输入明文
- s2=t4.getText();//输入密钥
- miyao =s2.toCharArray();
- zifu = s1.toCharArray();
- for(i=0; i<zifu.length; i++){
- zifu[i] = (char)((zifu[i]-97+(miyao[k%miyao.length]-97))%26+97);
- k++;
- }
- String s3=new String(zifu);
- s3s3=s3.toUpperCase();
- t2.setText(s3);
- }
- /*维吉尼亚解密算法*/
- public void wjnyjiemi()
- {
- int i,j,k=0,tmp;
- String s1;
- String s2;
- char zifu[],miyao[];
- s1=t2.getText();//密文
- s2=t4.getText();//密钥
- s1s1=s1.toLowerCase();
- miyao =s2.toCharArray();
- zifu = s1.toCharArray();
- /*解密算法中会出现减出负数的状况如果出现负数加26解决问题*/
- for (i =0;i<zifu.length ;i++ ){
- tmp = (zifu[i]-miyao[k%(miyao.length)]);
- zifu[i]=(char)(tmp+65);
- if (tmp<0)
- zifu[i] =(char)(tmp+65+26);
- k++;
- };
- String s3=new String(zifu);
- s3s3=s3.toLowerCase();
- t3.setText(s3);
- }
注:*********由于源代码过大,我就上传到下载中心了,可复制下面连接去下载********
http://down.51cto.com/data/417584