流密码MTP多次密码本攻击

Exp2 Theory: Many Time Pad (MTP)多次使用流密码

参考实验代码:

密码学实验一:Many Time Pad(多次使用流密码)_ustcsse2019-lee的博客-CSDN博客

参考原理:

Many-Time-Pad 攻击

OTP是无条件安全的:即使攻击者拥有无限的计算资源,都不可能破译OTP加密的密文。探索在使用一次一密的方法加密时,密钥被重复使用时的已知密文攻击方法。

在这里插入图片描述

题目:如下所示是 11 个使用同一个密钥按照 one time pad 方法进行加密得到的密文。请使用前 10 个密文进行分析,并对目标密文进行解密。其中消息(明文)是[a-zA-Z]以及空格组成的字符,使用 ascii 编码(十进制),密文使用 hex 编码(字符的ascii码值的16进制表示)。

密文 = 明文 ⊕ 密钥 密文 1 ⊕ 密文 2 = 明文 1 ⊕ 明文 2 ⊕ 密钥 ⊕ 密钥 = 明文 1 ⊕ 明文 2 \text{密文}=\text{明文}\oplus \text{密钥} \\ \text{密文}_1\oplus \text{密文}_2=\text{明文}_1\oplus \text{明文}_2\oplus \text{密钥}\oplus \text{密钥}=\text{明文}_1\oplus \text{明文}_2 密文=明文密钥密文1密文2=明文1明文2密钥密钥=明文1明文2

上述运算表明两个密文的异或,等于对应明文的异或。这是很危险的性质,高明的攻击者可以通过频率分析,来破译这些密文。如果字符串C1异或上其他所有密文可能得到以下内容,只保留英文字符,其余字符以 “.” 代替。

可以观察到,有些列上有大量的英文字符,有些列一个英文字符都没有。

🐒ASCII码表

ASCII 全称为 ( American Standard Code for Information Interchange),简单的说,就是用 7 位二进制 ( 即 十进制表示为 0 到 127 ) 去编码我们生活中常见的数字,大小写字母。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

ascii 码表在 Linux 下可以通过 man ascii 指令查看。它的性质有:

  • 0x20 是空格。 低于 0x20 的,全部是起特殊用途的字符; 0x20~0x7E 的,是可打印字符。
  • 0x30~0x39 是数字 0,1,2...9
  • 0x41~0x5A 是大写字母 A-Z0x61~0x7A 是小写字母 a-z.

💡 存在一个至关重要的规律:小写字母 xor 空格,会得到对应的大写字母;大写字母 xor 空格,会得到小写字母。所以如果 x ⊕ y x\oplus y xy得到一个英文字母,那么 x , y x,y x,y中的某一个有很大概率是空格。再来回头看上面密文C1 xor 其他密文——也就等于明文M1 xor 其他明文,如果第col列存在大量的英文字母,可以猜测 M 1 [ c o l ] M_1[col] M1[col]是一个空格。那一列英文字母越多,把握越大。如果M1的第col列是空格,则有: M i [ c o l ] = M 1 [ c o l ] ⊕ M i [ c o l ] ⊕ M 1 [ c o l ] = M 1 [ c o l ] ⊕ M i [ c o l ] ⊕ 0 x 20 M_i[col]=M_1[col] \oplus M_i[col] \oplus M_1[col] = M_1[col] \oplus M_i[col] \oplus 0x20 Mi[col]=M1[col]Mi[col]M1[col]=M1[col]Mi[col]0x20,也就是只要知道某个字符串C1的某一位是空格,就可以恢复出所有明文在这一列的值。恢复过程为: M i [ c o l ] = C 1 [ c o l ] ⊕ C i [ c o l ] ⊕ 0 x 20 M_i[col]=C_1[col] \oplus C_i[col] \oplus 0x20 Mi[col]=C1[col]Ci[col]0x20

攻击

攻击过程显而易见:对于每一条密文 C i C_i Ci,去异或其他所有10条密文。然后计数异或结果中每一列有多少个英文字符,作为 M i M_i Mi在这一位是空格的评分。然后记录前10条密文空格评分为10~6处的下标,每一轮依次使用前10条密文,根据 M i [ c o l ] = C 1 [ c o l ] ⊕ C i [ c o l ] ⊕ 0 x 20 M_i[col]=C_1[col] \oplus C_i[col] \oplus 0x20 Mi[col]=C1[col]Ci[col]0x20恢复第11条密文相应下标处的值,一共进行5轮,观察恢复过程。最后对明文结果进行修正获得 M i M_i Mi,同时可得到密钥 k e y = M i ⊕ C i key=M_i \oplus C_i key=MiCi,使用密钥可获得此后任意一条密文对应的明文。

在这里插入图片描述

  • 代码示例(Linux):

在这里插入图片描述
在这里插入图片描述

将明文、密文和密钥都转化为16进制整数, 密文 = 明文 ⊕ 密钥 密文=明文 \oplus 密钥 密文=明文密钥

两个长度不同的16进制字符串进行异或时,会将长度较短的字符串前面补0与长字符串长度一致,任何数与0异或后结果不变。例如16进制111异或:1 ^ 11 = 00000001 ^ 00010001 = 00010000 = (16)d = (10)h。

由于只有一个密钥,当明文长度<密钥长度时,密文长度=密钥长度;当明文长度>密钥长度时,密文长度=明文长度。即不能断言密文长度等于明文长度。由上述示例可以看出:当两个16进制字符串长度不同时(令长字符串长为L,短字符串长为l),在结果中会保留长字符串前L-l位,然后对两个字符串的后l位异或,追加到前L-l位后。即长字符串的前L-l位并没有和短字符串实际值异或,而是和0异或,没有用于判断是否为空格的参考价值。

综上所述,当两个密文长度不同时,应当对较长的密文从第0位开始截取长度较短的密文长度的字符串,然后进行异或分析空格位置。此题要分析第11个密文对应的明文,则其他密文长度一定都不小于该密文,所以可以在初始时都截取前10个密文的后l个字符。

问题记录:以上处理方法基于将16进制整数都转换为10进制整数后再进行异或,但是发现并不能这样处理,因为会违背明文是字符串而不是整数的本意。所以需要将16进制字符串中的每2个字符转换为ascii码(即每2个16进制字符对应明文/密文字符串中的一个字符),需要注意bytes类型没有内置的__xor__函数,所以不能直接使用^进行异或,可以依次对两个bytes类型中的对应的每个ascii码进行异或。【binascii.unhexlify()将16进制字符串转化为字节数组bytes类型,字节数组中的每一个元素等于实际字符串中对应每一个字符的ascii码,每两位十六进制字符对应一个ascii码】

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值