Nonces, salts, paddings y otras hierbas aleatorias para aderezar ensaladas criptográficas

Gonzalo Álvarez Marañón    17 noviembre, 2020
Nonces, salts, paddings y otras hierbas aleatorias para aderezar ensaladas criptográficas

Cuentan las crónicas de los reyes de Noruega que el rey Olaf Haraldsson el Santo disputaba con el vecino rey de Suecia la posesión de la isla de Hísing. Decidieron resolver la disputa pacíficamente con un juego de dados. Tras acordar que la ganaría quien obtuviera la puntuación más alta, lanzó los dados en primer lugar el rey de Suecia.

–¡Doce! ¡He ganado! No hace falta que arrojéis los dados, rey Olaf.

Mientras agitaba los dados entre sus manos, Olaf el Santo replicó:

–Todavía quedan dos seises en los dados y no le será difícil a Dios, mi Señor, hacer que vuelvan a aparecer en mi favor.

Volaron los dados y volvieron a salir dos seises. De nuevo lazó los dados el rey de Suecia y de nuevo sacó dos seises. Cuando le llegó el turno a Olaf el Santo, uno de los dados arrojados se partió en dos, mostrando una mitad un 6 y la otra, un 1, sumando un total de 13. Como consecuencia, la titularidad de la isla le fue adjudicada a Noruega y ambos reyes se despidieron como amigos.

La aleatoriedad juega un papel fundamental en todos los juegos de azar. Y lo que tal vez te sorprenda más: la criptografía no podría existir sin la aleatoriedad. En este artículo descubrirás cómo se usa la aleatoriedad en criptografía y cómo obtener números aleatorios, tarea, como verás, nada sencilla.

¿Qué es la aleatoriedad?

Existen tantas definiciones sobre aleatoriedad que podríamos llenar un libro con ellas. En criptografía es común la siguiente interpretación, que cito de Bruce Scheneier:

La aleatoriedad se refiere al resultado de un proceso probabilístico que produce valores independientes, uniformemente distribuidos e impredecibles que no pueden ser reproducidos de manera fiable.

Quiero destacar los siguientes tres ingredientes que debe exhibir todo generador de aleatoriedad para usarse con garantías en “ensaladas criptográficas”:

  • Independencia de valores: no existe ninguna correlación entre los valores generados. Por ejemplo, si lanzas una moneda (sin trucar) al aire y sale cara nueve veces seguidas, ¿qué es más probable? ¿Cara o cruz en el décimo lanzamiento? Pues la probabilidad sigue siendo 1/2, porque el resultado de un lanzamiento es independiente de los lanzamientos precedentes.
  • Impredecibilidad: aunque te aburras observando valores y más valores, no puedes predecir con probabilidad superior al azar el próximo valor, sin importar lo larga que haya sido la secuencia precedente. Nuevamente, monedas, dados y ruletas constituyen excelentes generadores aleatorios porque, por muchas teorías que elabores, no sabrás qué saldrá a continuación (asumiendo que no están trucados).
  • Distribución uniforme: seguro que mientras leías la crónica del rey Olaf el Santo habrás pensado: «¡Imposible! ¿Cómo van a salir dos seises cuatro veces seguidas?». Y haces bien en dudar, porque la probabilidad de esta secuencia es (1/36)·(1/36)·(1/36)·(1/36) = (1/36)4 = 0,00000059537… o 1 entre 1,67 millones. No es probable que se dé esa secuencia, pero sí es posible. De hecho, si se tiran los dados mil millones de veces aparecería en promedio unas 600 veces. La aleatoriedad tal y como la imaginamos se manifiesta en los grandes números, no en los pequeños números. Cuantos más valores se generen, esperaremos ver todas las secuencias posibles, distribuidas uniformemente, sin ningún tipo de sesgo.

