离散数学的一道作业题。
题目如下:
It is known that the following crypted paragraph is encryted using a slighted enhanced Caesar encryption method of the form f(p)=(ap+b)mod29.
jgc!.chr, dhdw,nbn bn kdncy oh uxc jdru uxdul bh dh, qbfch nugcurx oj mgbuuch wdhq.dqcl rcgudbh wcuucgn dhy roakbhdubohn oj wcuucgn orr.g mbuxfdg,bhq jgc!.chrbcns aogcofcgl uxcgc bn d rxdgdrubnubr ybnugbk.uboh oj wcuucgn uxdu bn go.qxw, uxc ndac jog dwaonu
dww ndavwcn oj uxdu wdhq.dqcs
What is also known is the two most frequently used letters in the paragraph are t and e.The reference alphabet is an array of length 29 "abcdefghijklmnopqrstuvwxyz,.!", indicating that space is not handled during encryption (space remains space). Try to de-cypher
the message and give the plaintext.
简单理解就是解密一段文字,加密方式为f(p)=(ap+b)mod29的凯撒加密方式,字母表为"abcdefghijklmnopqrstuvwxyz,.!",且根据统计,t和e为英语中出现最多的字母。
破解的一般思路就是通过字母的频率求得对应的密钥,然后反解密文。求解过程如下。
统计字母出现
void analyze(char *c) { int a[26]={0}; int i=0,j; while(c[i]!='\0') { if(c[i]!='.'||c[i]!='!'||c[i]!=',') a[c[i]-'a']++; printf("%d\t",i++); } for(j=0;j<26;j++) { printf("%c:%d\n",j+'a',a[j]); } }
在main中调用。
int main() { char ch1[10000]; char hash[29]; printf("Input paragragh:\n"); gets(ch1); analyze(ch1); return 1; }
得到结果:
可治u和c为出现频率最高的两个字母。
在字母表中的顺序:
t-19 u-20 e-4 c-2
可以列出下面的式子:
(19a+b)mod29=20
(4a+b)mod29=2
但是还不能求得a和b的值,需要用一段程序枚举求得。
#include<stdio.h> void getA() { int a,b; for(a=0;a<20;a++) { b=20-(19*a)%29; if((4*a+b)%29==2) printf("%d,%d\n",a,b); } } int main() { getA(); return 1; }
得到a=7,b=3.
由于f(p)是满足双射关系的,即两两对应,可以将明暗文对应关系放在Hash表中。
char alphabet[]="abcdefghijklmnopqrstuvwxyz,.!"; void createHash(char *c,int a,int b,int d) { int i; char encode[29]; for(i=0;i<29;i++) { encode[i]=alphabet[(a*i+b)%d]; printf("%c",encode[i]); } for(i=0;i<29;i++) { c[encode[i]-'a']=alphabet[i]; } }
这样就可以通过密文直接hash到明文了。
解密函数就最简单了。
void decypher(char *c,char *hashmap,int a,int b,int d) { int i=0; int char_pos;//record the caractor's position while(c[i]!='\0') { char_pos=c[i]-'a'; //printf("char_pos:%d\n",char_pos); if(c[i]!=' ') { printf("%c",hashmap[char_pos]); } else { printf(" "); } i++; } }
完整的程序如下:
#include<stdio.h> void analyze(char *c); void decypher(char *c,char *hashmap,int a,int b,int d); void createHash(char *c,int a,int b,int d); char alphabet[]="abcdefghijklmnopqrstuvwxyz,.!"; int main() { char ch1[10000]; char hash[29]; printf("Input paragragh:\n"); gets(ch1); analyze(ch1); printf("\nAfter decyphered:\n"); createHash(hash,7,3,29); decypher(ch1,hash,7,3,29); printf("\n%s\n",ch1); return 1; } void analyze(char *c) { int a[26]={0}; int i=0,j; while(c[i]!='\0') { if(c[i]!='.'||c[i]!='!'||c[i]!=',') a[c[i]-'a']++; printf("%d\t",i++); } for(j=0;j<26;j++) { printf("%c:%d\n",j+'a',a[j]); } } void decypher(char *c,char *hashmap,int a,int b,int d) { int i=0; int char_pos;//record the caractor's position while(c[i]!='\0') { char_pos=c[i]-'a'; //printf("char_pos:%d\n",char_pos); if(c[i]!=' ') { printf("%c",hashmap[char_pos]); } else { printf(" "); } i++; } } void createHash(char *c,int a,int b,int d) { int i; char encode[29]; for(i=0;i<29;i++) { encode[i]=alphabet[(a*i+b)%d]; printf("%c",encode[i]); } for(i=0;i<29;i++) { c[encode[i]-'a']=alphabet[i]; } printf("\n%s\n",alphabet); }
最终运行结果:
解密结果:
frequency analysis is based on the fact that, in any given stretch of written language, certain letters and combinations of letters occur withvarying frequencies. moreover, there is a charactistic distribution of letters that is roughly the same for almost
all samples of that language.