Registros de algoritmos
Los registros de identificadores nombrados para hashes, AEAD, KEM, KDF y firmas, junto con la regla de agilidad que convierte la migración poscuántica en algo aditivo en lugar de disruptivo.
Cada decisión criptográfica en Label 309 se nombra mediante un identificador de cadena tomado
de un registro extensible: sha2-256, chacha20-poly1305-stream64k, EdDSA, etc. Un registro nunca lleva
un número de algoritmo en bruto ni una suposición implícita; declara qué primitiva utilizó, y el
verificador consulta ese identificador. Este es el mecanismo que sustenta el invariante de ser
ágil en algoritmos: los registros de algoritmos pueden crecer con el tiempo, y un verificador
que se topa con un identificador que no implementa rechaza el registro con un error tipado y
estable: nunca falla de forma abrupta y nunca acepta en silencio algo que no puede comprobar.
Esa única regla es lo que hace que la migración a algoritmos poscuánticos sea aditiva. Un identificador nuevo es una fila nueva en una tabla, no una versión nueva del formato de transmisión. Los registros antiguos siguen verificándose exactamente igual que antes, y los verificadores antiguos fallan de forma segura ante registros que nunca fueron diseñados para entender.
Dos reglas permanentes
En todos los registros de algoritmos rigen dos restricciones absolutas. Las implementaciones NO DEBEN inventar criptografía novedosa: cada primitiva remite a un estándar público con nombre. Y todo cifrado DEBE estar autenticado: solo se permiten construcciones AEAD, nunca un cifrador sin autenticar con una comprobación de integridad añadida (o ausente).
Hash
El hash del contenido es la afirmación principal de todo registro, por lo que el registro de algoritmos de hash es el que más peso soporta. Ambas funciones registradas producen un resumen de 32 bytes, y una implementación conforme DEBE admitir las dos.
| Identificador | Algoritmo | Resumen |
|---|---|---|
sha2-256 | SHA-256 (FIPS 180-4) | 32 B |
blake2b-256 | BLAKE2b-256 (RFC 7693) | 32 B |
Un productor PUEDE calcular el hash del mismo contenido con ambas funciones para una defensa en profundidad; un único hash es suficiente para un registro válido.
Compromiso Merkle
Para comprometerse con una lista ordenada de hojas bajo una única raíz en la cadena, Label 309
registra un identificador de compromiso Merkle. Es la cadena registrada por la IANA para el árbol
de Merkle binario SHA-256, que comparte la separación de dominios del prefijo de hoja (0x00) y el
prefijo de nodo interno (0x01) que evita las colisiones entre hojas y nodos.
| Identificador | Algoritmo | Raíz |
|---|---|---|
rfc9162-sha256 | Árbol de Merkle binario de RFC 9162, SHA-256 | 32 B |
Un árbol de una sola hoja se compromete con SHA-256(0x00 ‖ leaf), no con la hoja desnuda: por
eso una prueba de un solo archivo DEBE usar un identificador de hash simple, nunca un árbol de una
hoja.
AEAD
El registro de algoritmos AEAD rige qué formato de contenido protege una carga útil sellada
durante la transmisión: el campo enc.aead. Bajo enc.scheme: 1 queda registrado exactamente un
identificador, y es un formato segmentado en lugar de un cifrador de una sola pasada.
| Identificador | Algoritmo | Clave / Nonce / Nonce por segmento / Etiqueta | Estado |
|---|---|---|---|
chacha20-poly1305-stream64k | ChaCha20-Poly1305, STREAM segmentado de 64 KiB | 32 B / 24 B / 12 B / 16 B por segmento | Obligatorio: el formato de transmisión |
aes-256-gcm | AES-256-GCM | — | Reservado (perfil futuro) |
chacha20-poly1305-stream64k es ChaCha20-Poly1305
(RFC 8439) en la disposición STREAM segmentada de 64 KiB
de la especificación de age v1: el texto plano se
divide en segmentos de 65536 bytes, y cada segmento se sella bajo la clave de contenido con un nonce
por segmento de 12 bytes uint88_be(counter) ‖ final_flag (contador desde 0, final_flag 0x01 en
el último segmento) y un AAD por segmento vacío, produciendo una etiqueta de 16 bytes por segmento.
El enc.nonce de 24 bytes no es un nonce de segmento: es el salt único del sobre del HKDF de la
clave de contenido, que es lo que mantiene seguros los nonce de contador, ya que la clave de
contenido es de un solo uso, así que dos flujos nunca comparten un par (key, nonce) y los
productores sin estado nunca coordinan nonces entre sobres. La disposición segmentada permite a un
verificador autenticar y liberar una carga útil grande de forma incremental con memoria acotada, y la
marca final hace detectable el truncamiento. La grafía en transmisión es exactamente
chacha20-poly1305-stream64k; no DEBEN producirse grafías alternativas. La construcción completa
está en PoE sellada.
chacha20-poly1305-stream64k es el único identificador que puede aparecer como formato de contenido
en transmisión. Una construcción distinta, chacha20-poly1305
(RFC 8439, clave de 32 bytes / nonce de 12 bytes /
etiqueta de 16 bytes), se usa internamente para envolver una clave por destinatario dentro de la
construcción sellada: un nonce de 12 bytes todo a cero, la AAD fijada a la etiqueta info del KEM
elegido, que produce un wrap de 48 bytes (clave envuelta de 32 bytes + etiqueta de 16 bytes). Es
un bloque de construcción, no un identificador de transmisión, y un registro que lo nombre en
enc.aead DEBE rechazarse. aes-256-gcm está nombrado pero inactivo: queda reservado para un perfil
de cifrado futuro (enc.scheme: 2) y un verificador de la v1 rechaza cualquier registro que lo
seleccione.
KEM
El registro de algoritmos KEM cubre los mecanismos de encapsulamiento de claves que se usan para dirigir una carga útil sellada a destinatarios concretos. Label 309 registra un KEM clásico de curva y un híbrido poscuántico que se distribuye activo desde la primera versión.
| Identificador | Algoritmo | Clave pública / Secreta | Texto cifrado / Secreto compartido |
|---|---|---|---|
x25519 | X25519 ECDH (RFC 7748) | 32 B / 32 B | 32 B / 32 B |
mlkem768x25519 | Híbrido X-Wing (ML-KEM-768 + X25519) | 1216 B / 32 B | 1120 B / 32 B |
mlkem768x25519 es la construcción X-Wing de
draft-connolly-cfrg-xwing-kem-10:
combina ML-KEM-768 (FIPS 203) con X25519
(RFC 7748) de modo que un atacante deba romper ambos
para recuperar el secreto compartido. La clave pública es la clave de encapsulamiento de ML-KEM-768
concatenada con la clave pública X25519 (1184 B ‖ 32 B = 1216 B); el secreto es una semilla de
32 bytes a partir de la cual se deriva la clave completa. El texto cifrado de cada destinatario es el
texto cifrado de ML-KEM-768 concatenado con una clave pública X25519 efímera
(1088 B ‖ 32 B = 1120 B), y los dos secretos compartidos se combinan mediante el combinador
SHA3-256 de X-Wing (FIPS 202) para obtener el
secreto final de 32 bytes. Label 309 consume X-Wing como un KEM de caja negra (encapsular,
desencapsular, el secreto compartido de 32 bytes) y no depende de ninguna propiedad del hashing
interno del combinador. El identificador se escribe sin guiones internos para coincidir con la grafía
establecida de X-Wing.
El híbrido se selecciona por registro mediante la cabecera de cifrado, de forma independiente del AEAD de contenido. Como ya está registrado, la confidencialidad poscuántica es cuestión de elegir el identificador, no de esperar a una nueva versión del formato de transmisión.
Un registro nombra exactamente un enc.kem, y cada ranura usa la forma de ese KEM; una ranura con
la forma equivocada es ENC_SLOT_INVALID_SHAPE, un epk o un kem_ct reensamblado de longitud
incorrecta es KEM_EPK_LENGTH_MISMATCH / KEM_CT_LENGTH_MISMATCH, y un enc.kem no registrado es
UNSUPPORTED_KEM_ALG. El material de encapsulamiento también debe ser distinto dentro de un mismo
slots[]: todos los valores epk (en x25519) o todos los valores kem_ct reensamblados (en
mlkem768x25519) DEBEN diferir. Un duplicado dentro del registro se rechaza con
ENC_SLOTS_DUPLICATE_KEM_MATERIAL antes de ejecutar ninguna primitiva KEM o AEAD, porque un epk o
un kem_ct repetido rompe la unicidad de clave por ranura de la que depende el envoltorio con nonce
a cero. Un verificador también acota el uso de recursos del analizador antes de cualquier primitiva:
un sobre cuyo slots[] supere el límite de referencia de 1024 ranuras es ENC_SLOTS_TOO_MANY, y un
sobre enc decodificado que supere los 65 536 bytes es ENC_ENVELOPE_TOO_LARGE. Ambos límites
quedan muy por encima del techo de ~16 KiB de los metadatos de Cardano que acota cualquier registro
honesto; son constantes impuestas por el verificador y fijadas por despliegue —no campos de
transmisión— y los despliegues PUEDEN endurecerlas.
KDF
El registro de algoritmos KDF nombra las funciones de derivación de claves. hkdf-sha256 deriva
claves dentro de la construcción sellada; argon2id refuerza una frase de contraseña humana frente
a la fuerza bruta y lleva un mínimo obligatorio de parámetros.
| Identificador | Algoritmo | Parámetros |
|---|---|---|
hkdf-sha256 | HKDF-SHA-256 (RFC 5869) | salt (opcional), info (opcional), longitud de salida |
argon2id | Argon2id (RFC 9106) | memoria ≥ 65536 KiB, iteraciones ≥ 3, paralelismo ≥ 1 |
El mínimo de Argon2id es normativo: una carga útil protegida por frase de contraseña DEBE usar al
menos 64 MiB de memoria, al menos tres iteraciones y al menos un carril. Un productor PUEDE elegir
parámetros más fuertes, y estos viajan con el registro para que un verificador pueda reproducir la
derivación. Cuando la plataforma lo permita, los productores DEBERÍAN fijar el paralelismo p = 4
—el segundo perfil recomendado de
RFC 9106 §4—, mientras que un verificador PUEDE
aceptar cualquier p ≥ 1, sujeto a los topes del despliegue. Esos topes son un SHOULD de
implementación, no un MAY: un verificador DEBERÍA imponer cotas superiores frente a una denegación
de servicio del lado del verificador por parámetros desmesurados, informando
ENC_PASSPHRASE_PARAMS_EXCEED_POLICY. El tope depende del hardware y no es normativo, y NO DEBE
confundirse con el código del mínimo ENC_PASSPHRASE_ARGON2_PARAMS_TOO_LOW.
Solo argon2id es seleccionable en la transmisión: es el único identificador que un registro
puede nombrar en enc.passphrase.alg. hkdf-sha256 es un bloque de construcción interno, el
paso fijo de extracción y expansión que respalda la derivación de la semilla a la clave, la
derivación del KEK por ranura, la clave MAC del conjunto de ranuras, la clave MAC del compromiso de
frase de contraseña y la derivación de la clave de contenido, y no lleva ningún identificador de
transmisión. Un registro que nombre hkdf-sha256 en enc.passphrase.alg DEBE rechazarse: HKDF está
pensado para entradas de alta entropía, no para estirar una frase de contraseña de baja entropía.
Las etiquetas internas son constantes, nunca van en la transmisión
La construcción sellada toma su separación de dominios de un conjunto fijo de literales de etiqueta:
etiquetas info de HKDF y prefijos SHA-256 (prefijos de salt de KEK, prefijos de transcripción y el
prefijo de hashes del ítem). Cada uno es una constante de enc.scheme: 1, ASCII exacto sin
terminador ni prefijo de longitud; ninguno se serializa jamás, y ninguno es seleccionable a través de
ningún registro. Son once:
| Etiqueta | Función |
|---|---|
cardano-poe-kek-v1 | info de HKDF para el KEK por ranura en la ruta x25519 |
cardano-poe-kek-mlkem768x25519-v1 | info de HKDF para el KEK por ranura en la ruta mlkem768x25519 |
cardano-poe-x25519-kek-salt-v1 | Prefijo SHA-256 para el salt del HKDF del KEK de x25519 |
cardano-poe-xwing-kek-salt-v1 | Prefijo SHA-256 para el salt del HKDF del KEK de mlkem768x25519 |
cardano-poe-item-hashes-v1 | Prefijo SHA-256 para el resumen de hashes del ítem hashes_hash |
cardano-poe-slots-transcript-v1 | Prefijo SHA-256 para el hash de transcripción de ranuras slots_hash |
cardano-poe-slots-mac-v1 | info de HKDF para la clave MAC del conjunto de ranuras |
cardano-poe-passphrase-transcript-v1 | Prefijo SHA-256 para el hash de transcripción de frase de contraseña pw_hash |
cardano-poe-passphrase-mac-v1 | info de HKDF para la clave MAC del compromiso de frase de contraseña |
cardano-poe-payload-v1 | info de HKDF para la clave de contenido en la ruta de ranuras |
cardano-poe-payload-passphrase-v1 | info de HKDF para la clave de contenido en la ruta de frase de contraseña |
Ambos salts de KEK comparten una única forma de hash etiquetado,
SHA-256(label ‖ enc.nonce ‖ <material KEM de la ranura> ‖ pub_R), bajo su propia etiqueta por KEM.
Estas etiquetas son distintas de las cadenas info de derivación de la semilla en
Claves y del prefijo de dominio de firma de registros en Firmas:
el conjunto está libre de colisiones y de prefijos, así que ninguna etiqueta sellada por registro es
igual —ni es un prefijo de bytes— de una etiqueta de derivación de clave de largo plazo, y la
derivación de la clave de identidad y el envoltorio de claves por registro nunca colisionan. Un
verificador DEBE usar cada literal byte a byte; un solo byte divergente produce un slots_mac, un
compromiso o una etiqueta AEAD que el productor honesto no puede reproducir. La construcción a nivel
de bytes que consume cada etiqueta está en PoE sellada.
Firma
Label 309 registra un único algoritmo de firma. Las firmas de autoría siempre son opcionales, pero
cuando están presentes se transportan como COSE_Sign1
(RFC 9052) usando Ed25519.
| Identificador | alg COSE | Algoritmo | Envoltorio |
|---|---|---|---|
EdDSA | -8 | Ed25519 (RFC 8032) | COSE_Sign1 (RFC 9052) |
La verificación es estricta según RFC 8032 §5.1.7: las implementaciones DEBEN rechazar las codificaciones de firma no canónicas y los puntos de orden pequeño (sin la extensión de eliminación de cofactor). Esto coincide con los criterios de aceptación conservadores que se usan en las billeteras de Cardano, de modo que una firma que se verifica con una implementación conforme se verifica con todas ellas.
La compatibilidad con firmas es independiente de la afirmación de contenido. Un verificador que no implementa el algoritmo de firma de un registro marca ese campo de firma como no admitido y deja plenamente válidas las afirmaciones de tiempo y de contenido: un algoritmo de firma desconocido nunca invalida el registro en sí.
Identificadores reservados
Varios identificadores están nombrados pero todavía no activos. Marcan la ruta de migración acordada para que los perfiles futuros usen nombres estables y comprometidos de antemano en lugar de cadenas improvisadas. Un productor conforme NO DEBE emitirlos, y un verificador conforme DEBE rechazar cualquier registro que use uno de ellos, con el error tipado correspondiente.
| Identificador | Algoritmo | Función |
|---|---|---|
aes-256-gcm | AES-256-GCM (NIST SP 800-38D) | AEAD de contenido |
ml-kem-768 | ML-KEM-768 (FIPS 203), autónomo | KEM |
ml-dsa-65 | ML-DSA (FIPS 204) | Firma |
slh-dsa-sha2-128s | SLH-DSA (FIPS 205) | Firma |
ml-kem-768 es el KEM poscuántico puro, distinto del híbrido registrado mlkem768x25519; el
híbrido es lo que distribuye Label 309, bajo el principio de que debe conservarse una alternativa
clásica incluso después de añadir la mitad poscuántica.
Agilidad de algoritmos y migración
Añadir un algoritmo es una operación autónoma y aditiva: cite un estándar público para la primitiva, añada el identificador al registro de algoritmos adecuado, aporte una implementación verificada y bien revisada de él, y publique un fixture de conformidad multilenguaje para que las implementaciones independientes coincidan byte a byte. La versión del formato de transmisión no cambia, porque el esquema no cambia: solo crece el conjunto de cadenas reconocidas.
Las consecuencias se derivan directamente del diseño de los registros de algoritmos:
- Los registros antiguos siguen siendo verificables. Sus identificadores siguen en el registro de algoritmos, así que todo registro existente se verifica exactamente igual que el día en que se publicó.
- Los verificadores antiguos fallan de forma segura. Un verificador anterior a un identificador
nuevo rechaza los registros que lo usan con un error estable
UNSUPPORTED_*en lugar de adivinar: no hay ninguna vía hacia la aceptación silenciosa. - La compatibilidad poscuántica es aditiva. Como
mlkem768x25519ya está registrado, y como los nuevos KEM y firmas encajan en el mismo mecanismo, la transición poscuántica es un crecimiento del registro de algoritmos, no una migración disruptiva.
El aumento de la versión del formato de transmisión se reserva para cambios de esquema genuinamente disruptivos: un nuevo campo obligatorio, un campo eliminado, un tipo modificado. El crecimiento del registro de algoritmos nunca cumple ese criterio, que es precisamente lo que permite que el catálogo criptográfico evolucione sin dejar nunca varada una prueba ya publicada.
Contenido y hashing
Cómo Label 309 vincula un registro con su contenido: el mapa de hashes, a qué se compromete el resumen criptográfico y los compromisos Merkle para anclar muchos elementos bajo una sola raíz.
Claves
El modelo de claves de Label 309: una semilla de 32 bytes, tres pares de claves de algoritmos derivados de ella mediante HKDF-SHA-256 con separación de dominio, las claves de cifrado de clave por ranura que una PoE sellada deriva por encima, y cómo se codifican las claves públicas y los secretos de los destinatarios.