El problema con la aleatoriedad es que nunca estás seguro. ¿Estaban trucados los dados de los reyes nórdicos? ¿Coincidió que, mira tú por dónde qué casualidad, esa secuencia improbable se dio ese día? Existen pruebas de aleatoriedad que dictaminan con una confianza muy elevada si un generador es o no aleatorio, pero nunca se puede estar absolutamente seguro. De hecho, existe una amplia gama de conjuntos de pruebas estadísticas (NIST, Test01, Diehard, ENT, etc.) que tratan de descartar las secuencias que no verifican ciertas propiedades estadísticas, aunque no pueden garantizar la perfecta aleatoriedad.

Cómo se generan los números aleatorios

Sí, pero ¿cómo se generan números aleatorios en un ordenador? Para no complicar las cosas, limitémonos a dos enfoques:

  • Generadores de bits verdaderamente aleatorios (TRNG): requieren una fuente natural de aleatoriedad. Diseñar un dispositivo de hardware o un programa de software para explotar esta aleatoriedad y producir una secuencia de bits libre de sesgos y correlaciones es una tarea difícil. Por ejemplo, se sabe que el ruido térmico de una resistencia es una buena fuente de aleatoriedad. Los TRNGs también pueden recolectar entropía en un sistema operativo en ejecución mediante el uso de sensores conectados, dispositivos de E/S, actividad de la red o del disco, registros del sistema, procesos en ejecución y actividades del usuario como pulsaciones de teclas y movimientos del ratón. Estas actividades generadas por el sistema y por el humano pueden funcionar como una buena fuente de entropía, pero pueden ser frágiles y ser manipuladas por un atacante. Además, son lentas para producir bits aleatorios.
  • Generadores de números pseudoaleatorios (PRNG): por desgracia, la mayoría de las fuentes naturales no son prácticas debido a la lentitud inherente al muestreo del proceso y a la dificultad de asegurar que un adversario no observe el proceso. Además, sería imposible de reproducir, lo que exigiría dos copias de la misma secuencia: una para Alice y otra para Bob, lo que entraña la dificultad casi insalvable de hacérselas llegar a ambos. Por lo tanto, se requiere un método para generar aleatoriedad que se pueda implementar en software y que sea fácilmente reproducible, tantas veces como sea necesario. La respuesta está en los generadores de números pseudoaleatorios: un algoritmo matemático eficiente y determinístico para transformar una cadena corta y uniforme de longitud k, llamada la semilla, en una cadena de salida más larga, de aspecto uniforme (o pseudoaleatorio), de longitud l >> k. Dicho de otra manera:

Un generador pseudoaleatorio utiliza una pequeña cantidad de verdadera aleatoriedad para generar una gran cantidad de pseudoaleatoriedad”.

Para qué sirve la aleatoriedad en criptografía

