题目
It is said that Vigenere cipher does not achieve the perfect secrecy actually :-)
Tips: 1.The encode pragram is given; 2.Do u no index of coincidence ? 3.The key is last 6 words of the plain text(with “nctf{}” when submitted, also without any interpunction)
什么是异或
异或(exclusive or)是二元逻辑运算符,符号为 XOR 或 EOR 或 ⊕或 ^ 。对于表达式 a^b
的取值,当且仅当a、b逻辑值不同时为真。具体来说就是四个式子:1^1=0; 0^0=0; 1^0=1; 0^1=1
。另外,异或有一些基本的特性,本题仅用到第七行的特性即可。
|
|
概念
我们知道,英文中的每个字母使用频率是不同的,在够长的一段话里,各个字母的占比大致稳定,并且这个稳定值也已经用巨大的语料库统计出来了,这就是字母频率。这种统计层面的现象,就给我们提供了判断一段文字是否可能有意义的依据,并且这种判断可以通过编程轻松完成。然而,给定两个字母组合,只计算出其中各字母的占比是不够的,想要准确高效地比较两段文字谁更可能具备有意义的语义,我们最好算出一个归一化参数,用以直观表示可能性的大小,这就是文中提到的 correlation ,计算公式也是有的 ,其中n(i)指字母i在一段话的所有字母中所占的比例,f(i)就是已经统计出来的i字母的频率,具体如下所示。
字母频率列表:
|
|
解题
理解加密
题目的加密方式大致等价于这样写:
程序意思是将明文和密钥逐字节异或,每次异或后的值用两位十六进制表示写入文件,也就是我们见到的code.txt,在这个过程中,密钥是循环使用的。
那么现在情况是这样的,我们知道:
密钥的长度区间为1-13字节
加密方式为逐字节循环异或
加密结果,即密文的完整内容
我们想知道
明文内容
密钥内容
(⊙﹏⊙) 这看起来有点困难。
不过,其实还有两个不言而喻但非常重要的信息
明文的每一个字节都是可见字符。
明文是一段有意义的话。
解密代码主程序
先放个主程序,和下面的对照着看。全部代码在文章底部 。
|
|
确定密钥的长度和候选字符集
明文由可见字符组成。这意味着任何一个使明文出现不可见字符的值都不可能出现在key里。 依据此可以取得两个进展。
- 求出key的每一个字节有哪些候选字符。 具体操作: 当我们假设某一字节的key的值时,就可以使用前文提到的plain = cipher ^ key 求出这一字节密文对应的明文,如果这个明文是不可见的,那么我们假设的这个值就不可能出现在key的这个字节。 因为是循环异或,所以每个字节的key会去加密多个字节的明文,我们就可以如法炮制,大大缩小key的每个字节的候选字符集。
- 在1的基础上,确定key可能有哪几种长度。 具体操作: 我们假设key每一种可能的长度,一一去求对应的候选字符集, 如果有一种长度的key在某一字节的候选字符集为空,那么key就不可能是这个长度。
至此,我们可以从无到有求得 key有哪些可能的长度 以及 **key在每一种长度下对应的每个字节的候选字符集 **。
上代码:
|
|
遍历候选字符集,求出对应的字频
这虽是个体力活,却也得小心翼翼。
|
|
根据字频求得密钥
明文是一段有意义的话。这意味着它算出来的correlation值一定是所有候选明文中最大的,依照这一点就能挑出密钥每个字节的值,从而得到整个密钥。这也是整个解密过程最核心的一部分。
|
|
根据密钥解密
求出密钥剩下的就好办了。
一些数据
可能的密钥长度和对应字符集
|
|
最后结果
|
|
解密代码全文
|
|
题目备份
|
|