2013-09-30 36 views
3

因此,我們被告知不要使用相同的密鑰進行一次性填充,因爲如果攻擊者知道兩個密文,他可以得到兩個純文本的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 

但是這些信息給攻擊者帶來了什麼好處呢?他可以用兩個純文本的XOR來做什麼?

+0

不完全是兩個密文異,但可以進行暴力攻擊,XORring第一密文,以及第二個與當前,猜到關鍵;如果他們匹配,賓果。 – 2013-09-30 16:34:29

+0

我不是一個加密專家,但是攻擊者不知道其中一個明文是否能夠恢復另一個? – szx

+0

請注意,如果知道多個密文,則該密鑰可以一次強制一個字母 - 此方法不涉及將密文異或在一起。 – ntoskrnl

回答

2

我想會有很多其他的答案,但你可以做以下事情 - 嘗試猜測一個已知的單詞是在任何一個文本在給定的位置和異或與該單詞的位置。如果該值看起來合理(統計上看起來像你感興趣的明文),那麼你就知道這兩個明文的一部分。

比方說,你有明文以下XOR(或密文,它是其中的密文==明文XOR OTP的問題所描述的情況相同):

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

現在你試圖以匹配的話字典和發現,如果你在位置1 XOR此字符串與「正確的」,你會得到:

some ot 

好了,你的明文是最有可能:

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

現在嘗試異字開頭的「OT ......」與XOR和發現,「其他」你(與已知的開始一起):

correct ho 

所以你的明文是:

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

等繼續這種方式,你可以恢復兩個完整的字符串。對於不是英文單詞的明文,這當然會更困難,但仍然有可能。在任何時候你都不需要知道OTP的內容。

+0

@KerrekSB假設密文是由OTP xor明文產生的,那麼ciphertext1 xor ciphertext2 == plaintext1 xor plaintext2。上面的例子是針對該值(消息的異或)。 – viraptor

+0

噢,好的。沒關係! –

+0

+1非常好的建設性的例子 –

2

兩個明文的異或對攻擊者非常有用。舉一個例子,當用字母字符進行着色時,空格字符(ascii 32)只是改變它們的大小寫。所以如果一個明文有很多空格,你可以通過反轉情況來讀取其他明文。

2

避免將字母用作一次性傳遞(使用循環算法)。如果一個得到cyper文本

GUTV 

人們可以不知道除了它是4個字母長的明文什麼。 它可以是 炸彈或愛或任何其他字。你不能區分,也不可​​能比另一個更有可能。

但是,如果你有兩個明文使用相同的鍵盤,這意味着一旦你採取一個解決方案,第二個是自動定義。

使用一些試驗和錯誤(或帶有詞彙的計算機),您可以在最差的情況下顯着減少到幾個選項。

所以,你從完全安全的東西(真正的一次性墊子)得到一件容易破碎的東西。

編輯

這裏是小美人在Python writen你需要的話文件。我走如果從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') 
相關問題