La aleatoriedad es difícil de generar y difícil de medir. A pesar de todo, es un ingrediente clave para el éxito de cualquier algoritmo criptográfico. Fíjate los diferentes papeles que puede llegar a jugar la aleatoriedad para hacer segura la criptografía.

  • Claves de cifrado: para cifrar un mensaje se necesita una clave de cifrado, tanto para algoritmos de clave secreta como algoritmos de clave pública. Si esta clave es fácil de adivinar, ¡vaya timo! Un requisito fundamental para el uso seguro de todo algoritmo de cifrado es que la clave se seleccione de manera aleatoria (o lo más aleatoriamente posible). De hecho, un problema al que se enfrenta el ransomware es cómo generar claves aleatorias para cifrar los archivos de las víctimas. El mejor algoritmo de cifrado del mundo no vale nada si se desvela la clave. Se recomienda usar un dispositivo hardware para generarlas, como el TPM de los sistemas Windows o un HSM.
  • Vectores de inicialización: los algoritmos de cifrado en bloque se sirven de un valor inicial aleatorio, llamado vector de inicialización (IV), para arrancar el cifrado del primer bloque y garantizar que el mismo mensaje cifrado con la misma clave nunca arrojará el mismo valor, siempre que se use un IV distinto. Este valor puede ser conocido, pero no predecible. Nuevamente, resulta crítico por tanto usar valores aleatorios (e impredecibles) para evitar repeticiones. Una vez más, se recomienda acudir a dispositivos hardware para generarlos.
  • Nonces: un nonce es un número que solo puede usarse una vez (number used once) en un protocolo seguro de comunicación. ¿Y qué utilidad pueden tener estos fugaces nonces? De forma parecida a lo explicado con los vectores de inicialización, los nonces aseguran que aunque se transmitan los mismos mensajes durante una comunicación, se cifrarán de forma completamente diferente, lo que evita los ataques de reproducción o de reinyección. De hecho, los nonces suelen funcionar como IVs: se genera un nonce y se cifra con la clave secreta para crear el IV. Se utilizan además en protocolos de autenticación, como en HTTPS, o para los sistemas de prueba de trabajo, como en Bitcoin.
  • Salts: la sal es otro valor aleatorio usado comúnmente a la hora de almacenar contraseñas en una base de datos. Como sabrás, nunca deben almacenarse las contraseñas en claro: ¡cualquier atacante que accediera a la tabla de usuarios vería las contraseñas! En su lugar podría almacenarse el hash de la contraseña. Pero ¿qué pasará si dos contraseñas son iguales? ¡Darán el mismo hash! Si un atacante roba la base de datos y ve muchos hashes de contraseñas idénticos, ¡bingo! Sabe que son contraseñas facilonas, de las que todo el mundo elige cuando no se esmera. Por otro lado, se pueden precomputar gigantescas tablas de hashes de contraseñas conocidas y buscar esos hashes en la base de datos robada. Para evitar estos problemas, se añade un valor aleatorio: la sal. En adelante, no se guardará el hash de la contraseña, sino la sal y el hash de la contraseña concatenada con la sal: H( contraseña || sal). Por consiguiente, dos contraseñas idénticas darán como resultado dos hashes diferentes siempre que la sal sea aleatoria. Igualmente, ya no sirven de nada los ataques que precalculaban hashes de contraseñas conocidas. Como los nonces, las sales no tienen que ser secretas, pero sí aleatorias. Otra aplicación típica de sales es en funciones de derivación de claves a partir de contraseñas (KDF). Un esquema muy sencillo consiste en repetir n veces el hash de una contraseña y una sal:

clave = Hn( contraseña || salt )

  • Relleno: el famoso algoritmo de cifrado de clave pública RSA es determinista, es decir, el mismo mensaje cifrado con la misma clave arrojará siempre el mismo texto cifrado. ¡Eso no puede ser! Hace falta aleatorizar el mensaje en claro. ¿Cómo? Añadiendo bits aleatorios de manera muy cuidadosa, en lo que se conoce como el esquema OAEP, lo que transforma al RSA tradicional en un esquema probabilístico. Igualmente, para evitar la maleabilidad del cifrado con RSA en las firmas digitales, el esquema PSS añade aleatoriedad.
  • Firmas ciegas: para conseguir que una persona firme digitalmente un documento, pero sin que pueda ver el contenido del documento firmado, se utilizan igualmente valores aleatorios que “ciegan” al firmante, ocultando el contenido del mensaje a firmar. Posteriormente, conocido el valor aleatorio, puede verificarse el valor de la firma. Es el equivalente digital a firmar un documento poniendo encima un papel de calco: impide ver el documento a firmar, pero transfiere perfectamente la firma al documento. ¿Y quién querría firmar algo sin verlo antes? Estos protocolos de firma ciega su utilizan, por ejemplo, en aplicaciones de voto electrónico y de dinero digital.

Sin aleatoriedad no hay seguridad

Los números aleatorios tienen una importancia capital en criptografía: constituyen la base misma de la seguridad. La criptografía no puede incorporarse a los productos y servicios sin números aleatorios. Un generador de números aleatorios inadecuado puede comprometer fácilmente la seguridad de todo el sistema, como confirma la larga lista de vulnerabilidades debidas a una pobre aleatoriedad. Por tanto, la elección del generador aleatorio debe tomarse cuidadosamente al diseñar cualquier solución de seguridad. Sin buena aleatoriedad no hay seguridad.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *