pkcs5padding library example cipher cbc encryption aes ctr-mode

encryption - library - ¿Cómo elegir un IV apropiado(Vector de inicialización) para AES/CTR/NoPadding?



cipher android example (5)

Me gustaría cifrar las cookies que están escritas por una aplicación web y me gustaría mantener el tamaño de las cookies al mínimo, de ahí la razón por la que elegí AES / CTR / NoPadding.

¿Qué recomendarías usar como IV que sea lo suficientemente aleatorio y aún así mantener la aplicación sin estado? Sé que puedo generar un IV aleatorio y anexarlo al mensaje, pero eso aumentará el tamaño de la cookie.

Además, ¿cuál es el tamaño recomendado de IV para AES de 128 bits?

¿De qué otra manera están haciendo esto todos? ¿Existen formas "probadas y verdaderas"? No quiero reinventar la rueda.


Es posible evitar la IV aleatoria mediante el uso de CBC y el almacenamiento del HMAC delante del mensaje. Usar una constante IV al azar es aceptable. Pero debes estar seguro de que los mensajes son todos diferentes.

Este es el caso cuando el mensaje cifrado siempre es diferente. Una clave de licencia con un número de serie coincidiría con este criterio. Una cookie con una ID de usuario o ID de sesión también coincidiría.

Puede usar CBC con una constante aleatoria IV si almacena el hmac delante del mensaje. El hash acumulará todas las variaciones diseminadas en el mensaje en el primer bloque. También puede agregar algunos bytes aleatorios o preferiblemente un número de serie si puede asegurarse de que será único o no reutilizado en mucho tiempo.

Ni siquiera piense en usar CTR con IV constante.


Incluya un número aleatorio grande con la cookie. Un número de 64 o 128 bit es probablemente lo suficientemente grande. Debe ser lo suficientemente grande como para que sea muy difícil obtener duplicados. Asegúrate de poner suficiente entropía en este número. No use simplemente gettime (). Si tiene acceso a CRNG, utilícelo aquí.

Almacene una llave maestra de 256 bit con su aplicación. Use SHA256 para derivar su información clave. De nuevo, usa un CRNG para esto.

$keyblob = sha256( concat("aeskeyid", $masterkey , $randomnumberwithcookie ) ) $aeskey = $keyblob[0..15] $aesiv = $keyblob[16..31]

Es posible que también desee obtener una clave para un HMAC.

$mackeyblob = sha256( concat("hmackeyid", $masterkey , $randomnumberwithcookie ) )

Alternativamente, puede combinar las dos operaciones de hash anteriores en una usando SHA512.

$keyblob = sha512( concat("randomkeyid", $masterkey , $randomnumberwithcookie ) ) $aeskey = $keyblob[0..15] $aesiv = $keyblob[16..31] $hmackey = $keyblob[32..63]


La seguridad de CTR requiere que nunca reutilice un IV para dos encriptaciones de mensaje con la misma clave. En realidad, es aún más estricto: el modo CTR funciona encriptando valores sucesivos de un contador (el IV es solo el valor inicial para ese contador) y se logra una seguridad adecuada solo si el mismo valor de contador no se usa dos veces; esto significa que encriptar un valor con un IV en realidad "consume" una secuencia de valores IV sucesivos que no deben reutilizarse con otro cifrado.

La manera más fácil de hacerlo es usar un generador de números aleatorios criptográficamente seguro y crear un nuevo IV aleatorio de 16 bytes para cada mensaje. Subrayo "criptográficamente seguro" porque eso es importante; un generador de números aleatorios básicos no es suficiente. Con Java, use java.util.SecureRandom . Con Win32, llama a CryptGenRandom() . Con una selección aleatoria, el espacio posible de IV de 128 bits es lo suficientemente grande como para que las colisiones sean extremadamente improbables. En realidad, es por eso que AES usa bloques de 128 bits (lo que implica IV de 128 bits).

La entidad que descifrará el mensaje debe conocer el IV, por lo que debe almacenarlo junto con el mensaje encriptado. Eso es un extra de 16 bytes. Entiendo que esta sobrecarga es lo que desea evitar, aunque 16 bytes no son mucho para una cookie. La longitud máxima efectiva de una cookie depende del navegador web, pero 4000 caracteres parecen funcionar "en todas partes". Un IV de 16 bytes, cuando está codificado en caracteres (por ejemplo, con Base64), usará unos 22 caracteres, es decir, mucho menos del 1% del tamaño máximo de su cookie: ¿puede permitirse eso?

