显然是考察 block cipher 模式,打开维基百科看图复习一下……
读代码,要求是 enc(message) == message
,即密文等于明文。而明文长度是 14 byte + len(name) + padding
,如果 name
长度为 1,用 AES block cipher 的话实际上只有一个 block。现在明文/密文已知,key 随便选,倒推 IV 很容易。
我选择了 AES-OFB,也就是 cipher = plaintext xor enc(IV)
,使得 enc(IV)
为全 0 即可。随便选个 key,解一下需要的 IV:
>>> codecs.encode(Magic_box('AES', 'ECB', b'01234567ABCDEFGH').auto_dec(bytearray(16)), 'hex')
b'932d7e81fae63fe5d21bb3a25e8b8e11'
输入所需要的完整 key + IV 就是:
>>> codecs.encode(b'01234567ABCDEFGH', 'hex') + b'932d7e81fae63fe5d21bb3a25e8b8e11'
b'30313233343536374142434445464748932d7e81fae63fe5d21bb3a25e8b8e11'
就是第一题加强。10 轮测试,每次要求第 i 个 block 的密文等于明文。还是用 AES-OFB,第一轮所需要的 IV 同前一题,即 dec(0)
,第二轮的 IV 是 dec(dec(0))
,第三轮 dec(dec(dec(0)))
,依此类推……
这次要求 enc(enc(message)) == message
,即重复加密两次恢复明文。有这个性质的是 DES weak keys。这次增加的一点麻烦是 key 是输入字符串的 CRC128 校验。
当我开始琢磨这个 crc128
函数怎么逆向时,很快注意到传全 1 bit 的话,输出也是全 1:
>>> long_to_bytes(crc128(b'\xff' * 16))
b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff'
而在忽略 parity bit 的情况下,这就是个 DES weak key(实际上带正确 parity bit 的 key 应当是 0xFEFEFEFEFEFEFEFE)。