0x00 前言
最近参加了De1CTF,其中的密码学题目xorz就需要对流密码重用加密后的密文进行爆破攻击,从而得到加密明文和密钥.介于之前接触过流密码相关的题目但没有进行细致归纳,故在此进行归纳总结.
0x01 异或运算
异或运算,也是在模2域上进行的加法,遵循以下法则:
1 | 1 xor 1 = 0 |
下面通过cryptopals set1中的题目进行说明.
0x02 Cryptopals Set1
题目链接:https://cryptopals.com/sets/1
Set0 函数储备
1 | # 十六进制字符串转化为字节数组 |
Challenge2 Fixed XOR
题目要求:实现一个函数,输入为两个等长的字符串,输出为这两个字符串的异或结果.功能为实现两个等长的字符串异或.
实现方法:
- 先使用Set0中的str_to_bytelist()方法将字符串转化为字节数组;
- 然后调用xor()方法进行异或操作;
- 最后调用bytelist_to_hex()方法将得到的字节数组转化为十六进制字符串.
脚本如下:
1 | def bytelist_to_hex(bytelist): |
Challenge3 Single-byte XOR cipher
题目要求:给定一个十六进制字符串hexString,它是某个字符串与一个单字符key异或进行加密之后得到的结果.现在已知hexString,我们需要找到key,来解密字符串.
实现方法:
- 在这个挑战中,我们可以从0-255遍历字符key,对所给的密文进行逐字符异或解密;
- 通过解密后的英文文本中的字符频率,来对测试key解密结果进行评估.选择出得分最高的key,即可能为正确的key.
脚本如下:
1 | CHARACTER_FREQ = { #字符频率表 |
Challenge5 Implement repeating-key XOR
题目要求:实现一个函数,给定待加密的字符串和密钥,该函数通过使用重复密钥异或(repeating-key XOR)的方法,加密一段英文文本,返回加密后的结果.
直接贴出实现脚本:
1 | def repeatingkey_xor(string, key): |
Challenge6 Break repeating-key XOR
题目要求:在该挑战中提供了一个文件challenge6.txt,文件中是使用重复密钥异或方法加密后,再经过base64编码后得到的文本,我们需要找到密钥,对其进行解密.
实现方法:
- 猜测密钥长度KEYSIZE,在一定范围内爆破;
- 对于每个KEYSIZE,求得每个解密块两两之间的汉明距离,对KEYSIZE取平均值;
- 选取2-3个最小汉明距离的KEYSIZE;
- 获取KEYSIZE之后,对每一块的对应字节组合后的字符串与单字符异或,从而可以破解密钥;
- 对不同KEYSIZE解密之后的明文进行评估,选取得分最高的一组.
对于汉明距离的解释说明及整个爆破过程的具体解法可以参考Hamming Distance的内容.
脚本如下:
1 | def hamming_distance(s1, s2): |
0x03 xorz
题目来源: 2019.8.3-8.5 De1ctf Crypto
题目描述: xorzzz…
题目附件中的py脚本如下:
1 | from itertools import * |
解题思路:
拿到题目之后关注运算代码段:
1 | cipher = ''.join([hex(ord(p) ^ ord(next(ki)) ^ ord(next(si)))[2:].zfill(2) for p in plain]) |
可以发现密文通过key、salt和plain逐位异或得到.题目中已知salt,可以通过逐位异或还原key和plain的异或值.下面可以想到的方法就是爆破,使用上面提到的Break repeating-key XOR脚本,可以爆破出最有可能的明文,从而得到flag,结果如下: