任成风
2018年5月20日星期日
博客首发地址:个人博客网站 http://fairycity.wang,内容以个人博客为主,修正后的博文见个人博客,请点击访问。
本文的框架:
摘要和关键字: 1、 引言 2、 凯撒密码(Caesar)基本原理 3、 凯撒密码(Caesar)加密算法 4、 凯撒密码(Caesar)解密算法 5、 C/C++程序框架 6、 结束语 |
摘要:凯撒密码(Caesar)是一种简单的代换密码,即将一个字符按一定的规则简单的代换为另一个字符实现加密。在本文中,我将站在一个“计算机密码编码学与网络安全”课程学习者的角度,与你一起学习和了解凯撒密码(Caesar)。本文将从它的基本原理,加密算法实现,解密算法实现,简单测试的C++程序等方面和你分享一些学习心得。
关键词:凯撒,caesar,加密,加密
1、 引言
凯撒密码(Caesar)是一种代换密码,他是经典的古典密码算法之一,它的基本思想是通过把字母移动一定的位数来实现加密和解密。明文中的所有字母都在字母表上向后(或向前)按照一个固定数目进行偏移后被替换成密文。例如,当偏移量是3的时候,所有的字母A将被替换成D,B变成E,以此类推X将变成A,Y变成B,Z变成C。由此可见,位数就是凯撒密码加密和解密的密钥。(百度百科)
凯撒密码是一种单字母加密的密码,明文密文一一对应,明文做的简单变换变成密文的过程,可以看做明文移动N位取出N处字母的过。虽说这个加密算法极为简单,但对初学者理解加密解密很有帮助,所以我严格按照老师的要求,写了一下代码吗,算是巩固学习的内容了。
2、 凯撒密码(Caesar)基本原理
我们知道,字母表一共有26个英文字母,我们选择凯撒密码实现一个加密时,我们需要将某个明文字母做N位偏移得到密文,这个N最多为26,而且偏移为26时和偏移为0时一样,明文和密文对应相等,实际上可以说最大的偏移量为25,这里的偏移量是这个加密解密算法的核心,我们可以说他就是秘钥。
这个对应过程的计算,我们是通过求模运算来实现的。例如上述提到的偏移量为3的凯撒密码,我们可以得到这样的加、解密公式:
加密公式: f(a)=(a+3) mod 26 解密公式: f(a)=(a+23) mod 26 |
上述公式是偏移量为3(秘钥为3)的凯撒密码的计算方法,同理,我们将上述式子中的3换成N,23换成(26-N)就可以得到秘钥为N的凯撒密码的计算方法了。
加密公式: f(a)=(a+N) mod 26 解密公式: f(a)=(a+(26-N)) mod 26 |
废话就说到这里,下面开始实实在在的代码。
3、 凯撒密码(Caesar)加密算法
要实现凯撒密码(Caesar)加密算法,我们只需要写一段代码或者更为准确的说写一个函数实现上面的加密公式就好。
实际上写代码的过程中,我们比较容易出错的是模运算的实现,在我们的理解中,不知不觉的把A和a都默认为第0个字符,如A偏移为3的时候,(0+3)mod 26等于3,对应的是第3个字符,这里得到的是D而不是C,类似于数组的逻辑。那么我们要怎么用代码来实现呢?
if(strI[i] >= 'A' && strI[i] <= 'Z') { strI[i] = ((strI[i]-'A')+numB)%26+'A'; } else if(strI[i] >= 'a' && strI[i] <= 'z') { strI[i] = ((strI[i]-'a')+numB)%26+'a'; } |
我们将处理一串字符的代码封装成函数可以得到:
void Encry(char *strI,int numB,int model) //明文串 秘钥 功能模式 { if(model==1) { for(int i=0; i<strlen(strI); i++) { if(strI[i] >= 'A' && strI[i] <= 'Z') { strI[i] = ((strI[i]-'A')+numB)%26+'A'; } else if(strI[i] >= 'a' && strI[i] <= 'z') { strI[i] = ((strI[i]-'a')+numB)%26+'a'; } } cout<<"加密完成:"<<strI<<endl; FileOut(strI); cout<<"已输出到文件!"<<endl; } else { cout<<"该模式不支持此项功能!"<<endl; } } |
4、 凯撒密码(Caesar)解密算法
在这个密码算法中,写完加密算法解密算法就简单多了。我们可以这样理解,“哪里来的回哪里去”“怎么移动得来的,我们移动回去就好了”。但是为了规则的一致性,我们不妨可以这样想,我们继续移动,当他转一个圈子又回到原来的地方了,但是当他转到原来的明文的地方就停下了呢?(26-N)就是他要停下的地方。
这样我们可以类比加密算法得到解密算法。
void Decry(char *strI,int numB,int model) 明文串 秘钥 功能模式 { if(model==2) { int num; num=26-numB; for(int i=0; i<strlen(strI); i++) { if(strI[i] >= 'A' && strI[i] <= 'Z') { strI[i] = ((strI[i]-'A')+num)%26+'A'; } else if(strI[i] >= 'a' && strI[i] <= 'z') { strI[i] = ((strI[i]-'a')+num)%26+'a'; } } cout<<"解密完成:"<<strI<<endl; } else { cout<<"该模式不支持此项功能!"<<endl; } } |
5、 C/C++程序框架
至于我们的测试主程序,我们只需要调用上述的加密函数、解密函数就可以了,搭主框架的时候时,应该做到良好的人机交互帮助用户使用程序。
int main() { char str[N]; int model; int numB;
while(1) { cout<<"凯撒密码:请选择模式:\n"; cout<<"1.加密\n"; cout<<"2.解密\n"; cout<<"3.退出\n"; cin>>model; cout<<endl;
switch(model) { case 1: cout<<"请输入要加密的字符串:"; cin>>str; cout<<"请输入该密码算法的偏移数量:"; cin>>numB; Encry(str,numB,model); cout<<endl; break; case 2: cout<<"请输入要解密的字符串:"; cin>>str; cout<<"请输入原密码算法的偏移数量:"; cin>>numB; Decry(str,numB,model); cout<<endl; break; case 3: return 0; break; default: break; } } return 0; } |
6、 结束语
我们在做加密解密实验的时候,可能会用到文件。
一般两个人一个小组,其中一个把明文加密后得到的密文和秘钥发送给另一个人,再由另一个解密,看结果是不是第一个人输入的明文。这样我们可能会用到文件,把加密后的内容写入一个文件。
文章到这里,凯撒加密解密算法的实现基本上完成了,从原理到具体代码,我要说的大致如此。
参考资料:
【1】 密码编码学和网络安全第五版。
【2】 百度百科。
附录:完整代码和运行结果
#include<stdio.h> #include<iostream> #include<stdlib.h> #include <string.h>
#define N 100 using namespace std; //凯撒密码 //加密公式 f(a)=(a+3) mod 26 //解密公式 f(a)=(a+23) mod 26
void Encry(char *strI,int numB,int model);//加密公式函数 void Decry(char *strI,int numB,int model);//解密公式函数 int FileOut(char *strI); int main() { char str[N]; int model; int numB;
while(1) { cout<<"凯撒密码:请选择模式:\n"; cout<<"1.加密\n"; cout<<"2.解密\n"; cout<<"3.退出\n"; cin>>model; cout<<endl;
switch(model) { case 1: cout<<"请输入要加密的字符串:"; cin>>str; cout<<"请输入该密码算法的偏移数量:"; cin>>numB; Encry(str,numB,model); cout<<endl; break; case 2: cout<<"请输入要解密的字符串:"; cin>>str; cout<<"请输入原密码算法的偏移数量:"; cin>>numB; Decry(str,numB,model); cout<<endl; break; case 3: return 0; break; default: break; } }
return 0; }
void Encry(char *strI,int numB,int model) {//明文串 秘钥 功能模式 if(model==1) { for(int i=0; i<strlen(strI); i++) { if(strI[i] >= 'A' && strI[i] <= 'Z') { strI[i] = ((strI[i]-'A')+numB)%26+'A'; } else if(strI[i] >= 'a' && strI[i] <= 'z') { strI[i] = ((strI[i]-'a')+numB)%26+'a'; } } cout<<"加密完成:"<<strI<<endl; FileOut(strI); cout<<"已输出到文件!"<<endl; } else { cout<<"该模式不支持此项功能!"<<endl; } }
void Decry(char *strI,int numB,int model) { if(model==2) { int num; num=26-numB; for(int i=0; i<strlen(strI); i++) { if(strI[i] >= 'A' && strI[i] <= 'Z') { strI[i] = ((strI[i]-'A')+num)%26+'A'; } else if(strI[i] >= 'a' && strI[i] <= 'z') { strI[i] = ((strI[i]-'a')+num)%26+'a'; } } cout<<"解密完成:"<<strI<<endl; } else { cout<<"该模式不支持此项功能!"<<endl; } }
int FileOut(char *strI) { FILE *fp = NULL; int iWrite=0; int len=strlen(strI);
if( strI == NULL || len ==0 ) return false;
//! 打开文件句柄 if( (fp = fopen( "密文.txt","w" )) == NULL ) // 文本模式写 return false;
iWrite = fwrite(strI, 1, len, fp ); fclose(fp);
if( iWrite>0 ) return true; else return false; } |
运行结果:
完