4

因此,我们被告知不要对一次性密文使用相同的密钥,因为如果攻击者知道这两个密文,他可以得到两个明文的 XOR。例如:

Plain Text1: 0001011
Key        : 1010110
Ciphertext : 1011101

Plain Text2: 0110011
Key        : 1010110
Ciphertext : 1100101

XOR of ciphertexts
1011101
1100101
0111000

XOR of plaintexts (which of course match)
0001011
0110011
0111000

但是这些信息究竟能给攻击者带来什么好处呢?他可以用两个纯文本的异或做什么?

4

3 回答 3

3

我想会有很多其他答案,但您可以执行以下操作 - 尝试猜测已知单词在给定位置的任一文本中,并与该单词异或该位置。如果该值看起来合理(统计上看起来像您感兴趣的明文),那么您知道两个明文的一部分。

假设您有以下明文异或(或密文,与密文 == 明文 xor OTP 的问题中描述的情况相同):

"\x10\x00\x1f\x17E\x0c\x00H\r\x1dR\x06\x0bK\x0c\x0e\x03\x1aE\x01\rR\x1a\x1a\x06P\x04\x00RE"

现在你尝试匹配字典中的单词,发现如果你在位置 1 用“正确”对这个字符串进行异或,你会得到:

some ot

好的,所以您的明文很可能是:

correct.....
some ot.....

现在尝试用 xor 对以“ot...”开头的单词进行异或运算,并找出您得到的“其他”(以及已知的开头):

correct ho

所以你的明文是:

correct ho....
some other....

等等。继续这种方式,您可以恢复两个完整的字符串。对于不是英语单词的纯文本,这当然会更难,但仍然可能。而且您在任何时候都不需要知道 OTP 内容。

于 2013-09-30T16:47:00.450 回答
2

以免将字母用作一次性通行证(使用循环算术)。如果有人得到密文

GUTV

人们对纯文本一无所知,除了它有 4 个字母长。它可以是 BOMB 或 LOVE 或任何其他词。你无法区分,也没有比另一个更有可能。

但是,如果您有两个使用同一个键盘的纯文本,这意味着一旦您采用一种解决方案,就会自动定义第二种解决方案。

使用一些试验和错误(或有词汇的计算机),您可以显着减少最坏的选择。

因此,您可以从完全安全的东西(真正的一次性垫)到容易损坏的东西。

编辑

这是用 python 编写的小破解器 你需要单词文件。我从http://norvig.com/big.txt

此代码的作用需要两个单词bomblove并使用填充/密码haha对两者进行加密。然后它找出所有可能的密码,这些密码可以将这个密文对解密为词汇表中的单词。

import re

with open("big.txt","r") as f:
    words = set(re.findall('[a-z]+', f.read().lower())) 

def encrypt(word,password):
   add_letters = lambda x,y:chr((ord(x)+ord(y)-2*ord('a'))%26 + ord('a'))
   return "".join(add_letters(*i) for i in zip(word.lower(),password.lower()))

def decrypt(word,password):
   sub_let = lambda x,y:chr((ord(x)-ord(y)+26)%26 + ord('a'))
   return "".join(sub_let(*i) for i in zip(word.lower(),password.lower()))


def crack(a,b):
    assert(len(a) == len(b))
    w = (i for i in words if len(i) == len(a))
    for i in w:
        password = decrypt(a,i)
        b_plain= decrypt(b,password)
        if b_plain in words:
            print(i,b_plain,password)

password = "haha"
a="bomb"
b="love"

a_cyper=encrypt(a,password)
b_cyper=encrypt(b,password)

print("cyper",a_cyper,b_cyper)

crack(a_cyper,b_cyper)

输出:

('cyper', 'iotb', 'soce')
('tomb', 'dove', 'paha')
('bath', 'lack', 'hoau')
('bomb', 'love', 'haha')  <---
('vote', 'foch', 'naax')
('reid', 'berg', 'rkly')
('tank', 'dawn', 'pogr')
('felo', 'peur', 'dkin')
('hath', 'rack', 'boau')
('cork', 'moan', 'gacr')
('rath', 'back', 'roau')
('ruth', 'buck', 'ruau')
('bank', 'lawn', 'hogr')
('rake', 'bath', 'rojx')
('mike', 'with', 'wgjx')
('hero', 'rear', 'bkcn')
('comb', 'move', 'gaha')
('foch', 'polk', 'daru')
('foci', 'poll', 'dart')
('both', 'lock', 'haau')
('peri', 'zeal', 'tkct')
('maim', 'warp', 'wolp')
('limb', 'vive', 'xgha')
于 2013-09-30T17:07:00.740 回答
2

两个明文的异或对攻击者非常有用。举个例子,空格字符(ascii 32)当与字母字符异或时,只需改变它们的大小写。因此,如果一个明文中有很多空格,您可以通过反转大小写来读取另一个明文。

于 2013-09-30T16:50:48.070 回答