2013-02-05 39 views
10

Tôi đang cố gắng hiểu PyCrypto hoạt động như thế nào trong một dự án nhưng tôi không hiểu đầy đủ ý nghĩa của Vector khởi tạo (IV). Tôi đã tìm thấy rằng tôi có thể sử dụng sai IV khi giải mã một chuỗi và tôi vẫn dường như để có được thông điệp trở lại ngoại trừ 16 byte đầu tiên (kích thước khối). Chỉ đơn giản là sử dụng nó sai hoặc không hiểu một cái gì đó?PyCrypto - Vector khởi tạo hoạt động như thế nào?

Dưới đây là một số mẫu mã để chứng minh:

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() 

Tôi đang sử dụng Python 3.3.

Output sẽ thay đổi tùy tình hình thực hiện, nhưng tôi nhận được một cái gì đó như thế này: b"1^,Kp}Vl\x85\x8426M\xd2b\x1aer secret message. Please don't tell anyone about it or I'll have to shoot you."

Trả lời

17

Hành vi bạn thấy cụ thể đối với chế độ CBC. Với CBC, giải mã có thể được hình dung theo cách sau (từ wikipedia):

CBC decryption

Bạn có thể thấy rằng IV chỉ góp phần vào việc 16 byte đầu tiên của văn bản gốc. Nếu IV bị hỏng trong khi nó đang được chuyển tiếp đến người nhận, CBC sẽ vẫn giải mã chính xác tất cả các khối nhưng lệnh đầu tiên. Trong CBC, mục đích của IV là cho phép bạn mã hóa cùng một thông điệp với cùng một khóa, và vẫn nhận được một bản mã hoàn toàn khác nhau mỗi lần (mặc dù chiều dài tin nhắn có thể cho một cái gì đó đi).

Các chế độ khác ít được tha thứ hơn. Nếu bạn bị IV sai, toàn bộ thông báo bị cắt xén khi giải mã.Hãy chế độ CTR ví dụ, nơi nonce mất gần cùng ý nghĩa của IV:

CTR mode

+0

okay, tôi nghĩ rằng tôi hiểu ... Tôi nghĩ rằng có thể các văn bản được mã hóa sẽ chỉ được thay đổi cho khối đầu tiên, nhưng nó dường như ảnh hưởng đến toàn bộ chuỗi byte. Nó có vẻ như một thực tế phổ biến là để thêm IV vào mã được mã hóa trước khi gửi, vì vậy tôi nghĩ rằng tôi sẽ làm điều đó. –

1

Các nhà phát triển cho PyCrypto kéo đặc tả cho AES CBC Mode từ NIST:

AES Mode_CBC -> tham khảo NIST 800-38a (The Recommendation for Cipher Mode Operations)

Từ rằng, trang 8:

5.3 Khởi tạo Vectors

Đầu vào cho các quá trình mã hóa của các chế độ CBC, CFB và OFB bao gồm, ngoài bản rõ, một khối dữ liệu được gọi là vectơ khởi tạo (IV), được biểu thị bằng IV. IV được sử dụng trong bước đầu tiên trong quá trình mã hóa tin nhắn và giải mã tương ứng của thông điệp. IV không cần bí mật; tuy nhiên, đối với các chế độ CBC và CFB, IV cho bất kỳ việc thực hiện mã hóa cụ thể nào cũng không thể đoán trước được, và đối với chế độ OFB, IV duy nhất phải được sử dụng cho mỗi lần thực hiện quá trình mã hóa. Thế hệ IVs được thảo luận trong Phụ lục C.


Thing nhớ, bạn cần phải sử dụng một IV ngẫu nhiên mỗi khi bạn soạn một tin nhắn, điều này cho biết thêm một 'muối' vào tin nhắn do đó làm cho thông điệp độc đáo; ngay cả với 'muối' đang được mở ra, nó sẽ không giúp phá vỡ mã hóa nếu khóa mã hóa AES là không rõ. Nếu bạn không sử dụng một IV ngẫu nhiên, nói, bạn sử dụng cùng một 16 byte mỗi tin nhắn, tin nhắn của bạn, nếu bạn lặp lại chính mình, sẽ trông giống như đi qua dây và bạn có thể bị tần số và/hoặc phát lại các cuộc tấn công.

Một thử nghiệm cho kết quả IVs ngẫu nhiên vs tĩnh:

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) 

Hope this helps!

+0

Câu trả lời đó không giải thích lý do tại sao IV, nếu nó sẽ ảnh hưởng đến giải mã của tất cả các khối duy nhất trong CBC chế độ, chỉ ảnh hưởng đến giải mã của khối đầu tiên. – Patashu

+0

'AttributeError: đối tượng 'byte' không có thuộc tính 'encode'' là những gì tôi nhận được khi thử in mã được mã hóa bằng bản in (code.encode (' hex ')) –

+0

nhờ lưu ý về các cuộc tấn công lặp lại ... Tôi sẽ sử dụng một IV ngẫu nhiên trên mỗi tin nhắn và thêm nó vào mã được mã hóa. –

Các vấn đề liên quan