2016-06-30 73 views
11

Ho generato una chiave simmetrica a 256 bit casuale, in un file, da utilizzare per crittografare alcuni dati utilizzando la riga di comando di OpenSSL che ho bisogno di decrittografare successivamente in modo programmatico utilizzando la libreria OpenSSL. Non sto avendo successo, e penso che il problema potrebbe essere nel vettore di inizializzazione che sto usando (o non usando).Qual è l'IV predefinito durante la crittografia con la crittografia aes_256_cbc?

ho crittografare i dati utilizzando questo comando:

/usr/bin/openssl enc -aes-256-cbc -salt -in input_filename -out output_filename -pass file:keyfile 

sto usando la seguente chiamata per inizializzare la decriptazione dei dati:

EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), nullptr, keyfile.data(), nullptr)) 

keyfile è un vector<unsigned char> che contiene i 32 byte della chiave. La mia domanda riguarda l'ultimo parametro. Dovrebbe essere un vettore di inizializzazione dell'algoritmo di cifratura. Non ho specificato un IV durante la crittografia, quindi è necessario che sia stato utilizzato un valore predefinito.

Il passaggio di nullptr per quel parametro significa "utilizza l'impostazione predefinita"? Il valore predefinito è null e nulla viene aggiunto al primo blocco di cifratura?

Devo dire che sono in grado di decifrare dalla riga di comando senza fornire una flebo.

+0

Non sarebbe senza usare IV (o un valore predefinito fisso) potrebbe gravemente compromettere la forza della crittografia? A quanto ho capito, il punto IV è quello di garantire che il testo in chiaro identico non generi testo cifrato identico. Quindi c'è bisogno di essere un IV, non ha bisogno di essere segreto, ha solo bisogno di essere unico per tutto ciò che crittografate. Non usarne uno (o uno fisso) suona come una pessima idea. –

+0

Io non sono un crittografo, né mi giocare uno in TV, quindi sono davvero non qualificato per rispondere (da qui il motivo per cui quanto sopra era solo un commento).Come non esperto vorrei * supporre * che finché la chiave è unica ogni volta, allora probabilmente è OK, ma allora come pragmatico che sa di sapere troppo poco sulla crittografia probabilmente userò anche una IV casuale, * comunque * e memorizzarlo insieme ai dati crittografati. –

+0

Ho trovato alcune informazioni al riguardo: [Risposta su crypto.stackexchange.com Riguardo all'utilizzo della stessa IV con chiavi diverse per ogni testo in chiaro.] (Http://crypto.stackexchange.com/questions/8600/why-should-i- use-an-initialization-vector-iv-when-i-have-unique-keys) – Steve

risposta

6

Qual è l'IV predefinito durante la crittografia con EVP_aes_256_cbc() [sic] cipher ...

Vuol passando nullptr per quel parametro significa "usare il default"? Il valore predefinito è null e nulla viene aggiunto al primo blocco di cifratura?

Non v'è nessuno. Devi fornirlo. Per completezza, l'IV dovrebbe essere non prevedibile.

non prevedibile è leggermente diversa rispetto sia unico e casuale. Ad esempio, SSLv3 usato per usare l'ultimo blocco di testo cifrato per il IV del prossimo blocco. Era Unique, ma non era né CasualeNon prevedibile e reso vulnerabile agli attacchi di testo in chiaro SSLv3.

Altre biblioteche fanno cose intelligenti come fornire un vettore nullo (una stringa di 0). I loro aggressori li ringraziano per questo. Vedi anche Why is using a Non-Random IV with CBC Mode a vulnerability? su Stack Overflow e Is AES in CBC mode secure if a known and/or fixed IV is used? su Crypto.SE.


/usr/bin/openssl enc -aes-256-cbc...

Devo dire che io sono in grado di decifrare dalla riga di comando senza fornire una flebo.

OpenSSL utilizza una funzione di derivazione chiave/mashup interna che accetta la password e ricava una chiave iv. Si chiama EVP_BytesToKey e si può leggere a riguardo nelle pagine man. Le pagine man dicono anche:

Se la chiave e IV lunghezza totale è inferiore alla lunghezza digest e MD5 viene utilizzato l'algoritmo di derivazione è compatibile con PKCS # 5 v1.5 altrimenti un'estensione non standard è utilizzato per ricava i dati extra.

Ci sono molti esempi di EVP_BytesToKey una volta che sai cosa cercare. Openssl password to key è uno in C. How to decrypt file in Java encrypted with openssl command using AES in uno in Java.


EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), nullptr, keyfile.data(), nullptr))

