2013-02-05 178 views
10

我想了解PyCrypto如何在項目中使用,但我並不完全瞭解初始化向量(IV)的意義。我發現在解碼一個字符串時我可以使用錯誤的IV,並且除了前16個字節(塊大小)外,我似乎仍然收到消息。我只是使用它錯誤或不理解的東西?PyCrypto - 初始化矢量如何工作?

下面是一個示例代碼來演示:

import Crypto 
import Crypto.Random 
from Crypto.Cipher import AES 

def pad_data(data): 
    if len(data) % 16 == 0: 
     return data 
    databytes = bytearray(data) 
    padding_required = 15 - (len(databytes) % 16) 
    databytes.extend(b'\x80') 
    databytes.extend(b'\x00' * padding_required) 
    return bytes(databytes) 

def unpad_data(data): 
    if not data: 
     return data 

    data = data.rstrip(b'\x00') 
    if data[-1] == 128: # b'\x80'[0]: 
     return data[:-1] 
    else: 
     return data 


def generate_aes_key(): 
    rnd = Crypto.Random.OSRNG.posix.new().read(AES.block_size) 
    return rnd 

def encrypt(key, iv, data): 
    aes = AES.new(key, AES.MODE_CBC, iv) 
    data = pad_data(data) 
    return aes.encrypt(data) 

def decrypt(key, iv, data): 
    aes = AES.new(key, AES.MODE_CBC, iv) 
    data = aes.decrypt(data) 
    return unpad_data(data) 

def test_crypto(): 
    key = generate_aes_key() 
    iv = generate_aes_key() # get some random value for IV 
    msg = b"This is some super secret message. Please don't tell anyone about it or I'll have to shoot you." 
    code = encrypt(key, iv, msg) 

    iv = generate_aes_key() # change the IV to something random 

    decoded = decrypt(key, iv, code) 

    print(decoded) 

if __name__ == '__main__': 
    test_crypto() 

我使用Python 3.3。

輸出將在執行有所不同,但我得到的是這樣的:b"1^,Kp}Vl\x85\x8426M\xd2b\x1aer secret message. Please don't tell anyone about it or I'll have to shoot you."

回答

17

您看到的行爲特定於CBC模式。隨着CBC,解密可通過以下方式(維基百科)進行可視化:

CBC decryption

你可以看到,四隻貢獻前16個字節的明文。如果IV在傳輸到接收器時損壞,CBC將仍然正確地解密除第一個之外的所有塊。在CBC中,IV的目的是使您能夠使用相同的密鑰對相同的消息進行加密,並且每次仍然獲得完全不同的密文(即使消息長度可能會使某些內容消失)。

其他模式不太寬容。如果你的IV錯誤,整個消息在解密時會出現亂碼。以CTR模式,例如,在現時需要近的IV相同的含義:

CTR mode

+0

好吧,我想我明白了......我想也許加密文本只會改變第一個塊,但它似乎影響到整個字節鏈。似乎通常的做法是在發送之前將IV加入加密的代碼中,所以我認爲我會這樣做。 –

1

爲PyCrypto開發商拉規範AES CBC模式從NIST:

AES Mode_CBC - >引用NIST 800-38a (The Recommendation for Cipher Mode Operations)

從即第8頁:

5.3初始化向量

除了明文之外,CBC,CFB和OFB模式的加密過程的輸入還包括稱爲初始化矢量(IV)的數據塊,用IV表示。 IV在消息加密和消息的相應解密的初始步驟中使用。 IV不一定是祕密;但是,對於CBC和CFB模式,執行加密過程的任何特定的IV必須是不可預知的,並且對於OFB模式,必須使用唯一的IV來執行加密過程的每次執行。 IV型的產生在附錄C


的是要記住,則需要使用每次撰寫郵件時間的隨機IV被討論的,這增加了一個「鹽」的消息,因此使得該消息是唯一的;即使「鹽」公開,如果AES加密密鑰是未知,也不會幫助破壞加密。如果你不使用隨機IV,比如說,你使用同樣的16字節的每條消息,如果你重複自己,你的消息看起來是相同的,你可能會受到頻率和/或重放攻擊。

隨機的IV的結果VS靜態測試:

def test_crypto(): 
    print("Same IVs same key:") 
    key = generate_aes_key() 
    iv = b"123456789" 
    msg = b"This is some super secret message. Please don't tell anyone about it or I'll have to shoot you." 
    code = encrypt(key, iv, msg) 
    print(code.encode('hex')) 
    decoded = decrypt(key, iv, code) 
    print(decoded) 

    code = encrypt(key, iv, msg) 
    print(code.encode('hex')) 
    decoded = decrypt(key, iv, code) 
    print(decoded) 

    print("Different IVs same key:") 
    iv = generate_aes_key() 
    code = encrypt(key, iv, msg) 
    print(code.encode('hex')) 
    decoded = decrypt(key, iv, code) 
    print(decoded) 

    iv = generate_aes_key() 
    code = encrypt(key, iv, msg) 
    print(code.encode('hex')) 
    decoded = decrypt(key, iv, code) 
    print(decoded) 

希望這有助於!

+0

這個答案並不能解釋爲什麼四,是否會影響在CBC每一個塊的解密模式,隻影響第一個塊的解密。 – Patashu

+0

'AttributeError:'bytes'對象沒有屬性'encode''是我用print(code.encode('hex'))打印出加密的代碼時獲得的結果 –

+0

感謝關於重複攻擊的註釋...我將在每封郵件中使用一個隨機IV,並將其預先添加到加密的代碼中。 –