ML-DSA frente a SLH-DSA es la elección principal entre las firmas poscuánticas que ha estandarizado el NIST, publicadas ambas el 13 de agosto de 2024. ML-DSA (FIPS 204, derivado de CRYSTALS-Dilithium) se basa en retículos estructurados; SLH-DSA (FIPS 205, derivado de SPHINCS+) solo depende de la seguridad de su función hash. Sus perfiles de tamaño y velocidad son tan distintos que la mayoría de los sistemas usarán ML-DSA, y SLH-DSA allí donde sus supuestos conservadores justifiquen el coste.
De un vistazo
| ML-DSA (FIPS 204) | SLH-DSA (FIPS 205) | |
|---|---|---|
| Supuesto | Problemas de retículos Module-LWE y Module-SIS | Solo propiedades de SHA-2 o SHAKE |
| Conjuntos de parámetros | ML-DSA-44, -65, -87 | 12 conjuntos: SHA2 o SHAKE × 128/192/256 × s (small, pequeño) o f (fast, rápido) |
| Categorías de seguridad | 2, 3, 5 | 1, 3, 5 |
| Clave pública | 1312 / 1952 / 2592 bytes | 32 / 48 / 64 bytes |
| Firma | 2420 / 3309 / 4627 bytes | de 7856 (128s) a 49.856 bytes (256f) |
| Clave privada | 2560–4896 bytes en forma expandida, o una semilla de 32 bytes | 64 / 96 / 128 bytes |
| Firmas por segundo (OpenSSL 3.6.5) | unas 3900 (44), 2400 (65), 2050 (87) | unas 7 (SHA2-128s), 144 (SHA2-128f), 3,5 (SHA2-192s) |
| Verificaciones por segundo | unas 20.800 (44), 13.600 (65), 8500 (87) | unas 7400 (SHA2-128s), 2400 (SHA2-128f) |
| Claves generadas por segundo | unas 22.000 (44) | unas 55 (128s), 3400 (128f) |
| Aleatoriedad de la firma | Hedged por defecto; se permite una variante determinista | Hedged por defecto; se permite una variante determinista |
| Cadena de contexto | Hasta 255 bytes | Hasta 255 bytes |
| Variante pre-hash | HashML-DSA (§5.4) | HashSLH-DSA (§10.2.2) |
| X.509 | RFC 9881 (id-ml-dsa-44 = 2.16.840.1.101.3.4.3.17 …) | RFC 9909 (id-slh-dsa-sha2-128s = …3.4.3.20 …) |
Las velocidades se midieron con openssl speed en un núcleo de un Apple M4 Max; el ML-DSA de OpenSSL está escrito en C portable, y las implementaciones optimizadas firman varias veces más rápido.
Supuestos de seguridad
ML-DSA es un esquema de retículos basado en Fiat–Shamir con abortos (Fiat–Shamir with aborts). Su seguridad descansa en el aprendizaje con errores sobre módulos (Module Learning With Errors) y en la solución entera corta sobre módulos (Module Short Integer Solution), problemas que se estudian desde hace unas dos décadas y que han resistido tanto los ataques clásicos como los cuánticos, pero cuyas estimaciones concretas de seguridad todavía cambian a medida que mejoran las técnicas de reducción de retículos. El NIST eligió conjuntos de parámetros con márgenes frente a esas estimaciones.
SLH-DSA construye sus firmas a partir de firmas basadas en hash de un solo uso y de pocos usos, organizadas en un hiperárbol. Mientras SHA-256 o SHAKE256 conserven su resistencia a preimágenes y las propiedades relacionadas, SLH-DSA sigue siendo seguro: no hay ninguna estructura algebraica que atacar. Eso lo convierte en la firma más conservadora que ha estandarizado el NIST y en la alternativa natural de respaldo si algún día se produce un avance decisivo contra los retículos. A diferencia de los esquemas basados en hash con estado LMS y XMSS, no necesita estado: cada clave puede firmar hasta 2⁶⁴ mensajes.
Tamaños y velocidad en la práctica
El script siguiente firma el mismo mensaje con cada algoritmo usando OpenSSL 3.6.5.
#!/bin/sh
dir=$(mktemp -d)
cd "$dir" || exit 1
printf 'firmware-2026.10.bin digest' > msg
for alg in ML-DSA-44 ML-DSA-65 SLH-DSA-SHA2-128s SLH-DSA-SHA2-128f ED25519; do
openssl genpkey -algorithm "$alg" -out key.pem 2>/dev/null
openssl pkeyutl -sign -rawin -inkey key.pem -in msg -out sig.bin 2>/dev/null
openssl pkey -in key.pem -pubout -outform DER -out pub.der 2>/dev/null
openssl pkey -in key.pem -pubout -out pub.pem 2>/dev/null
if openssl pkeyutl -verify -rawin -pubin -inkey pub.pem -in msg -sigfile sig.bin >/dev/null 2>&1; then ok=yes; else ok=no; fi
printf '%-18s public key (SPKI DER) %5s bytes, signature %6s bytes, verifies: %s\n' "$alg" \
"$(wc -c < pub.der | tr -d ' ')" "$(wc -c < sig.bin | tr -d ' ')" "$ok"
done
cd / && rm -rf "$dir"
ML-DSA-44 public key (SPKI DER) 1334 bytes, signature 2420 bytes, verifies: yes
ML-DSA-65 public key (SPKI DER) 1974 bytes, signature 3309 bytes, verifies: yes
SLH-DSA-SHA2-128s public key (SPKI DER) 50 bytes, signature 7856 bytes, verifies: yes
SLH-DSA-SHA2-128f public key (SPKI DER) 50 bytes, signature 17088 bytes, verifies: yes
ED25519 public key (SPKI DER) 44 bytes, signature 64 bytes, verifies: yes
Los perfiles son inversos. ML-DSA tiene claves públicas y firmas de kilobytes y firma miles de veces por segundo. SLH-DSA tiene claves públicas diminutas (tan pequeñas como las de Ed25519), pero firmas de 8 a 50 KB, y sus conjuntos pequeños s tardan unos 137 ms por firma en esta máquina (los conjuntos f aceptan el doble de tamaño de firma a cambio de firmar unas 20 veces más rápido). La verificación es rápida en ambos. Para una cadena de certificados o un handshake TLS, ML-DSA es viable y SLH-DSA no; para una imagen de firmware que se firma una vez por versión y se verifica en cada arranque, el coste de SLH-DSA es irrelevante y su diminuta clave pública cabe en la ROM de arranque.
Detalles operativos
- Firma hedged. Por defecto, ambos estándares mezclan aleatoriedad nueva con valores derivados de la clave y permiten una variante determinista para plataformas sin generador de números aleatorios; los verificadores no pueden distinguir una de otra.
- Contextos. Ambos vinculan a cada firma una cadena de contexto de hasta 255 bytes, que los protocolos deberían usar para separar finalidades.
- Variantes pura y pre-hash. HashML-DSA y HashSLH-DSA firman un resumen con el OID del hash incluido en la firma; son algoritmos distintos con OID distintos, y FIPS 204 recomienda usar cada clave solo para una de las dos variantes.
- Formatos de clave privada. Las claves ML-DSA se pueden guardar como la semilla de 32 bytes, que el RFC 9881 permite en sus codificaciones
seedoboth; los problemas de interoperabilidad surgen cuando una de las partes espera la clave expandida. - Hardware y validación FIPS. Desde 2024 han ido apareciendo módulos validados con ML-DSA y SLH-DSA; consulta el certificado del módulo para conocer los conjuntos de parámetros exactos.
Cuándo elegir cada uno
- PKI privada, mTLS interno, firma de código y de documentos: ML-DSA-65 (o 44).
- Firmware, arranque seguro, raíces de confianza de hardware: SLH-DSA-128s o 192s, o los esquemas con estado LMS y XMSS que CNSA 2.0 exige para este caso, si puedes gestionar el estado del firmante.
- Archivos a largo plazo y certificados raíz pensados para durar décadas: SLH-DSA, posiblemente junto a ML-DSA como firma dual.
- Firma de gran volumen (tokens, transacciones, registros): ML-DSA; SLH-DSA no da abasto.
- Protocolos con ancho de banda limitado: ninguno de los dos es pequeño; ML-DSA-44 es hoy la opción estandarizada más pequeña, y FN-DSA (borrador de FIPS 206) aspira a tamaños menores.
- TLS de la PKI web pública: hoy los navegadores no aceptan ninguno de los dos; consulta ML-DSA frente a ECDSA para ver el panorama de la transición.
Notas de migración
- Haz un inventario de los usos de la firma según su vida útil y su volumen: los artefactos de larga duración que se firman pocas veces son candidatos a SLH-DSA; todo lo demás, a ML-DSA.
- Elige versiones de bibliotecas que implementen los estándares definitivos: OpenSSL 3.5 o posterior (abril de 2025), Bouncy Castle para Java 1.79 o posterior (1.81 para la codificación estandarizada de la clave privada),
crypto/mldsade Go 1.27 para ML-DSA. Las salidas de Dilithium y SPHINCS+ anteriores al estándar no son compatibles. - Planifica el tamaño: aumenta los límites de los campos de certificados, tokens y firmas; los certificados ML-DSA-65 ocupan unos 5,5 KB (consulta la comparación complementaria) y las firmas SLH-DSA pueden superar los límites habituales de encabezados o de registros.
- Considera los esquemas híbridos durante la transición: los certificados compuestos de ML-DSA más ECDSA o EdDSA (un borrador del IETF) o las firmas duales permiten que los verificadores clásicos sigan funcionando.
- Fija la cadena de contexto y la variante (pura o pre-hash) en la especificación de tu protocolo para que todas las implementaciones coincidan.