non ho specificato una flebo quando la crittografia, in modo un po 'di default deve essere stato usato.

Verificare i valori di restituzione. Una chiamata dovrebbe essere fallita da qualche parte lungo il percorso. Forse non a EVP_DecryptInit_ex, ma sicuramente prima di EVP_DecryptFinal.

Se la sua non mancando, quindi si prega di un bug report.

+0

Non ha esito negativo fino a EVP_DecryptFinal. Questa è una buona informazione, grazie! – Steve

5

EVP_DecryptInit_ex è un'interfaccia per la primitiva di decrittografia AES. Questo è solo un pezzo di ciò che è necessario decodificare il formato di crittografia OpenSSL. Il formato di crittografia OpenSSL non è ben documentato, ma puoi lavorarlo a ritroso dal codice e da alcuni documenti. Il calcolo chiave e IV è spiegato nella documentazione EVP_BytesToKey:

The key and IV is derived by concatenating D_1, D_2, etc until enough 
    data is available for the key and IV. D_i is defined as: 

      D_i = HASH^count(D_(i-1) || data || salt) 

    where || denotes concatentaion, D_0 is empty, HASH is the digest 
    algorithm in use, HASH^1(data) is simply HASH(data), HASH^2(data) is 
    HASH(HASH(data)) and so on. 

    The initial bytes are used for the key and the subsequent bytes for the 
    IV. 

"cancelletto" qui è MD5. In pratica, questo significa che calcolare gli hash come questo:

Hash0 = '' 
Hash1 = MD5(Hash0 + Password + Salt) 
Hash2 = MD5(Hash1 + Password + Salt) 
Hash3 = MD5(Hash2 + Password + Salt) 
... 

Poi si tira dei byte è necessario per la chiave, e poi tirare i byte necessari per il IV. Per AES-128 significa che Hash1 è la chiave e Hash2 è la IV. Per AES-256, la chiave è Hash1 + Hash2 (concatenata, non aggiunta) e Hash3 è la IV.

È necessario rimuovere l'intestazione iniziale Salted___, quindi utilizzare il sale per calcolare la chiave e IV. Quindi avrai i pezzi da alimentare in EVP_DecryptInit_ex.

Dato che lo stai facendo in C++, probabilmente puoi semplicemente scavare il codice enc e riutilizzarlo (dopo aver verificato che la sua licenza è compatibile con il tuo uso).

Si noti che OpenSSL IV viene generato casualmente, poiché è l'output di un processo di hashing che coinvolge un salt casuale. La sicurezza del primo blocco non dipende dal fatto che l'IV sia casuale di per sé; richiede semplicemente che una particolare coppia di chiavi IV + non venga mai ripetuta. Il processo OpenSSL garantisce che finché il sale casuale non viene mai ripetuto.

È possibile che l'utilizzo di MD5 in questo modo impigli la chiave e IV in un modo che perde informazioni, ma non ho mai visto un'analisi che lo afferma. Se si deve usare il formato OpenSSL, non avrei esitazioni sulla sua generazione IV. I grossi problemi con il formato OpenSSL sono la sua forza bruta (4 round di MD5 non sono sufficienti) e manca di autenticazione.

+0

Uh, hai il codice sorgente e chiami quel reverse engineering? – Pacerier

+0

Qualche idea su come funziona aes 256 qui con un IV a 256 bit? La mia comprensione è che l'IV ha bisogno di 128 bit e la chiave 256 bit. Nella pseudo sopra entrambi sono corretti a 256 bit. – Aaron

+1

@Aaron aggiornato. Il IV a 256 bit era sbagliato. Ha funzionato bene a causa delle librerie con cui stavo lavorando, ma solo i primi 128 bit erano effettivamente utilizzati. –