Decifrare AES CBC in python da OpenSSL AES

Sep 30 2020

Ho bisogno di decrittografare un file crittografato su OpenSSL con python ma non capisco le opzioni di pycrypto.

Ecco cosa faccio in OpenSSL

  1. openssl enc -aes-256-cbc -a -salt -pbkdf2 -iter 100000 -in "clear.txt" -out "crypt.txt" -pass pass: "mypassword"

  2. openssl enc -d -aes-256-cbc -a -pbkdf2 -iter 100000 -in "crypt.txt" -out "out.txt" -pass pass: "miapassword"

Ho provato (che ovviamente non funzionerà)

obj2 = AES.new("mypassword", AES.MODE_CBC)
output = obj2.decrypt(text)

Voglio solo fare il secondo passaggio in Python, ma guardando l'esempio:

https://pypi.org/project/pycrypto/

obj2 = AES.new('This is a key123', AES.MODE_CBC, 'This is an IV456')
obj2.decrypt(ciphertext)

Non ho bisogno di IV, come faccio a specificare il sale? l'hash pbkdf2? Sono anche guardato in questo thread

Come decrittografare i file crittografati con OpenSSL AES in Python?

ma non ha aiutato.

Qualcuno può mostrarmi come farlo usando Python?

grazie.

Risposte

4 Topaco Sep 30 2020 at 04:16

L'istruzione OpenSSL utilizza PBKDF2 per creare una chiave da 32 byte e un IV da 16 byte. Per questo, viene generato implicitamente un salt di 8 byte casuale e vengono applicati la password specificata, il conteggio delle iterazioni e il digest (predefinito: SHA-256). La coppia chiave / IV viene utilizzata per crittografare il testo in chiaro con AES-256 in modalità CBC e riempimento PKCS7, s. qui . Il risultato viene restituito in formato OpenSSL, che inizia con la codifica ASCII a 8 byte di Salted__ , seguita dagli 8 byte salt e dal testo cifrato effettivo, tutti codificati in Base64. Il sale è necessario per la decrittazione, in modo che la chiave e l'IV possano essere ricostruiti.

Notare che la password nell'istruzione OpenSSL viene effettivamente passata senza virgolette, ovvero nell'istruzione OpenSSL inserita, le virgolette fanno parte della password.

Per la decrittografia in Python, il sale e il testo cifrato effettivo devono essere prima determinati dai dati crittografati. Con il sale si può ricostruire la coppia chiave / flebo. Infine, la coppia chiave / IV può essere utilizzata per la decrittazione.

Esempio: con l'istruzione OpenSSL pubblicata, il testo in chiaro

The quick brown fox jumps over the lazy dog

è stato crittografato nel testo cifrato

U2FsdGVkX18A+AhjLZpfOq2HilY+8MyrXcz3lHMdUII2cud0DnnIcAtomToclwWOtUUnoyTY2qCQQXQfwDYotw== 

La decrittografia con Python è possibile come segue (utilizzando PyCryptodome ):

from Crypto.Protocol.KDF import PBKDF2
from Crypto.Hash import SHA256
from Crypto.Util.Padding import unpad
from Crypto.Cipher import AES
import base64

# Determine salt and ciphertext
encryptedDataB64 = 'U2FsdGVkX18A+AhjLZpfOq2HilY+8MyrXcz3lHMdUII2cud0DnnIcAtomToclwWOtUUnoyTY2qCQQXQfwDYotw=='
encryptedData = base64.b64decode(encryptedDataB64)
salt = encryptedData[8:16]
ciphertext = encryptedData[16:]

# Reconstruct Key/IV-pair
pbkdf2Hash = PBKDF2(b'"mypassword"', salt, 32 + 16, count=100000, hmac_hash_module=SHA256)
key = pbkdf2Hash[0:32]
iv = pbkdf2Hash[32:32 + 16]

# Decrypt with AES-256 / CBC / PKCS7 Padding
cipher = AES.new(key, AES.MODE_CBC, iv)
decrypted = unpad(cipher.decrypt(ciphertext), 16)

print(decrypted)

Modifica - Per quanto riguarda il tuo commento: 16 MB dovrebbero essere possibili, ma per dati più grandi il testo cifrato sarebbe generalmente letto da un file ei dati decrittografati sarebbero scritti su un file, a differenza dell'esempio postato sopra.
La possibilità di decrittografare i dati in un unico passaggio dipende in ultima analisi dalla memoria disponibile. Se la memoria non è sufficiente, i dati devono essere elaborati in blocchi.
Quando si utilizzano blocchi, avrebbe più senso non codificare in Base64 i dati crittografati ma archiviarli direttamente in formato binario. Ciò è possibile omettendo -aopzione nell'istruzione OpenSSL. Altrimenti è necessario assicurarsi che vengano caricati sempre multipli interi della dimensione del blocco (relativa al testo cifrato non codificato), dove 3 byte del testo cifrato non decodificato corrispondono a 4 byte del testo cifrato codificato Base64.

Nel caso del testo cifrato binario memorizzato: durante la decrittografia solo il primo blocco (16 byte) dovrebbe essere letto (binario) nel primo passaggio. Da questo, è possibile determinare il sale (i byte da 8 a 16), quindi la chiave e IV (analogo al codice pubblicato sopra).
Il resto del testo cifrato può essere (binario) letto in blocchi di dimensioni adeguate (= un multiplo della dimensione del blocco, ad esempio 1024 byte). Ogni blocco viene crittografato / decrittografato separatamente, vedere più chiamate crittografate / decrittografate . Per leggere / scrivere file in blocchi con Python vedere ad esempio qui .
Ulteriori dettagli trovano una risposta migliore nell'ambito di una domanda separata.