Crittografando usando AES-256, posso usare IV a 256 bit?

16

Voglio crittografare i dati usando AES in java e voglio inizializzare il cifrario con Initialisation Vector. Posso usare IV a 256-bit? O devo usare solo IV a 128 bit?

    
posta Hakim 04.06.2015 - 15:43
fonte

4 risposte

37

L'IV dipende dalla modalità di funzionamento . Per la maggior parte delle modalità (ad esempio CBC), l'IV deve avere la stessa lunghezza del blocco . AES utilizza blocchi a 128 bit, quindi un IV a 128 bit. Nota che AES-256 usa una chiave a 256-bit (da cui il nome), ma con blocchi a 128-bit.

AES è stato scelto come sottoinsieme della famiglia di codici a blocchi noto come Rijndael . Quella famiglia comprende non meno di 15 varianti, per tre possibili blocchi di dimensioni (128, 192 e 256 bit) e cinque possibili dimensioni di chiave (128, 160, 192, 224 e 256 bit). AES , come standardizzato dal NIST, include solo tre varianti, tutte con blocchi a 128 bit e con chiavi di 128, 192 o 256 bit.

Per confondere ulteriormente le cose, alcuni framework software hanno sbagliato; per esempio. PHP utilizza "MCRYPT_RIJNDAEL_128" per designare Rijndael con chiavi a 128 bit e blocchi a 128 bit (vale a dire la stessa cosa di AES-128) e "MCRYPT_RIJNDAEL_256" per Rijndael con chiavi a 256 bit e blocchi a 256 bit (cioè non uno di le varianti AES, in particolare non AES-256).

    
risposta data 04.06.2015 - 16:08
fonte
6

Devi usare un IV a 128 bit. Per la modalità CBC IV deve corrispondere alla dimensione del blocco, che è sempre 128 bit per AES.

Rijndael, il candidato AES vincente, è definito per blocchi a 128 e 256 bit, ma solo i blocchi a 128 bit sono stati standardizzati come AES. Alcune librerie supportano Rijndael con blocchi a 256 bit, ma in questo caso non utilizzi più AES.

Se hai bisogno di un IV più lungo per qualche motivo, puoi usare un KDF o un hash per trasformare la chiave originale e la IV nella chiave che usi effettivamente per AES.

    
risposta data 04.06.2015 - 16:08
fonte
4

La gestione IV in Java dipende dal provider crittografico utilizzato. Il provider SUN fornito con i runtime di Oracle è piuttosto rigido; richiede che IV abbia la stessa dimensione della dimensione del blocco per la maggior parte delle modalità di funzionamento . Questo è vero anche per la modalità CTR in cui ci si potrebbe aspettare che fornire un nonce - i primi byte della IV - dovrebbe essere sufficiente. Naturalmente la modalità ECB non richiede una IV, quindi genererà un'eccezione se proverai a fornirne una.

La dimensione del blocco di AES è sempre di 128 bit, quindi un IV a 256 bit non è possibile per la maggior parte dei modi operativi. Come già osservato in alcune risposte, Rijndael può essere configurato con una dimensione di blocco di 256 bit, ma Rijndael non è incluso nel runtime standard. Avresti bisogno di un fornitore aggiuntivo o di una biblioteca come Bouncy Castle per usare Rijndael. Il codice a blocchi AES non usa un IV come input, il che è anche il motivo per cui fallisce fornire un IV per la modalità ECB. Alcune altre lingue / runtime semplicemente ignorano l'IV per ECB

Ora c'è un codice che ti permette di specificare un IV a 256 bit (o in realtà: nonce) e cioè GCM. GCM funziona meglio con un nonce di 12 byte però. GCM converte i dati - include il nonce - in un contatore a 128 bit per la modalità CTR internamente.

Si noti che l'aumento della dimensione IV non rende automaticamente l'algoritmo più sicuro. Se hai un input a 256 bit per un IV, potresti usare SHA-256 bit sull'input e prendere invece i 128 bit più a sinistra.

Come stavamo parlando di Java, ecco un codice, puoi armeggiare con la dimensione IV e provare alcuni algoritmi come "AES/CFB/NoPadding" te stesso. Nota che gli IV statici utilizzati nel codice sono solo a scopo dimostrativo . CTR richiede un IV unico, CBC richiede un IV indistinguibile da casuale a un aggressore.

SecretKey aesKey = new SecretKeySpec(new byte[256 / Byte.SIZE], "AES");
byte[] pt = "owlstead".getBytes(StandardCharsets.US_ASCII);

{
    // === CBC mode requires an IV of the same size as the block size
    Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
    // changing the IV size will result in an exception
    byte[] ivBytes = new byte[c.getBlockSize()];
    IvParameterSpec iv = new IvParameterSpec(ivBytes);
    c.init(Cipher.ENCRYPT_MODE, aesKey, iv);
    byte[] ct = c.doFinal(pt);
    System.out.println(Hex.toHexString(ct));
}

{
    // === CTR mode actually requires a complete IV in Java
    // Java (or actually, the SUN provider) requires a 128 bit IV instead of just a nonce
    Cipher c = Cipher.getInstance("AES/CTR/NoPadding");
    // changing the IV size will result in an exception
    byte[] ivBytes = new byte[c.getBlockSize()];
    IvParameterSpec iv = new IvParameterSpec(ivBytes);
    c.init(Cipher.ENCRYPT_MODE, aesKey, iv);
    byte[] ct = c.doFinal(pt);
    System.out.println(Hex.toHexString(ct));
}

