2013-10-29 24 views
8

Từ this trang web tôi có đoạn mã này:Mã hóa AES Python và mã hóa Ruby - hành vi khác nhau?

>>> from Crypto.Cipher import AES 
>>> obj = AES.new('This is a key123', AES.MODE_CBC, 'This is an IV456') 
>>> message = "The answer is no" 
>>> ciphertext = obj.encrypt(message) 
>>> list(bytearray(ciphertext)) 
[214, 131, 141, 100, 33, 86, 84, 146, 170, 96, 65, 5, 224, 155, 139, 241] 

Khi tôi mất mảng này và biến nó thành một String trong Ruby và tiến tới giải mã nó, một lỗi xảy ra:

>> require 'openssl' 
=> true 
>> obj2 = OpenSSL::Cipher::Cipher.new("AES-128-CBC") 
=> #<OpenSSL::Cipher::Cipher:0x007fa388389b30> 
>> obj2.decrypt 
=> #<OpenSSL::Cipher::Cipher:0x007fa388389b30> 
>> obj2.key = 'This is a key123' 
=> "This is a key123" 
>> obj2.iv = 'This is an IV456' 
=> "This is an IV456" 
>> ciphertext = [214, 131, 141, 100, 33, 86, 84, 146, 170, 96, 65, 5, 224, 155, 139, 241].pack('c*') 
=> "\xD6\x83\x8Dd!VT\x92\xAA`A\x05\xE0\x9B\x8B\xF1" 
>> obj2.update(ciphertext) + obj2.final 
OpenSSL::Cipher::CipherError: bad decrypt 
    from (irb):20:in `final' 
    from (irb):20 
    from /home/danyel/.rbenv/versions/2.0.0-p0/bin/irb:12:in `<main>' 

Tại sao điều này không hoạt động?

Trả lời

10

Điều này có thể hiểu được một cách dễ hiểu — PyCrypto đã đi một chút khỏi các đường ray ở đây và bị hỏng với việc triển khai thông thường. Nếu bạn quen thuộc với dữ liệu được mã hóa thông thường trông như thế nào, đầu ra của Python trông có vẻ như là sai và cho bạn một nơi để bắt đầu. Nếu bạn không, thật dễ dàng để tự hỏi những gì heck đã đi sai và không có ý tưởng nơi để bắt đầu tìm kiếm.

Trong triển khai "bình thường", đệm sẽ được sử dụng theo mặc định và bạn sẽ kết thúc (trong trường hợp này) với đầu ra được mã hóa dài hơn 16 byte.

mã hóa sử dụng Ruby, ví dụ, đây là kết quả:

>> ciphertext 
=> "\xD6\x83\x8Dd!VT\x92\xAA`A\x05\xE0\x9B\x8B\xF1\xD5f\xC7\xFFNI\xC7N\xBC-;!\f\xF1!\xB4" 
>> ciphertext.bytes 
=> [214, 131, 141, 100, 33, 86, 84, 146, 170, 96, 65, 5, 224, 155, 139, 241, 213, 102, 199, 255, 78, 73, 199, 78, 188, 45, 59, 33, 12, 241, 33, 180] 

PyCrypto, vì lý do tôi không thể ngay lập tức tìm thấy, đã chọn để work only with unpadded data. Khi trao đổi dữ liệu với PyCrypto, bạn sẽ muốn cấu hình bất kỳ thư viện nào khác một cách thích hợp.

Trong trường hợp thư viện OpenSSL Ruby, đối tượng Cipher cho thấy một tài sản mà có thể được sử dụng để vô hiệu hóa đệm padding:

>> require 'openssl' 
=> true 
>> obj2 = OpenSSL::Cipher::Cipher.new("AES-128-CBC") 
=> #<OpenSSL::Cipher::Cipher:0x007fe62407a9b0> 
>> obj2.decrypt 
=> #<OpenSSL::Cipher::Cipher:0x007fe62407a9b0> 
>> obj2.key = 'This is a key123' 
=> "This is a key123" 
>> obj2.iv = 'This is an IV456' 
=> "This is an IV456" 
>> obj2.padding = 0 
=> 0 
>> ciphertext = [214, 131, 141, 100, 33, 86, 84, 146, 170, 96, 65, 5, 224, 155, 139, 241].pack('c*') 
=> "\xD6\x83\x8Dd!VT\x92\xAA`A\x05\xE0\x9B\x8B\xF1" 
>> obj2.update(ciphertext) + obj2.final 
=> "The answer is no" 
+0

Cảm ơn, đây là một phản ứng tuyệt vời. Bạn có biết tại sao điều này không hoạt động với 'AES.MODE_CFB'? – Danyel

+0

Tôi giả sử bạn không làm như vậy. Bất kỳ ý tưởng làm thế nào để làm cho 'câu hỏi' công cộng (hoặc bumping nó) mà không cần tạo một cái mới? – Danyel

+0

Làm thế nào bạn có thể đi theo hướng ngược lại từ Ruby sang Python. Python luôn có vẻ phàn nàn rằng "ValueError: Chuỗi đầu vào phải là bội số của 16 độ dài" – user2694306

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