Ahora podemos hacer funky y tratar de reducir la longitud IV a través del engaño:

  • Genere el IV con una función hash: en el lado del servidor, use un contador, que comienza en 0 y se incrementa cada vez que se necesita un nuevo IV. Para obtener el IV, hash el contador con una función hash adecuada, por ejemplo, SHA-256, y mantienes los primeros 16 bytes del valor hash. Las "propiedades de aleatorización" de la función hash serán suficientes para que el IV sea lo suficientemente aleatorio con respecto a los requisitos de CTR. Esto necesita una función hash criptográficamente segura, por lo tanto SHA-256 (evitar MD5). A continuación, solo tiene que almacenar el valor del contador en la cookie, y el contador será más corto que 16 bytes (por ejemplo, si no tiene más de 4 mil millones de clientes, el contador se ajustará en 4 bytes). Sin embargo, hay un costo oculto: el servidor (supongo que el servidor está realizando el cifrado en su sistema) debe asegurarse de que nunca reutilice un valor de contador, por lo que debe almacenar el "contador actual" en algún lugar de una manera que persista el servidor se reinicia, y tampoco falla si se amplía a varios frontales. Eso no es tan fácil en parece.

  • Use un valor externo único: posiblemente, la cookie podría ser parte de un contexto que proporcione datos suficientes para generar un valor que será exclusivo para cada encriptación. Por ejemplo, si la solicitud también contiene (en claro) una "identificación de usuario", puede usar la ID de usuario como fuente IV. La configuración es similar a la anterior: usted obtiene todos esos datos, los rellena en SHA-256, y los primeros 16 bytes de salida SHA-256 es la IV que necesita. Esto funciona solo si esos datos no cambian para un mensaje encriptado dado, y si es realmente único. Esto es algo raro: por ejemplo, un "ID de usuario" es bueno para eso solo si nunca es necesario volver a cifrar un mensaje nuevo para el mismo usuario, y si nunca existe la posibilidad de que se reutilice un ID de usuario (p. Ej. un antiguo usuario se cierra, aparece un nuevo usuario y selecciona la ID de usuario ahora libre).

Usar una IV aleatoria de 16 bytes generada con un PRNG criptográficamente seguro sigue siendo la forma "segura" y la que yo recomiendo. Si encuentra espacio apretado en la cookie, significa que se está acercando al límite de 4 kB, en cuyo punto es posible que desee usar compresión (en los datos antes del cifrado; después de la encriptación, es muy poco probable que funcione la compresión). Use zlib (en Java, puede acceder a zlib a través de java.util.zip ).

Advertencia: en todo lo anterior, no estoy diciendo nada sobre si el cifrado de cookies ayuda a proporcionar las características de seguridad que está tratando de lograr. Por lo general, cuando se necesita encriptación, en realidad necesita encriptación e integridad, y luego debe usar un modo de encriptación-encriptación-y-integridad. Lookup GCM y CCM . Además, el cifrado de cookies es en general bueno para un propósito, que es evitar el costo de almacenar en el servidor un poco de datos específicos del usuario. Si desea cifrar una cookie para otra cosa, por ejemplo, para autenticar a un usuario válido, entonces lo está haciendo mal: el cifrado no es la herramienta adecuada para eso.


No tengo una respuesta directa para su pregunta, pero sí algunas cosas para agregar.

En primer lugar, cifrar la cookie no tiene sentido para mí. Si desea confidencialidad de sus datos, no debe almacenarlos en una cookie de todos modos. Si desea integridad (es decir, no es posible alterar el contenido de la cookie), debe usar un hash con clave (HMAC, por ejemplo).

Otra nota es nunca usar un IV que sea todo 0 solo por conveniencia.

Las IV tienen el mismo tamaño que tu bloque. En el caso de AES-128, el tamaño de bloque es 128, el tamaño de clave es 128 y, por lo tanto, el IV es de 128 bits.

La mejor manera de hacerlo es creando una clave AES aleatoria y utilizándola como IV. Este IV aleatorio puede ser público siempre que no se reutilice en encriptaciones posteriores con la misma clave

editar :

Es posible que desee consultar esta página wiki para obtener más información sobre qué modo usar. Sin embargo, nunca use ECB a menos que esté seguro de que debe usarlo. E incluso entonces, verifique con un experto. CBC es, por lo que yo sé, el más seguro (junto con PCBC).

http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation


Si no haces el IV al azar (es decir, utilizas un grupo repetitivo de números), será más fácil descifrar la clave si la cookie siempre comienza con el mismo texto claro.

El tamaño IV para AES-128 es de 128 bits. IIRC, el IV tiene el mismo tamaño que el bloque de cifrado. 128 bits es 16 bytes. 32 bytes si lo almacena como una cadena hexadecimal ASCII. ¿Eso es realmente demasiado? 32 bytes en este día y edad no es mucho en absoluto ...