Quiero cifrar los datos usando AES en java, y quiero inicializar el cifrado con el Vector de inicialización. ¿Puedo usar 256 bits IV? ¿O debo usar solo 128 bits IV?
El IV depende del modo de operación . Para la mayoría de los modos (por ejemplo, CBC), el IV debe tener la misma longitud que el bloque . AES utiliza bloques de 128 bits, por lo que un IV de 128 bits. Tenga en cuenta que AES-256 utiliza una clave de 256 bits (de ahí el nombre), pero aún con bloques de 128 bits.
AES fue elegido como un subconjunto de la familia de cifrados de bloque conocido como Rijndael . Esa familia incluye no menos de 15 variantes, para tres tamaños de bloque posibles (128, 192 y 256 bits) y cinco tamaños de clave posibles (128, 160, 192, 224 y 256 bits). AES , según lo estandarizado por NIST, incluye solo tres variantes, todas con bloques de 128 bits y con claves de 128, 192 o 256 bits.
Para confundir aún más las cosas, algunos marcos de software se equivocaron; p.ej. PHP usa "MCRYPT_RIJNDAEL_128" para designar Rijndael con claves de 128 bits y bloques de 128 bits (es decir, lo mismo que AES-128), y "MCRYPT_RIJNDAEL_256" para Rijndael con claves de 256 bits y bloques de 256 bits (es decir, no uno de las variantes AES, y en particular no AES-256).
Debes usar un 128 bit IV. Para CBC, el modo IV debe coincidir con el tamaño del bloque, que siempre es de 128 bits para AES.
Rijndael, el candidato AES ganador, se define para bloques de 128 y 256 bits, pero solo los bloques de 128 bits se estandarizaron como AES. Algunas bibliotecas admiten Rijndael con bloques de 256 bits, pero luego ya no estás usando AES.
Si necesita un IV más largo por algún motivo, puede usar un KDF o un hash para convertir la clave original y el IV en la clave que realmente usa para AES.
El manejo de IV en Java depende del proveedor criptográfico que se utiliza. El proveedor de SUN que viene con los tiempos de ejecución de Oracle es bastante estricto; requiere que el IV sea del mismo tamaño que el tamaño de bloque para la mayoría de los modos de operación . Esto es cierto incluso para el modo CTR en el que podría haber esperado que el suministro de un nonce (los primeros bytes del IV) sea suficiente. Por supuesto, el modo ECB no requiere un IV, por lo que lanzará una excepción si intenta suministrar uno.
El tamaño de bloque de AES es siempre de 128 bits, por lo que no es posible un IV de 256 bits para la mayoría de los modos de operación. Como ya se señaló en algunas respuestas, Rijndael se puede configurar con un tamaño de bloque de 256 bits, pero Rijndael no está incluido en el tiempo de ejecución estándar. Necesitaría un proveedor o biblioteca adicional como Bouncy Castle para usar Rijndael. El cifrado de bloque AES no utiliza un IV como entrada, por lo que también falla el suministro de un IV para el modo ECB. Algunos otros idiomas / tiempos de ejecución simplemente ignoran el IV para el BCE
Ahora hay un cifrado que le permite especificar un IV de 256 bits (o en realidad: nonce) y es GCM. Sin embargo, GCM funciona mejor con un nonce de 12 bytes. GCM convierte los datos (incluye el nonce) a un contador de 128 bits para el modo CTR internamente.
Tenga en cuenta que aumentar el tamaño de IV no hace que el algoritmo sea más seguro automáticamente. Si tiene una entrada de 256 bits para un IV, entonces podría usar un bit SHA-256 en la entrada y tomar los 128 bits más a la izquierda.
Mientras hablábamos de Java, aquí hay algo de código, puedes jugar con el tamaño IV y probar algunos algoritmos, como "AES/CFB/NoPadding"
. Tenga en cuenta que los IV estáticos utilizados en el código son solo para fines de demostración . CTR requiere un IV único, CBC requiere un IV indistinguible de aleatorio a un atacante.
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));
}
El propósito del IV es "mezclarlo" un poco.
Sin él, todos los mensajes con el mismo primer bloque de texto simple compartirían el mismo primer bloque de texto cifrado. Ese escenario no es tan raro, considere los archivos que comienzan con declaraciones estándar sobre su tipo de archivo o la forma en que SMTP usa elementos como RCPT TO :, MAIL FROM: etc como elementos comunes. 128 bits (el tamaño de bloque de AES) es pequeño, por lo que este tipo de cosas sucedería.
Hay diferentes modos de operación, pero al usar CBC como el más simple (¿y quizás aún más común?), el texto cifrado de un bloque se utiliza para alimentar al siguiente, es decir, la salida cifrada (texto cifrado) realizada desde el primer bloque de el texto simple se utiliza para XORAR el texto simple del bloque 2 (antes de que luego se cifre). El texto cifrado de cada bloque se usa para XOR (excluyendo O) el texto simple del siguiente bloque, y por lo tanto el nombre Cifrado bloque CHAINING . El problema es que el primer bloque no tiene ningún bloque que lo preceda (bueno, de todos modos, en CBC ...)
Aquí es donde el problema descrito por primera vez es un problema: los mensajes con el mismo primer bloque de texto sin formato compartirían el mismo primer bloque de texto cifrado si se utilizara la misma clave para cifrarlos.
Para evitar ese problema, se utiliza un IV (vector de inicialización). Este es un bloque de material que se puede utilizar para XOR (OR exclusivo) el primer bloque para iniciar la cadena. El IV se envía con el mensaje, de lo contrario sería imposible iniciar el descifrado.
Incluso si se vuelve a cifrar el mismo mensaje una y otra vez con la misma clave, el primer bloque cifrado será diferente cada vez, y por lo tanto, al encadenar, todo el mensaje cifrado será diferente cada vez.
Si considera lo que se está haciendo con la IV, en mi ejemplo de CBC, no tiene ningún sentido discutir una IV de cualquier tamaño mayor o menor que el tamaño del bloque de 128 bits, porque ese es el tamaño del primer bloque debe "mezclarse" y, a partir de ese momento, utilizar el texto cifrado anterior para encadenarlo. (OK, esto no es cierto para todos los modos, algunos IV deben ser más pequeños que el primer bloque, pero consideremos CBC por ahora). Por lo tanto, para CBC, el IV debe ser el mismo que el tamaño de bloque, que en AES siempre es de 128 bits (independientemente del tamaño de clave).
El beneficio para la seguridad no es tanto considerando la longitud del IV, ¡no creas que un IV más largo debe significar una mejor seguridad, el IV no es la clave!
El problema con las IV es más qué / cómo generas tus IV. Deben ser de buena calidad (es decir, material pseudoaleatorio uniforme no relacionado estadísticamente con cualquier IV utilizado anteriormente), si tiene un esquema de generación de IV deficiente o un programa de claves deficiente, puede socavar la seguridad, lo que posiblemente lo abra al criptoanálisis basado en estadísticas técnicas.
Lo que realmente me gustaría decir es que la criptografía es un poco complicada :) e incluso cometer un error con la mejor intención ha llevado a algunas consecuencias catastróficas. Algunos esquemas por lo demás buenos se han arruinado completamente por pequeños errores de implementación. ¿Recuerda WEP para alguien inalámbrico?
Si no comprende completamente y en profundidad todos los factores involucrados, respete los estándares y utilice bibliotecas y prácticas establecidas bien usadas (revisadas por expertos)
Tratar de hacer algo inteligente, incluso con las mejores intenciones, es extremadamente peligroso a menos que entiendas todas las consecuencias. Lo que estoy tratando de decir con mucha cortesía es que si necesita hacer una pregunta como: ¿cuál es el tamaño de IV que debe usar, no debería intentar experimentar con la implementación, simplemente apéguese a los valores estándar?
Mis mejores deseos con su codificación, disfrute ...
Lea otras preguntas en las etiquetas aes initialisation-vector