Argon2 es una función de derivación de claves que fue seleccionada como ganadora de la Competencia de Hashing de Contraseñas de 2015. [1] [2] Fue diseñada por Alex Biryukov , Daniel Dinu y Dmitry Khovratovich de la Universidad de Luxemburgo . [3] La implementación de referencia de Argon2 se publica bajo una licencia Creative Commons CC0 (es decir, dominio público ) o la Licencia Apache 2.0 , y proporciona tres versiones relacionadas:
- Argon2d maximiza la resistencia a los ataques de piratería de GPU . Accede a la matriz de memoria en un orden que depende de la contraseña, lo que reduce la posibilidad de ataques de compensación de tiempo y memoria (TMTO), pero introduce posibles ataques de canal lateral .
- Argon2i está optimizado para resistir ataques de canal lateral. Accede a la matriz de memoria en un orden independiente de la contraseña.
- Argon2id es una versión híbrida. Sigue el enfoque de Argon2i para la primera mitad del paso por la memoria y el enfoque de Argon2d para los pasos posteriores. RFC 9106 recomienda usar Argon2id si no conoce la diferencia entre los tipos o si considera que los ataques de canal lateral son una amenaza viable. [4]
Los tres modos permiten la especificación mediante tres parámetros que controlan:
- tiempo de ejecución
- memoria requerida
- grado de paralelismo
Criptoanálisis
Si bien no existe un criptoanálisis público aplicable a Argon2d, hay dos ataques publicados a la función Argon2i. El primer ataque es aplicable solo a la versión anterior de Argon2i, mientras que el segundo se ha extendido a la última versión (1.3). [5]
El primer ataque muestra que es posible calcular una función Argon2i de un solo paso utilizando entre un cuarto y un quinto del espacio deseado sin penalización de tiempo, y calcular una función Argon2i de múltiples pasos utilizando solo el espacio N / e (≈ N /2.72) sin penalización de tiempo. [6] Según los autores de Argon2, este vector de ataque se corrigió en la versión 1.3. [7]
El segundo ataque muestra que Argon2i puede calcularse mediante un algoritmo que tiene una complejidad O( n 7/4 log( n )) para todas las opciones de parámetros σ (costo de espacio), τ (costo de tiempo) y número de subprocesos tales que n = σ ∗ τ . [8] Los autores de Argon2 afirman que este ataque no es eficiente si Argon2i se utiliza con tres o más pasadas. [7] Sin embargo, Joël Alwen y Jeremiah Blocki mejoraron el ataque y demostraron que para que el ataque falle, Argon2i v1.3 necesita más de 10 pasadas sobre la memoria. [5]
Para abordar estas preocupaciones, RFC9106 recomienda utilizar Argon2id para mitigar en gran medida dichos ataques. [9]
Algoritmo
Fuente: [4]
Función Argon2 Entradas: password ( P ): Bytes (0..2 32 -1) Contraseña (o mensaje) a ser hasheada salt ( S ): Bytes (8..2 32 -1) Sal (16 bytes recomendados para hashear contraseñas) parallelism ( p ): Número (1..2 24 -1) Grado de paralelismo (es decir, número de hilos) tagLength ( T ): Número (4..2 32 -1) Número deseado de bytes devueltos memorySizeKB ( m ): Número (8p..2 32 -1) Cantidad de memoria (en kibibytes ) a usar iterations ( t ): Número (1..2 32 -1) Número de iteraciones a realizar version ( v ): Número (0x13) La versión actual es 0x13 (19 decimal) key ( K ): Bytes (0..2 32 -1) Clave opcional (Errata: PDF dice 0..32 bytes, RFC dice 0..2 32 bytes) associateData ( X ): Bytes (0..2 32 -1) Datos adicionales arbitrarios opcionales hashType ( y ): Número (0=Argon2d, 1=Argon2i, 2=Argon2id) Salida: etiqueta: Bytes (tagLength) Los bytes generados resultantes, tagLength bytes de longitud Generar bloque inicial de 64 bytes H 0 . Todos los parámetros de entrada se concatenan y se introducen como fuente de entropía adicional. Erratas: RFC dice que H 0 es de 64 bits; PDF dice que H 0 es de 64 bytes. Erratas: RFC dice que el hash es H^, el PDF dice que es ℋ (pero no documenta qué es ℋ). En realidad es Blake2b. A los elementos de longitud variable se les antepone su longitud como números enteros little-endian de 32 bits. buffer ← paralelismo ∥ tagLength ∥ memorySizeKB ∥ iteraciones ∥ versión ∥ hashType ∥ Longitud(contraseña) ∥ Contraseña ∥ Longitud(sal) ∥ sal ∥ Longitud(clave) ∥ clave ∥ Longitud(datos asociados) ∥ datos asociados H 0 ← Blake2b(buffer, 64) //el tamaño de hash predeterminado de Blake2b es de 64 bytes Calcular el número de bloques de 1 KB redondeando memorySizeKB al múltiplo más cercano de 4*paralelismo kibibytes blockCount ← Piso(memoriaTamañoKB, 4*paralelismo) Asignar una matriz bidimensional de bloques de 1 KiB (paralelismo filas x columnCount columnas) columnCount ← blockCount / parallelism; //En el RFC, columnCount se conoce como q Calcular el primer y segundo bloque (es decir, columna cero y uno) de cada carril (es decir, fila) para i ← 0 a paralelismo-1 hacer para cada fila B i [0] ← Hash(H 0 ∥ 0 ∥ i, 1024) //Generar un resumen de 1024 bytes B i [1] ← Hash(H 0 ∥ 1 ∥ i, 1024) //Generar un resumen de 1024 bytes Calcular las columnas restantes de cada carril para i ← 0 a paralelismo-1 hacer //para cada fila para j ← 2 a columnCount-1 hacer //para cada columna subsiguiente //los índices i' y j' dependen de si es Argon2i, Argon2d o Argon2id (Ver sección 3.4) i′, j′ ← GetBlockIndexes(i, j) //la función GetBlockIndexes no está definida B i [j] = G(B i [j-1], B i′ [j′]) //la función hash G no está definida Pases posteriores cuando iteraciones > 1 para nIteration ← 2 a iteraciones hacer para i ← 0 a paralelismo-1 hacer para cada fila para j ← 0 a columnCount-1 hacer //para cada columna subsiguiente //Los índices i' y j' dependen de si es Argon2i, Argon2d o Argon2id (consulte la sección 3.4) i′, j′ ← ObtenerÍndicesDeBloque(i, j) si j == 0 entonces B i [0] = B i [0] xor G(B i [columnCount-1], B i′ [j′]) de lo contrario B i [j] = B i [j] xor G(B i [j-1], B i′ [j′]) Calcular el bloque final C como el XOR de la última columna de cada fila C ← B 0 [columnCount-1] para i ← 1 hasta paralelismo-1 hacer C ← C xor B i [columnCount-1] Calcular la etiqueta de salida que devuelve Hash(C, tagLength)
Función hash de longitud variable
Argon2 utiliza una función hash capaz de generar resúmenes de hasta 232 bytes de longitud. Esta función hash está integrada internamente en Blake2 .
Función Hash(message, digestSize) Entradas: message: Bytes (0..2 32 -1) Mensaje a codificar digestSize: Entero (1..2 32 ) Número deseado de bytes a devolver Salida: digest: Bytes (digestSize) Los bytes generados resultantes, digestSize en bytes de longitud Hash es una función hash de longitud variable, creada con Blake2b, capaz de generar resume hasta 2 bytes de 32 bytes. Si el digestSize solicitado es de 64 bytes o menos, entonces usamos Blake2b directamente if (digestSize <= 64) then return Blake2b(digestSize ∥ message, digestSize) //concatena el digestSize little endian de 32 bits con los bytes del mensaje Para hashes deseados de más de 64 bytes (por ejemplo, 1024 bytes para bloques Argon2), Usamos Blake2b para generar el doble de bloques de 64 bytes necesarios, y luego solo use 32 bytes de cada bloque Calcular la cantidad de bloques completos (sabiendo que solo vamos a utilizar 32 bytes de cada uno) r ← Ceil(digestSize/32)-2; Generar r bloques completos. El bloque inicial se genera a partir del mensaje V 1 ← Blake2b(digestSize ∥ message, 64); los bloques subsiguientes se generan a partir de los bloques anteriores para i ← 2 hasta r, hacer V i ← Blake2b(V i-1 , 64) Generar el bloque final (posiblemente parcial) partialBytesNeeded ← tamañoDigesto – 32*r; V r+1 ← Blake2b(V r , bytes parciales necesarios) Concatenar los primeros 32 bytes de cada bloque V i (excepto el último bloque posiblemente parcial, que tomamos completo) Sea A i los 32 bytes inferiores del bloque V i y devuelva A 1 ∥ A 2 ∥ ... ∥ A r ∥ V r+1
Parámetros mínimos recomendados
A partir de mayo de 2023, la hoja de trucos de almacenamiento de contraseñas de OWASP recomienda que las personas "utilicen Argon2id con una configuración mínima de 19 MiB de memoria, un recuento de iteraciones de 2 y 1 grado de paralelismo". [10]
OWASP recomienda que se prefiera Argon2id sobre Argon2d y Argon2i porque proporciona una resistencia equilibrada tanto a los ataques basados en GPU como a los ataques de canal lateral. [10]
OWASP señala además que las siguientes opciones de Argon2id proporcionan una fuerza criptográfica equivalente y simplemente intercambian el uso de memoria por la carga de trabajo computacional: [10]
- Memoria: 46 MiB, Iteraciones: 1, Paralelismo: 1
- Memoria: 19 MiB, Iteraciones: 2, Paralelismo: 1
- Memoria: 12 MiB, Iteraciones: 3, Paralelismo: 1
- Memoria: 9 MiB, Iteraciones: 4, Paralelismo: 1
- Memoria: 7 MiB, Iteraciones: 5, Paralelismo: 1
Referencias
- ^ "Concurso de hash de contraseñas"
- ^ Jos Wetzels (8 de febrero de 2016). "Ábrete Sésamo: La competencia de hash de contraseñas y Argon2". arXiv : 1602.03097 [cs.CR].
- ^ Argon2: la función de memoria difícil para el hash de contraseñas y otras aplicaciones, Alex Biryukov, et al, 1 de octubre de 2015
- ^ ab Biryukov, Alex; Dinu, Daniel; Khovratovich, Dmitry; Josefsson, Simon (septiembre de 2021). "Función de memoria de Argon2 para aplicaciones de hash de contraseñas y prueba de trabajo" . Consultado el 9 de septiembre de 2021 .
- ^ por Joël Alwen; Jeremiah Blocki (5 de agosto de 2016). Hacia ataques prácticos a Argon2i y Balloon Hashing (PDF) (Informe).
- ^ Henry; Corrigan-Gibbs; Dan Boneh; Stuart Schechter (14 de enero de 2016). Hashing de globo: funciones hash demostrablemente difíciles de manejar con patrones de acceso independientes de los datos (PDF) (informe).
- ^ ab "[Cfrg] Argon2 v.1.3". www.ietf.org . Consultado el 30 de octubre de 2016 .
- ^ Joël Alwen; Jeremiah Blocki (19 de febrero de 2016). Computación eficiente de funciones de memoria independientes de los datos (PDF) (informe).
- ^ "Recomendaciones". Función de memoria de Argon2 para aplicaciones de hash de contraseñas y prueba de trabajo. IETF . Septiembre de 2021. sec. 7.4. doi : 10.17487/RFC9106 . RFC 9106 . Consultado el 12 de julio de 2023 .
- ^ abc "Hoja de referencia para el almacenamiento de contraseñas". Serie de hojas de referencia de OWASP . OWASP . Consultado el 17 de mayo de 2023 .
Enlaces externos
- Repositorio de código fuente de Argon2 en Github
- Especificación de Argon2
- Concurso de hash de contraseñas
- Página Uni.Lu Argon2
- Hashing de globo: una función que requiere mucha memoria y que ofrece protección demostrable contra ataques secuenciales
- Función de memoria de alto rendimiento Argon2 RFC 9106 para aplicaciones de hash de contraseñas y prueba de trabajo