En criptografía, una función de derivación de clave (KDF) crea una clave secreta larga (que se llama "hash") a partir de una frase secreta, como una contraseña. El resultado de una función de derivación de clave tendrá un aspecto común a otro resultado hecho a partir de una frase aleatoria. También se utilizan para reutilizar claves secretas en un formato específico, como el uso de una clave secreta compartida del intercambio de claves Diffie-Hellman para enviar secretos en AES.
¿Para qué sirven las KDF?
Las KDF tienen varios propósitos importantes:
- Derivar claves criptográficas seguras a partir de material de menor entropía (por ejemplo, una contraseña o una clave compartida de un protocolo de establecimiento de claves).
- Estirar claves (key stretching): aumentar el coste computacional necesario para probar contraseñas por fuerza bruta.
- Separación de claves (key separation): generar varias claves independientes (por ejemplo, para cifrado y autenticación) a partir de una sola semilla.
- Normalizar la salida para que tenga la longitud y el formato adecuados para algoritmos simétricos (por ejemplo, claves de 128/256 bits para AES).
Conceptos clave y cómo funcionan
- Entrada (seed): la frase secreta o material inicial (contraseña, clave DH compartida, etc.).
- Salt (sal): datos aleatorios únicos por derivación que previenen ataques por tablas precalculadas (rainbow tables) y permiten que dos iguales contraseñas produzcan resultados distintos. El salt no necesita ser secreto y se almacena junto al resultado.
- Iteraciones / coste: número de rondas o parámetros que aumentan el coste computacional (CPU y/o memoria). Incrementan la dificultad de ataques por fuerza bruta.
- Salida: la clave derivada de la longitud deseada; suele presentarse como un valor pseudoaleatorio uniforme.
- Función subyacente: puede basarse en hash (HMAC, SHA), cifrado o funciones de memoria intensiva.
Tipos y algoritmos comunes
- PBKDF2 (basado en HMAC): ampliamente usado y soportado por muchas librerías; configurable en número de iteraciones. Adecuado si se necesita compatibilidad amplia.
- bcrypt: diseñado para almacenar contraseñas; incorpora factor de costo y resistencia a ataques en hardware especializado.
- scrypt: función memory-hard que obliga a usar memoria significativa, limitando la ventaja de GPUs/ASICs.
- Argon2 (Argon2i, Argon2d, Argon2id): ganador del concurso Password Hashing Competition; Argon2id es una opción recomendada por su equilibrio entre resistencia a canal lateral y ataques por GPU/ASIC.
- HKDF (HMAC-based Extract-and-Expand KDF): diseñado para extraer y expandir material pseudoaleatorio; útil en protocolos para derivar múltiples claves a partir de una fuente de alta entropía.
Buenas prácticas
- Usar un salt aleatorio y único para cada derivación y almacenarlo junto al resultado (no es secreto).
- Seleccionar parámetros de coste (iteraciones, memoria, paralelismo) de forma que la derivación sea notablemente costosa para atacantes pero aceptable para la experiencia de usuario; probar en el hardware objetivo. Una práctica común: ajustar el coste para que la operación dure decenas o cientos de milisegundos en el dispositivo objetivo.
- Para hashing de contraseñas, preferir funciones memory-hard actuales (Argon2id o scrypt) frente a sólo aumentar iteraciones de PBKDF2.
- Derivar una clave con la longitud apropiada para el uso final (p. ej., 128 o 256 bits para AES).
- Usar HKDF o un mecanismo similar cuando se necesite extraer y expandir material de alta entropía para múltiples claves (separación de dominios mediante el parámetro "info").
- No reutilizar parámetros (salt o contador de iteraciones) sin motivo; documentar y versionar el esquema de hashing para poder migrar si cambian las recomendaciones.
Seguridad y consideraciones prácticas
- El objetivo de una KDF es que la salida sea indistinguible de una cadena aleatoria para un atacante que desconozca la entrada.
- Elegir parámetros adecuados es crítico: valores débiles permiten ataques por fuerza bruta; valores excesivos degradan la usabilidad o el rendimiento del servidor.
- Considerar el uso de un pepper (valor secreto adicional) en sistemas donde sea aceptable almacenar un secreto separado para aumentar la protección frente a filtraciones de la base de datos de hashes.
- Proteger implementaciones contra fugas por canales laterales (timing, memoria) cuando sea relevante.
- Evitar crear KDFs caseros: usar implementaciones probadas y mantenidas por la comunidad o estandarizadas.
Ejemplo práctico (conceptual)
Para obtener una clave AES de 256 bits a partir de una contraseña:
- Generar un salt aleatorio (p. ej. 16 bytes) y guardarlo.
- Aplicar una KDF adecuada (p. ej., Argon2id o PBKDF2-HMAC-SHA256) usando la contraseña, el salt y parámetros de coste decididos.
- Extraer 256 bits de la salida como la clave para AES-GCM. Al verificar la contraseña, volver a derivar con el mismo salt y parámetros y comparar de forma segura.
Resumen
Las funciones de derivación de clave (KDF) convierten material secreto de distinta calidad (contraseñas, claves compartidas) en claves criptográficas seguras y adecuadas para su uso. Son esenciales para el almacenamiento seguro de contraseñas, la separación de claves y la interoperabilidad entre protocolos. Seleccionar el algoritmo y parámetros correctos (sal, iteraciones/memoria) y usar implementaciones probadas son pasos claves para mantener la seguridad.