天天看点

单字母密码密码分析(下)

上一篇我们分析了单表替换破译的思路,下面看看具体的实现过程吧~

2. 算法细节

2.1 一、二元词试探

这个方法基于一个假设:明文中的一元词和二元词都会出现在S,D集合中,如果出现了不在集合中的单词,后面我们会做一步筛选来排除这些干扰。在这样的前提下,我们用试探的方式逐一匹配S,D集合中的词。

            例如密文    di sygq t uspe tzsi ventzew sb st

我们找出密文中一元二元词{s, t}、{sb,st},就可以假设有密钥{s-a, t-i}、{sb-of, st-to},而sb-of可以得出{s-o, b-f},st-to可以得出{s-t,t-o}。将映射关系存入解码字母表中,我们就会发现字母表存在冲突,即一元词已经得出了{s-a},{t-i}这两个映射关系,后面又出现了{s-t},{t-o}。

    这时就要作一步取舍,假设一元词的映射关系是正确的,放弃当前二元词找到的映射关系。继续在集合D中匹配下一个单词。这样的匹配关系记录下来就是一张表格的形式,例如表1.1

表1.1

C\P of to in it
nb
vn
wv

    假设{w-i}放到解码字母表时产生冲突,那么{wv-in}的对应关系就要更改,以单词频率的先后顺序方式查找的话,下一个可能性应该是明文单词it,此时的对应关系表见表1.2

表1.2

C\P of to in it
nb
vn
wv

    如果密文wv在遍历了所有的二元词都产生冲突情况下,这时我们就要考虑之前的试探配对是不是出错了,基于我们假设的前提是筛选后的二元词都会出现在集合D中的,所以这时要选择放弃前一个映射关系,这里就是{bd-to},在解码字母表中去除{b-t}及{d-o}的编码。这时再让密文wv重新查找是否存在合适的明文与之匹配。表1.3是最后的匹配结果,找到了所有词的合适的映射,这样的过程类似于回溯执行,是一种试探的方法。

表1.3

C\P of to in it no
nb
vn
wn

    当二元单词都找不到合适的对应关系时,这就说明是上一部分的假设出错了,即一开始设想的一元词对应关系是不正确的,现在要返回去修改。一元词密文与明文之间的对应关系如表1.4所示,类似于前面的做法,密文与明文的映射关系可以用vector或是array来保存,回溯时修改里面的数值即可。但不同的是一元词没修改一次,就继续往下回到二元词表中进行回溯,如果依旧冲突,则再返回一元表修改其中的映射关系。如此往复进行后,由于S,D集合十分小,这种情况我们很快就可以破解出这些词的明文形式。

表1.4

C\P i a s m
k
v
e

  尽管上面破译出来的字母可以通过筛选密文中二元词频率的方式来排除异常词的干扰,如 

单字母密码密码分析(下)
单字母密码密码分析(下)

2.2 三元词分析

根据参考资料,三元词也同样具备明显的频率特征,比如句子中常见的关系代词,介词,谓语动词等等中有很大一部分都是三个字母组成的。像下面的三元词表T(Most Frequent Three-LetterWords),其中the的频率显著高于其余的词,但可读文本中出现的三元词并不一定都出现在T里面,因为三元词包含上千种,且不同类型的文本频率会有很大不同。例如个别名词TCP,在计算机网络的相关文章中就有可能频繁出现。

对于这样的问题,我们就不能像二元词频率筛选一样通过筛选三元词来保证它们一定出现在T内,所以当我们遇到冲突时,例如

单字母密码密码分析(下)

    判断一元二元词分析成不成功,就可以通过计数器的大小作为标准,这里设定一个threshold,当threshold* 密文三元词种类个数 > 计数器值时,我们认为前面的破译结果就是正确的,否则返回到二元词回溯继续匹配。threshold可以作为破译准确度的控制指标,不同值会影响筛查的严格程度,当threshold = 1时就认为密文中出现的所有三元词都会出现在T中,这对小文本较管用。

下面就是一个判断条件

    if (tripleDecode(simpleCipherArray[2], letterDecode) >= Cryptanalysis.threshold * simpleCipherArray[2].size())
           

threshold = 0.8是经过后来大量的文本测试所得出来的一个较通用的且破译准确度高的值

/**
	 * threshold:<strong> the strictness of filter</strong></br>
	 * set less than 0.8 if cipher is large, <br>
	 * over 0.8 you can get better result if cipher is short
	 */
	static final float threshold = 0.8f;            
单字母密码密码分析(下)

2.3 最后的穷举完整破译

剩下的最后一步,到这里至少60%的字母已经被破译出来了,剩下的未知字母中大都属于比较偏僻的字母,类似x,z等。他们在文本中出现的频率也不高,且可以从频率分布图1中看出他们频率都比较相近,这就很难再使用频率分析的方法对它们做进一步分析。

剩下10个左右的未解秘字符其实实际看来密钥空间并不是10!,随机抽出一个单词,它可能存在的未破译单词是单词长度的一半,通常一个单词长度不会超过10,那么也就是5!大小的密钥空间。所以我们完全可以直接用穷举的方式对未破译的单词进行穷举,然后到词典中去查找,查找失败则替换成另一个k,当密钥空间K已经遍历一遍后依然找不到,那我们默认词典单词缺失,放弃这个密文单词继而破译下一个。

前面我们都无一例外的在做一件事,就是为了这一步。我们知道破译密文最通用最有效的方法就是穷举密钥空间。但可不可行就需要看密钥空间的大小了,穷举的空间太大,我们就无法在理想时间内得到解。如密文单词 xogokgoxu 这时可能变成xaragraxh,x从初始密钥空间{a-z}现在变为{p,v, c},且这个单词里只剩下2个字母未破译,蛮力法就显得十分有效了。这时很快就能找到明文是paragraph。

穷举过程

假设x-{p, v, c}, u-{h, k},对穷举可以用栈来保存当前配对的字符位置,或是先前一维数组的形式。算法思想也是一个回溯的过程,维护好当前的对应关系即可。

译码效果

加密文本a1 短文本,单词量1300 words,图3.1

单字母密码密码分析(下)

                                          图 3.1 a1(1300 words)

加密后密文

单字母密码密码分析(下)

                                               图 3.1.1 a1_cipher

译码结果

单字母密码密码分析(下)

                                               图 3.1.2 a1_decode

准确率为93%,错误2个,此时threshold = 0.8。

设为

static final float threshold = 0.8f;            

这时的结果见图3.1.3,正确率100%。

单字母密码密码分析(下)

                                               图3.1.3 a1_decode_2

选其他较大的文本再做测试

单字母密码密码分析(下)

                  图3.2 大文本 (400,000words)