{
    // === GCM mode can do it!
    Cipher c = Cipher.getInstance("AES/GCM/NoPadding");
    byte[] ivBytes = new byte[256 / Byte.SIZE];
    GCMParameterSpec gcmSpecWithIV = new GCMParameterSpec(128, ivBytes);
    c.init(Cipher.ENCRYPT_MODE, aesKey, gcmSpecWithIV);
    byte[] ct = c.doFinal(pt);
    System.out.println(Hex.toHexString(ct));
}

{
    // ===  java.security.InvalidAlgorithmParameterException: ECB mode cannot use IV
    Cipher c = Cipher.getInstance("AES/ECB/PKCS5Padding");
    byte[] ivBytes = new byte[c.getBlockSize()];
    IvParameterSpec iv = new IvParameterSpec(ivBytes);
    c.init(Cipher.ENCRYPT_MODE, aesKey, iv);
    byte[] ct = c.doFinal(pt);
    System.out.println(Hex.toHexString(ct));
}
    
risposta data 05.06.2015 - 10:53
fonte
2

Lo scopo dell'IV è "mescolare" un po '.

Senza di esso, i messaggi con lo stesso primo blocco di testo in chiaro condividono tutti lo stesso primo blocco di testo cifrato. Quello scenario non è così raro, considera i file che iniziano con dichiarazioni standard sul loro tipo di file o il modo in cui SMTP usa cose come RCPT TO :, MAIL FROM: etc come elementi comuni. 128 bit (la dimensione del blocco di AES) è piccola, quindi questo genere di cose accadrebbe.

Ci sono diverse modalità di funzionamento, ma usando CBC come il più semplice (e forse ancora più comune?) il testo cifrato da un blocco è usato per alimentare il prossimo, cioè l'output crittografato (testo cifrato) fatto dal primo blocco di il testo in chiaro è usato per XOR il testo in chiaro del blocco 2 (prima che venga crittografato). Il testo cifrato di ciascun blocco viene utilizzato per XOR (OR esclusivo) il testo in chiaro del blocco successivo, e quindi il nome Blocco di cifratura CHAINING . Il problema è che il primo blocco non ha un blocco per precederlo (beh in CBC comunque ...)

Questo è dove il problema descritto per primo è un problema - i messaggi con lo stesso primo blocco di testo in chiaro condividono tutti lo stesso primo blocco di testo cifrato se la stessa chiave è stata utilizzata per crittografarli.

Per evitare questo problema viene utilizzato un IV (vettore di inizializzazione). Questo è un blocco di materiale può essere utilizzato per XOR (OR esclusivo) il primo blocco per avviare la catena. L'IV viene inviato con il messaggio, altrimenti sarebbe impossibile iniziare la decrittazione.

Anche ricodificando lo stesso messaggio più e più volte con la stessa chiave, il primo blocco cifrato sarebbe diverso ogni volta, e quindi concatenando, l'intero messaggio crittografato sarebbe diverso ogni volta.

Se si considera ciò che viene fatto con IV, nell'esempio CBC, non ha alcun senso discutere un IV di qualsiasi dimensione maggiore o minore della dimensione del blocco a 128 bit, perché quella è la dimensione del primo blocco è necessario "mescolare" e da quel momento in poi si usa il precedente testo cifrato per collegarlo. (OK, questo non è vero per tutte le modalità, alcuni IV potrebbero aver bisogno di essere più piccoli del primo blocco, ma per ora consideriamo CBC). Quindi per CBC IV deve essere uguale al blocco, che in AES è sempre 128 bit (indipendentemente dalla dimensione della chiave).

Il vantaggio per la sicurezza non è tanto considerando la lunghezza IV, non pensare che una IV più lunga debba significare una sicurezza migliore, la IV non è la chiave!

Il problema con le IV è più come / come si generano i propri IV. Devono essere di buona qualità (vale a dire materiale pseudo-casuale uniforme statisticamente non correlato a qualsiasi IV precedentemente utilizzato), se si dispone di uno schema di generazione IV povero o di un programma chiave scadente si può minare la sicurezza, potenzialmente aprendolo alla crittanalisi basata su statistiche tecniche.

Quello che vorrei davvero dire è che la crittografia è un po 'complicata :) e persino fare un errore intenzionale ha portato a conseguenze catastrofiche. Alcuni schemi altrimenti buoni sono stati completamente rovinati da piccoli errori di implementazione. Ricorda WEP per wireless chiunque?

Se non comprendi pienamente e in modo completo tutti i fattori coinvolti, ti preghiamo di attenersi agli standard e utilizzare librerie ben utilizzate (ben sottoposte a peer review) e pratiche consolidate.

Cercare di fare qualcosa di intelligente, anche con le migliori intenzioni, è estremamente pericoloso se non si comprendono tutte le conseguenze. Quello che sto cercando di dire molto gentilmente è che se hai bisogno di fare una domanda del tipo: qual è la dimensione IV da usare, non dovresti provare a sperimentare come implementare, basta attenersi ai valori standard.

I migliori auguri con la tua codifica, divertiti ...

    
risposta data 10.10.2016 - 16:44
fonte

Leggi altre domande sui tag