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 }