2013-10-29 19 views
8

Da this sito ho questo frammento di codice:Crittografia AES Python e crittografia Ruby - comportamento diverso?

>>> 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] 

Quando prendo questa matrice e trasformarlo in una stringa in Ruby e procedere per la decodifica, si verifica un errore:

>> 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>' 

Perché questo non funziona?

risposta

10

Questo è comprensibilmente confuso: PyCrypto è andato un po 'fuori dai binari qui e rotto con la solita implementazione. Se hai familiarità con i dati crittografati che dovrebbero apparire normalmente, l'output Python sembra in modo evidente errato e ti dà un punto di partenza. Se non lo sei, è facile chiedersi cosa diavolo è andato storto e non hai idea di dove cominciare a cercare.

In un'implementazione "normale", il riempimento verrà utilizzato per impostazione predefinita e terminerà (in questo caso) con un output crittografato con 16 byte in più.

cifrato utilizzando Ruby, per esempio, questo è il risultato:

>> 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, per ragioni che non riesco a trovare subito, ha scelto di work only with unpadded data. Quando si interscambiano i dati con PyCrypto, è necessario configurare le altre librerie in modo appropriato.

Nel caso della libreria OpenSSL di rubino, l'oggetto Cipher espone una proprietà padding che può essere usata per disabilitare 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

Grazie, questa è una grande risposta. Sai perché questo non funziona con 'AES.MODE_CFB'? – Danyel

+0

Suppongo che tu non lo faccia. Qualche idea su come rendere pubblica questa "domanda" (o picchiarla) senza crearne una nuova? – Danyel

+0

Come potresti andare nella direzione opposta da Ruby a Python. Python sembra sempre lamentarsi del fatto che "ValueError: le stringhe di input devono essere un multiplo di 16 in lunghezza" – user2694306

Problemi correlati