恺撒加密与解密小程序
作者:kvew www.smatrix.org
先简单介绍下恺撒加密法,是一个很古老也很简单的加密方法,就是把信息中的字母右移N位,产生密文,比如"Z" 右移2位后为"B"。关于解密用到了一个统计规律,在大量的文献中字母"E"的出现频率是最高的,那么对于用该算法加密的文件,我们只要统计出密文中出现频率最高的字母,然后和"E"比较下,就能得出密钥key。当然好有很多改进的方案,比如两个字母的单词出现频率高的"IS",三个字母的单词"THE"出现的比较多等等。我这里只是简单实现一下加密解密,没有涉及到算法改进,甚至这个程序也会有某些问题,如果您能提出来,那真的是非常感谢了!
先说一下输入测试信息的规则,由于前面说到,求解密钥用的是"E"出现频率最高这点,所以在输入要加密的信息时人为的多写点E进去,大写小写的都无所谓!如果感兴趣,可以把该程序梢加修改,用于加密一篇英文文章,然后用解密函数解密。
源程序如下:
简单介绍下,这里只对字母加密,其他符号没有进行加密。定义char类型的时候定义为unsigned char,如果不定义为无符号类型的话,在对小写字母移位较大的情况下,其ASCII码值会超过127,这样就会出现异常。
#include <stdio.h>
#include <stdlib.h>
#include <stdlib.h>
char kaiser(int n){
unsigned char ch;
ch = getchar();
if(ch>=65&&ch<=90){ //如果是大写字母
ch = ch + n; //移位
if(ch<91) //移位后仍然在大写字母集中,直接返回
return ch;
else
return ch%90+64; //超出则转换下
}
else if(ch>=97&&ch<=122){ //如果是小写字母
ch = ch + n; //移位
if(ch<123) //移位后仍然在小写字母集,直接返回
return ch;
else
return ch%122+96; //超出则转换下
}
return ch; //如果是其他字符,则不加密照常输出
}
void write_file(){ //写文件函数
int n ;
unsigned char ch = 65 ; //先随便给个初始值,后面要用到它判断输入是否结束
FILE *fp;
if((fp = fopen("a.txt","w"))==NULL){ // 判断fopen的返回值,打开文件是否成功
printf("Error,can't open the file!/n");
exit(0);
}
printf("please input the key (0--25):/n");
scanf("%d",&n);
if(n<0||n>25){
printf("Error! Wrong key number!/n");
exit(0);
}
printf("Please input the file end with $/n");
while(ch!=36 ){ //如果成功,向里面写入,以 $ 结束
ch = kaiser(n); //把输入字符用kaiser加密法加密
fputc(ch,fp);
}
if(fclose(fp)){
printf("Can not close the file!/n");
}
}
void break_kaiser(){
int i,count,k;
int key;
int num[26] = {0}; //初始化数组
unsigned char ch,ch_b;
FILE *fp1,*fp2;
if((fp1=fopen("a.txt","r"))==NULL){ //以读的方式打开文件a.txt
printf("can not open the file a.txt!/n");
exit(0);
}
if((fp2=fopen("b.txt","w"))==NULL){ //以写的方式打开b.txt
printf("can not open the file b.txt!/n");
exit(0);
}
while(!feof(fp1)){
ch = fgetc(fp1);
printf("the ch in a.txt is:%c/n",ch); //这行可以注释掉,是显示读取细节的东西
if(ch>=65&&ch<=90){
num[ch-65]++;
printf("the num[%d] is %d/n",ch-65,num[ch-65]); //同上,可以注释掉
}
else if(ch>=97&&ch<=122){
num[ch-97]++;
printf("the num[%d] is %d/n",ch-97,num[ch-97]); //同上
}
}
if(fclose(fp1)){ //关闭目标文件a.txt
printf("Can not close the file!/n");
}
count = num[0];
for(i=0;i<26;i++){
printf("the num[%d] is %d/n",i,num[i]);
if(count<num[i]) {
count = num[i];
k = i; //记录下最大值的下标
}
}
printf("the max is %d and its index is %d/n",count,k);
ch_b = 65 + k; // 记录下出现次数最多的字符,以大写方式记录
key = ch_b - 69; //和 E 值相减,计算出key
if(key<0)
key = 26 + key;
printf("the key is: %d/n",key);
if((fp1=fopen("a.txt","r"))==NULL){ //再次以读的方式打开文件a.txt
printf("can not open the file a.txt!/n");
exit(0);
}
while(!feof(fp1)){ //如果没有读到文件结尾,那么继续读取
ch = fgetc(fp1);
if(ch>=65&&ch<=90){
ch = ch - key;
if(ch < 65)
ch = 90 - (64 - ch);
}
if(ch>=97&&ch<=122){
ch = ch - key;
if(ch < 97)
ch = 122 - (96 - ch);
}
fputc(ch,fp2);
}
if(fclose(fp2)){ //关闭文件b.txt
printf("Can not close the file!/n");
}
}
int main(){
write_file();
break_kaiser();
return 0;
}