Caesar 密码只有25种可能的秘钥,远不够安全。 如果让每个明文字母对应的密文字母没有规律,那么安全程度会提升很多, 比如这章所讲的单表代替密码, 思路如下:

让明文字母中的每一个字母固定地和任意的一个字母交换,如果A-> C, E->Z, B->X,这样第一个字母就可以和26个字母中的任意一个交换,第二个字母就可以和剩下的25个字母中的任意一个交换。。。

那么可能的结果就有26!,大于4*10^26。

比如下面的加密过程:

先确定秘钥:A->C, B->Z,C->X.......I->A.......M->N.....J->Q.....E->W......R->B....Y->R

那么:
明文: IAMJERRY

密文: ACNQWBBR

这样加密之后,如果使用Caesar的穷举解密法的话,那么难度和计算量就直接上升了很多个数量级, 看似这样的加密已经比较安全了, 但是人民大众的智慧是无穷的,可以换一种思路来解密:

每个字母在使用频率上是不一样的, 比如E肯定比Z出现在单词当中的频率高得多, 那么通过统计我们可以算出每个字母在单词中出现的频率, 比如下图

英文字母使用频率统计

当密文长度达到一定程度是,通过分析每个字母出现的频率, 在和上图对比,并结合实际的语义, 就能很好的破解密文。

 来个java 加密实例:

 1 public class SingleReplace {
 2     public static final int[] key = {25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0};
 3 
 4     private static int char2int(char c){
 5         return (int)c - 97;
 6     }
 7     private static char int2char(int v){
 8         return (char)(v+97);
 9     }
10     public static String encode(String str){
11         str = str.toLowerCase(Locale.ENGLISH);
12         char[] chars = str.toCharArray();
13         char[] encodes = new char[chars.length];
14         int currentCharV;
15         for(int i = 0 ; i < chars.length ; i ++){
16             currentCharV = char2int(chars[i]);
17             if(currentCharV < 0 || currentCharV > 25){
18                 encodes[i] = chars[i];
19             }else{
20                 encodes[i] = int2char(key[currentCharV]);
21             }
22         }
23         return new String(encodes);
24     }
25     public static void main(String[] args){
26         String test = "abcdefghijklmnopqrstuvwxyz";
27         System.out.println(encode(test));
28     }
29 }