词频分析适用情况
1、词频分析适用于一些代换密码。代换密码就是那种用代换的方法加密的密码。代换密码可以简单理解为明文和密文之间存在有一张表,每一个字母通过表变换后结果是唯一的。而我们词频分析的词频在这种表格变换下是不会改变的,这就给我们破译密码提供了入口(信息论还是什么理论里好像提到对于一个好的密码,攻击者无法从密文中获得明文的信息,所以说,这个代换密码就是👎辣)
2、词频分析需要获得较大量的密文。因为词频分析的基础是频率的计算,带有统计学的因素,只有样本足够多,分析的结果才会准确。
单表代换的词频分析
单表代换的分析比较简单(大概),用到的就是词频分析的基本手段。著名的单表代换密码有凯撒密码和仿射密码。
首先说说词频分析的依据,在英语文章中,不同字母出现的频率是不同的,比如 $ C $ 出现的频率要远高于 $ X $ (怎么有一种四六级的痛 ?) 。如前所述,如果加密的是单表代换,是不会改变其频率的,例如我们对 $ hello $ 做位移为 $ 1 $ 的位移加密得到 $ ifmmp $ ,可以看到 $ l $ , $ m $ 出现了两次,而 $ l $ 和 $ m $ 恰好是一组对应关系。
糟糕的是,在足够长的英语文章中,每个字母出现的频率是一个定值(大多数字母还是不一样的),而这种性质也被反映在了单表代换后的密文中。换句话说,密文中某个字母的频率其实反映了它对应的明文字母的频率,这就好像一个被加密为 $ a $ 的 $ z $ 在大喊“我是 $ z $ !”,你我们就可以很轻易地还原出它。下面给出26个字母出现的频率(方便起见写成了字典):
1 | word_frequency={'a':0.082,'b':0.015,'c':0.028,'d':0.043,'e':0.127,'f':0.022,'g':0.020,'h':0.061,'i':0.070,'j':0.002,'k':0.008,'l':0.040,'m':0.024,'n':0.067,'o':0.075,'p':0.019,'q':0.001,'r':0.060,'s':0.063,'t':0.091,'u':0.028,'v':0.010,'w':0.023,'x':0.001,'y':0.020,'z':0.001} |
当然了,单纯分析频率有时候不太有效,毕竟统计学规律还得看你的样本大小还有误差的事你把握不住,不过这么操作下来其实已经得到了相当一部分对应关系了,剩下的可以通过枚举判断解析明文的语义来确定。
多表代换的词频分析
多表代换就是很多个单表代换 多表代换可以理解为同一篇文章,不同的地方用了不同的单表代换,这个就比单纯的单表代换复杂了。比如著名的维吉尼亚密码。
多表代换之于单表代换的一个问题是多表代换有时候不同的明文会得到相同的密文(反之亦然),比如 $ hellohello $ 用密钥 $ ab $ 做维吉尼亚加密会得到 $ helloifmmp $ 。这个时候如果逐字分析,字母的频率就改变了(如原文 $ l $ 出现了四次但密文不存在重复四次的字母)。这是因为加密用到了两张表,其中奇数位字母用 $ a $ (0)加密,偶数位用 $ b $ (1),从而造成了一些重复。不过我们发现,如果已知密钥长度(换句话说就是知道用了几张表和哪些地方用了同一张表),那么我们可以利用单表分析的办法逐个还原密钥,所以现在压力来到了如何确定密钥长度上。
比较可靠的用于确定密钥长度的方法有两个。
首先是目测法 $ Kasisi $ 测试法,其原理是在密文中找到几个重复的字符串(长度最好大于3),然后计算这些字符串的间距,然后多次选取几个不同的字符串操作,最后求出这些间距的最大公因子。它的原理是,一篇文章中肯定存在几个相同的单词(比如 $ the $ ),我们假设两个 $ the $ 之间的距离是 $ s_1 $ ,再假设密钥长度为 $ k $ ,如果两个 $ the $ 恰好被加密成同样的密文,则说明 $ s_1 $ 是 $ k $ 的倍数。我们在获得多个 $ s $ 后求出它们的公约数,就很有可能是 $ k $ 了。
$ Kasisi $ 测试法有一个小问题,就是比较难用计算机语言形容,导致我们想要编程解决问题时有些困难,于是我们有了第二个方法——重合指数法。
重合指数法基于的事实是,对于足够长的英语文章,从其中取出两个相同字母的概率是一个定值。这个很好理解,因为字母出现的频率确定的,而这个重合的概率只和频率有关(其实还和文章字数有关,但是密码分析里默认明文和密文一样长了)。我们假设每个字母出现的频数(划重点,不是频率哦)用 $ f_i $ 表示,文章总字母数记为 $ n $ ,则
$$
Ic=\sum_{i=0}^{25}{\frac{f_{i}(f_{i}-1)}{n(n-1)}}
$$
于是,如果密钥长度不太长的时候,我们可以先假定密钥长度k,然后对密文进行分割( $ c_1 $ … $ c_k $ ),此时 $ c_i $ 就是单表代换的结果,我们计算它的 $ Ic $ ,得到 $ k $ 个 $ Ic $ 后计算平均值或者分别比较,如果和标准值比较近,说明预测准确。在确定了 $ k $ 以后,再对每一个 $ c_i $ 进行词频分析就可以得到它对应的密钥,最后再把这些密钥连起来就是整个加密方案的密钥。
[AFCTF2018]一道有趣的题目
1 | The 26 letters a, b, c, ..., y, z correspond to the integers 0, 1, 2, ..., 25 |
这里还有一个c.txt文件就不展示了,是一篇加密文章。
题目看着像仿射密码,但是仿射密码的$key_a$和$key_k$是固定的而本题两个参数分别由一个循环构成。这个就很像维吉尼亚密码和凯撒密码的关系,维吉尼亚密码其实就是凯撒密码中位移量变成了某个周期性变量。那么本题的解法就应该和维吉尼亚密码分析一样,首先根据重合指数分析密钥长度。
不过有趣的地方在于,这题中的两个参数是独立的,也就是说,假设$key_a$,$key_k$的周期分别为$a,k$,那么我们就可以得到$a*k$种加密公式(前提是里面没有重复)。
我们通过指数分析得到$k*a$的预计值后,可以按照一般的解仿射密码的办法求解线性同余方程组来确定每一个$(a,k)$组合;当然此题中a,k都只有26种情况(考虑到仿射密码要求$a$,26互素,实际还要少),爆破的话可以省去不少思考。具体的脚本思路写在注释里。
把这题搬出来还有一个目的就是这个脚本可以在日后遇到词频分的时候作为参考。
1 | import math |
一些题外话
虽然现在有很多在线解密网站可以直接爆破类似的词频分析密码,但是呢,我还是觉得懂一点原理总是有好处的。毕竟说真的,咱学个觅🐎要是最后全是用一些网站工具包做题的话,就好像在用网站和工具包做题一样。而且貌似有些题目网上不一定找得到解密网站(比如上面那题)。顺便附上一个维吉尼亚解密网站