用计算思维写密码程序
作者:王兆远1 何祎1 韩彦强1
(南开大学 物理科学学院,天津 300071)
内容提要:简单介绍了密码学的起源、介绍了几种简单密码并给出了代码。 关键字:计算思维、密码、凯撒密码、Atbash密码、换位密码
在有些时候,信息的保密性直接决定信息的价值,尤其是在涉及国家的机密或个人的隐私的时候。在这些时候,我们将需要将信息变成只有自己人才明白的“暗语”,而使外来人不知所云。在密码学中这一过程称为加密(encryption),加密前的信息称为明文(clear text),加密过后的信息称为密文(cipher text),而密钥是打开加密的钥匙,通常它是在明文转换为密文或将密文转换为明文的算法中输入的一种参数。用来传递加密后的信息的载体是加密旨,由于加密的方法多种多样,加密旨的形式也多种多样,密码像蛋白质分子一样千奇百怪。
密码学是一个神秘而吸引人的学科。它在人类历史上起到了独特的作用,早在古罗马时代密码就出现在了战争中,用来秘密地传达消息。在《高卢战记》中恺撒就记录了自己使用密码来传达军事命令的策略,他由此成为历史上第一个使用加密旨的将领。于是他所使用的这种密钥为3的移位密码被称为恺撒密码。二战时密码战的博弈几乎
同战场上的厮杀一样激烈,德国开始使用当时世界上最先进的Enigma密码机,而英国建造了“炸弹”机专门用来破译德军的密码;太平洋战场上,美军用“钓鱼”法巧妙破译了日军的情报。到了今天,人们一方面在不断求索着更好的加密算法用来保护信息的安全,另一方面也在不断研究密码的破译来进行间谍或反恐工作。
由于我们在密码学和编程方面知识的局限,本文的讨论仅限于用计算思维给出几个简单密码的算法。
1.凯撒密码
这种密码因为首先被裘里斯·凯撒使用并记载而闻名。它是一种以26个罗马字母(即拉丁字母)为基础的替换密码,所谓替换,意即使26个字母中的每个都有唯一另一个和它对应。凯撒密码的替换规则是将每个字母换成后移3位的另一个字母(例如a换为d)。它又被称为移位密码,这可以说是最简单的替换密码了。它在专业加密中已经被淘汰,而由它发展出的ROT13如今经常可见于英语社会娱乐性的言论中,用以隐晦地表达一些看法。后来在凯撒密码的基础上还形成著名的多表替换密码——维吉尼亚密码(本文不讨论此密码)。
想要将这样一个密码用算法实现,我们很容易想到用英文字母在ASCII码中的连续性。定义一个字符串,将原文赋值给它。将串中每个字符的值加上一个移位值,输出加密后的字符串。而在ASCII码中不仅有英文字母,还有其他字符如标点。考虑到这一点,可以将移位的范围拓延到更大的范围内(移位值可以取-33~5,下面的程序中缩小了范围),只要不替换为不能输出的字符。而解密程序只要将移位
值取加密时的相反数。最后用do while语句使之可以连续地执行加密或解密。该程序代码如下:
#include<iostream>
using namespace std;
int main()
{
char jud,A[100],B[100];
int key,n;
do
{
cout<<"请输入密钥值n(0<n<5):";
cin>>key;
cout<<"请输入密文:";
rewind(stdin);
gets(A);
n=strlen(A);
for(int i=0;i<=n-1;i++)
B[i]=A[i]-key;
B[n]=0;
cout<<"加密后的文字为:"<<B<<endl;
cout<<"是否继续执行该程序?(输入Y继续执行)";
cin>>jud;
}while(jud=='Y');
return 0;
}
2.Atbash密码
Atbash源于希伯来文,转化到罗马字母中。从a到z26个字母分别编号0到25,每个字母取其值对25的补码所对应的字母(如a变成z、b变成y)。这个过程依靠减法运算即可完成,且加解密的算法完全相同。给出算法如下:
#include<iostream>
using namespace std;
int main()
{
cout<<"Atbash的加密和解密算法相同";
char e;
} do{ cout<<"请输入原文:"<<endl; char a[100],b[100]; cin>>a; bool j=1; int n,i; n=strlen(a); for(i=0;i<=n-1;i++) { if(a[i]>=97&&a[i]<=122) b[i]=122-a[i]%97; else{ j=0; cout<<"输入有误"<<endl; break; } } b[n]=0; if(j) cout<<"加密后的文字为:"<<endl<<b<<endl; cout<<"是否继续执行?(是Y)"<<endl; cin>>e; }while(e=='Y'); return 0;
3.换位密码
以上两种密码都属于简易换位密码,它们有一个共同的缺陷—— 每个字母对应唯一的另一个字母,这样就可以通过分析字符出现频率找出它所代表的字母。
而换位密码避免了这种缺陷,它不属于替换密码,而是打乱字母的顺序。先将字母写成一定列数的矩形,例如:
原文是:COMPUTER CRAPHICS MAY BE SLOW BUT AT LEAST ITS EXPENSIVE
C O M P U T E R C R
A P H I C S M A Y B
E S L O W B U T A T
L E A S T I T S E X
P E N S I V E
竖着读出的文字即为加密后的文字:CAELP OPSEE MHLAN PLOSS UCWTI TSBIV EMUTE RATSG YAERB TX
在写这样一个程序时显然要用到二维数组。将原文的字符串转变成为二维字符数组A[i][j](i=j=const int),然后做B[j][i]=A[i][j]的变换输出。这种密码的加解密程序也是完全相同的。在不使用动态数组的情况下,需要限定密码的最大位数,最后几位采用了全部以相同字母补全的方法。下面是我们写出的代码:
#include<iostream>
using namespace std;
int main()
{
int n;
char jud,A[8][8],B[8][8],a[100];
do
{
cout<<"请输入文字";
rewind(stdin);
gets_s(a);
n=strlen(a);
for(int i=0;i<=n-1;i++)
{
int j1=i/8,j2=i%8;
A[j1][j2]=a[i];
}
for(int i=n;i<=63&&i>=n;i++)
A[i/8][i%8]='a';
cout<<"原文是:";
for(int i=0;i<=63;i++)
{
int j1=i/8,j2=i%8;
cout<<A[j2][j1];
}
cout<<"是否继续执行该程序?(输入Y继续执行)";
cin>>jud;
}while(jud=='Y');
}
参考资料:
[1]:密码学_百度百科。http://baike.baidu.com/view/25311.htm
[2]:凯撒密码_百度百科。http://baike.baidu.com/view/270827.htm?fromId=73853
[3]:Atbash密码-Wikipedia.http://en.wikipedia.org/wiki/Atbash
[4]:换位密码_百度百科。http://baike.baidu.com/view/79245.htm