5.1 概述
异或(XOR)是一种逻辑二元操作,当两个输入中有且仅有一个为真时,结果为真。
另一种思考异或的方式是把当作一种“可编程的监视器”,一个输入的比特决定是否需要翻转另一个比特,还是直接保持其不变。
我们用下面的符号来表示异或操作:
通常i是索引,Pi指的是原文中的一个比特,ki指的是密钥中的一个比特,Ci指的是加密后的密文比特。
5.2 异或的一些特性
- 结合律 a⊕(b⊕c)=(a⊕b)⊕c
- 交换律a⊕b=b⊕a
- 任何比特异或自身是0,a⊕a=0
- 任何比特异或0是它自身a⊕0=a
所以a⊕b⊕a=a⊕a⊕b=0⊕b=b
5.3 按位异或操作
通常编程语言会提供异或的操作,例如Python中的^可以进行整数的按位异或,首先将两个整数转化为二进制,然后按位进行异或操作。
例如73⊕87=0b1001001⊕0b1010111
1 0 0 1 0 0 1
= ⊕ ⊕ ⊕ ⊕ ⊕ ⊕ ⊕
1 0 1 0 1 1 1
= 0 0 1 1 1 1 0
= 30
5.4 一次性密码本
一次性密码本就是用一串随机的比特和原文进行异或操作得到密文。其安全性取决于密码本只使用一次。
5.5 针对一次性密码本的攻击
一次性密码本的安全性
- 密码本包含的是完全随机的内容
- 密码本只使用一次
不使用真随机的数据
重复使用密码本
对于两段密文c1和c2
c1⊕c2=(p1⊕k)⊕(p2⊕k)=p1⊕p2⊕k⊕k=p1⊕p2
虽然依然得不到p1和p2,但是却掌握了p1和p2的某种关系。
例如下图
crib-dragging
对于复用密码本的情况,假设我们有一些用同一个密钥K生成的密文Ci。如果我们能正确的猜出其中一个Cj密文对应的明文Pj,就可以求出共享密钥K。
不幸的是我们并不能猜出整个密文,但是可以猜出其中一小部分密文(hard work)。
假设我们猜出了部分明文bit位Pi
k=Ci ⊕ Pi
所有密文处在同一个偏移位置的密钥都是k,求出同一偏移位置的所有明文:
Pi = Ci⊕ k。
猜中一部分明文文本要比猜中所有明文文本要简单的多,假设我们的明文文本是英文,下面是找一组常见的英文单词。 通常来说,the, to, of,and,a 这样的单词出现的频率非常高,因此,以它们作为突破口。如果我们更了解加密的文本就可以进行更靠谱的猜测,例如,HTML,要猜Content-Type等等。
那怎么知道我们猜的是正确的呢?如果我们的猜测是正确的,那么看密文在同一偏移位置解密出来的明文是否有意义。
对于每一条明文的同一个位置的内容,假定明文内容是空格,可以得到密钥可能是(密文)XOR(0x20),然后用这个可能的密钥去解其它的密文。假如解出来的明文都是字母,数字,标点或空格的话,则说明这个密钥很可能就是真正的密钥。用程序可以迅速对此作出判断。
假设成功猜出了5个字母 ␣the␣ ,在另一个文本中解出了对应 t␣thr ,可以查字典查找以thr开始的单词,例如through。重复过程。
- 我们会获取到更多可窃取的位置
- 每次成功的猜测可以获取到更多的明文字符,这样就更容易猜测出其他位置。
- 对于同一位置来说,越多的密文,越方便猜测。两个密文异或后得到的是明文的异或,可以通过猜测,枚举等各种方式去探索明文的情况。
有了自然语言分析之后,这件事情已经变得越来越高效。
5.6 遗留问题
一次性密码本很少被用到,因为它是不可实现的,密钥长度至少和信息一样长。并且需要不断地变换。同时还面临着密钥交换的问题。