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.
El hash del contenido es la afirmación. Todo lo que un registro de Label 309 asevera sobre la existencia parte de un resumen criptográfico de los bytes del contenido, anclado en la cadena bajo la etiqueta de metadatos 309. Esta página define cómo se transporta ese resumen, a qué se compromete exactamente y cómo una sola raíz de 32 bytes puede representar un lote de elementos de tamaño arbitrario.
El mapa hashes
Cada elemento de un registro incluye un mapa hashes: un mapa CBOR que asocia un
identificador de algoritmo con un resumen sin procesar de 32 bytes.
hashes = {
"sha2-256": h'…32 bytes…', ; key = algorithm id, value = raw digest
}Las claves son identificadores de tipo cadena de texto tomados del registro de algoritmos de hash; los valores son cadenas de bytes sin procesar, nunca codificados en hexadecimal. El mapa DEBE contener al menos una entrada, y cada algoritmo de hash registrado produce exactamente 32 bytes:
| Identificador | Algoritmo | Referencia | Resumen |
|---|---|---|---|
sha2-256 | SHA-256 | FIPS 180-4 | 32 B |
blake2b-256 | BLAKE2b-256 | RFC 7693 | 32 B |
Ambos identificadores son de implementación obligatoria para los verificadores, de modo que un registro de un solo hash bajo cualquiera de ellos valida en cualquier entorno. Un verificador que encuentre un identificador no reconocido rechaza el registro con un código de error estable, en lugar de omitir la entrada en silencio. El registro de algoritmos completo, incluidas las ranuras reservadas para uso poscuántico, se encuentra en Registros de algoritmos.
Usar un mapa CBOR, en lugar de arreglos paralelos o una lista de subobjetos
{alg, digest}, tiene tres consecuencias que forman parte del contrato del
formato de transmisión. Los algoritmos duplicados son imposibles por
construcción, ya que las claves de un mapa CBOR son únicas. El orden canónico es
automático, porque el CBOR canónico ordena las claves según sus bytes
codificados, de modo que dos productores que expresan el mismo conjunto de hashes
emiten mapas idénticos byte a byte y cualquier firma a nivel de registro sobre
ellos es estable. Y la estructura no necesita validación entrada por entrada: un
validador estructural solo comprueba que cada clave esté registrada y que cada
valor tenga la longitud de resumen del algoritmo.
A qué se compromete el hash
El resumen se compromete con los bytes del contenido: la secuencia exacta de
bytes que el productor está sellando con una marca de tiempo. Cada entrada de un
mapa hashes debe ser el resumen de esa misma secuencia de bytes bajo el
algoritmo indicado; un registro cuyas entradas describen textos planos distintos
no es conforme. Cuando los bytes del contenido están disponibles para un
verificador, este DEBE recalcular cada resumen y rechazar el registro si
alguno no coincide.
Cuando un registro incluye un sobre de cifrado (enc), el hash se vincula al
texto plano, nunca al texto cifrado. Esto es deliberado: una Prueba de
Existencia (PoE) existe para que un autor pueda revelar más tarde el texto plano y
demostrar que existía en un momento determinado. Calcular el hash del texto
cifrado solo probaría que existió algún bloque cifrado, lo cual no dice nada sobre
el contenido subyacente. Así, un registro sellado sigue probando exactamente qué
texto plano recibió la marca de tiempo: el destinatario descifra, recalcula los
resúmenes del texto plano y los coteja con el compromiso registrado en la cadena.
Por consiguiente, un elemento que incluya enc debe llevar al menos una entrada
de hash del contenido; sin ella no habría ninguna afirmación sobre el texto plano
que recalcular.
Vinculación al texto plano, incluso cuando está sellado
El resumen en la cadena de un registro sellado es el resumen del texto en claro. El propio texto
cifrado reside en una URI ar:// o ipfs:// direccionada por contenido, de modo que los bytes
que devuelve una pasarela de almacenamiento son verificables frente a la dirección sin tener que
confiar en la pasarela; el destinatario descifra y recalcula el hash del texto plano para cerrar
el ciclo con la afirmación registrada en la cadena.
Uno o varios hashes
Un solo hash del contenido es plenamente conforme. Para todos los hashes de 256
bits del registro de algoritmos, los mejores ataques de segunda preimagen
conocidos se sitúan en 2^256, o muy cerca, en el plano clásico: un único hash
de 256 bits bien fundado ya cubre el modelo de amenaza realista durante toda la
vida de archivo de un registro, y los validadores estructurales no emiten ninguna
advertencia para registros con una sola entrada.
Un productor PUEDE añadir una segunda entrada de una familia de diseño
independiente como defensa en profundidad opcional, combinando sha2-256 (SHA-2:
construcción Merkle–Damgård) con blake2b-256 (BLAKE2: una construcción HAIFA
basada en una permutación derivada de ChaCha). Dado que las dos familias no
comparten ningún linaje estructural, un registro que lleve ambas solo se debilita
si las dos caen bajo criptoanálisis a la vez. El coste es un resumen adicional de
32 bytes más su identificador corto por elemento; la elección corresponde al
productor y nunca es obligatoria.
Compromisos Merkle por lotes
Un solo hash del contenido ancla un único contenido. Para anclar una colección de
tamaño arbitrario (un conjunto de 500 artefactos de integración continua, una
secuencia de eventos IoT, un lote de registros de auditoría), Label 309 define un
arreglo merkle[] de nivel superior. Cada entrada se compromete con una lista
ordenada de hojas de 32 bytes mediante una sola raíz de 32 bytes publicada en la
cadena; las propias hojas ordenadas residen fuera de la cadena.
merkle = [
{
"alg": "rfc9162-sha256",
"root": h'…32 bytes…', ; canonical root over the ordered leaves
"leaf_count": 4, ; binds the on-chain root to the leaf-list size
"uris": [ … ], ; OPTIONAL — where the off-chain leaves list lives
},
]El algoritmo de compromiso registrado es rfc9162-sha256: el Merkle Tree Hash de
RFC 9162 §2.1.1, con SHA-256 como hash subyacente. Es una construcción de
compromiso sobre listas, distinta del registro de algoritmos de hash del
contenido (una raíz Merkle se compromete con la estructura de una lista de hojas,
mientras que un resumen sha2-256 se compromete con bytes de texto plano), y por
eso reside en su propio arreglo en lugar de dentro de hashes. El leaf_count
registrado en la cadena vincula la raíz al tamaño de la lista que está fuera de la
cadena, lo que descarta una sustitución que reconstruya un árbol de tamaño
distinto que comparta la raíz para alguna posición de hoja.
Construcción del árbol
La construcción distingue las hojas de los nodos internos mediante un prefijo de
separación de dominio de un byte (0x00 para las hojas, 0x01 para los nodos
internos), de modo que un atacante no pueda fabricar un nodo interno que colisione
con una hoja. Para una lista ordenada L = (d_0, …, d_{n-1}) de valores de 32
bytes con n ≥ 1, el Merkle Tree Hash se define de forma recursiva:
MTH(L) = SHA-256(0x00 || d_0) when n == 1
MTH(L) = SHA-256(0x01 || MTH(L[0:k]) || MTH(L[k:n])) when n > 1
where k is the largest power of 2 strictly less than nUna consecuencia crucial: una sola hoja se calcula como SHA-256(0x00 || d_0),
no como la hoja desnuda. Por tanto, la raíz de un árbol de una sola hoja nunca
es igual a la propia hoja. Los productores que deseen sellar un solo contenido con
una marca de tiempo DEBEN usar directamente una entrada sha2-256 o
blake2b-256, no un árbol Merkle de una sola hoja. Un árbol vacío (n == 0) está
prohibido.
La construcción es sensible al orden (permutar las hojas produce una raíz distinta), por lo que los productores deben tratar la lista de hojas como una secuencia ordenada y preservar ese orden durante la publicación, el archivado y cualquier generación posterior de pruebas.
La lista de hojas fuera de la cadena
La raíz es inútil sin la lista de hojas, por lo que los productores conservan las
hojas ordenadas fuera de la cadena. El artefacto canónico es un documento
cardano-poe-merkle-leaves-v1, codificado como CBOR canónico (RFC 8949): una
raíz de 32 bytes, el arreglo ordenado de hojas de 32 bytes y el recuento de hojas.
leaves-list = {
"format": "cardano-poe-merkle-leaves-v1",
"tree_alg": tstr, ; registered list-commitment algorithm id
"root": bytes .size 32, ; raw 32 bytes, not hex
"leaves": [ + bytes .size 32 ], ; ordered raw 32-byte leaves
"leaf_count": 1..4294967295, ; 1 .. 2^32-1; MUST equal the length of `leaves`
? "leaf_alg": tstr, ; informative; no verification semantics
}Un verificador resuelve la lista que está fuera de la cadena, recalcula la raíz a
partir de sus leaves usando la construcción anterior y la coteja byte a byte con
el valor merkle[i].root registrado en la cadena; el leaf_count del archivo
debe coincidir tanto con el leaf_count registrado en la cadena como con
len(leaves). Este contenedor de CBOR canónico es la única forma normativa de
la lista de hojas: no existe ninguna proyección JSON ni serialización alternativa,
de modo que dos implementaciones que intercambien una lista de hojas intercambian
siempre documentos comparables byte a byte.
Pruebas de inclusión
El objetivo del agrupamiento en lotes es la divulgación selectiva: demostrar que
un elemento estaba en la lista comprometida sin volver a publicar, ni siquiera
revelar, el resto. Una prueba de inclusión para una hoja es la lista ordenada de
los hashes de los nodos hermanos a lo largo del camino desde esa hoja hasta la
raíz: una ruta de hermanos de orden O(log n). Un verificador pliega la hoja y
los hermanos hacia arriba en el árbol conforme al RFC 9162 y acepta la prueba si,
y solo si, la raíz reconstruida coincide byte a byte con la raíz publicada.
Dado que los árboles del RFC 9162 no se rellenan hasta una potencia de dos, una hoja en el borde derecho de un árbol no equilibrado puede tener una ruta más corta que una hoja en el lado completo. La comprobación definitiva es, por tanto, algorítmica (¿reproduce el pliegue la raíz?), nunca una comparación de la longitud de la prueba.
Por qué importa el agrupamiento en lotes
Una sola transacción y una sola raíz de 32 bytes pueden representar miles o millones de hojas.
Cualquiera que posea una prueba de orden O(log n) puede demostrar más tarde «este elemento
estaba en mi lista», mientras que cada hoja no divulgada permanece privada: la raíz no revela nada
sobre las hojas a las que se compromete.
El registro
El formato de transmisión de Label 309: dónde reside el registro bajo la etiqueta de metadatos 309, la forma de su mapa, las reglas de CBOR canónico, el fragmentado para el transporte y el esquema CDDL.
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.