Specification 0.14, approved: SPEC_VERSION 0.14, testdata at spec-v0.14, one drand scheme and tlock_steps.json

- SPEC_VERSION 0.14; testdata synced from datekeys-go at 39b2033
  (spec-v0.14), which adds vectors/tlock_steps.json;
  testing/mutation-texts.json regenerated with Go: only its spec field
  changes.
- Decision 8: validateProfile admits only bls-unchained-g1-rfc9380, with
  its public key in G2, in the order and with the texts of Go's
  validateDrand at c041fa3; any other drand scheme fails with
  ERR_UNKNOWN_PROFILE before the key and the chain hash.
- vectors.test.ts walks tlock_steps.json value by value with the code of
  ibe.ts, release.ts and bls12381.ts, with its negative checks, and the
  testdata guard requires it. ibe.ts exports h3Base, h3Try and hashToG1,
  which h3, the encryption and release.ts now use.
- The comment of h3 said the top bit is cleared: the first byte is
  shifted one bit to the right, as kyber does.
- README and CHANGELOG.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
main
dev 1 day ago
parent f7cdb5a8d4
commit 4e23f88c0a

@ -4,7 +4,12 @@ Cambios notables de la librería TypeScript y de la página. El proyecto usa ver
## 0.3.0 — sin publicar ## 0.3.0 — sin publicar
Nada todavía. ### La especificación 0.14, aprobada (06-10-2026)
- El autor aprobó el 6 de octubre de 2026 el borrador v0.14 con la recomendación de cada una de sus diez decisiones: `datekeys-go` lo cierra con el tag `spec-v0.14` (`39b2033`). `SPEC_VERSION` pasa a `0.14`, `testdata` se sincroniza con ese tag, y `testing/mutation-texts.json` se regenera con Go: solo cambia su campo `spec`. Ningún otro fichero de `testing/` generado con Go lleva ese campo ni depende de un perfil de otro scheme; los veredictos de `bls12381-vectors.json` salen idénticos con Go en `39b2033`, y solo se corrige su descripción.
- **Un solo scheme de drand (decisión 8).** `validateProfile`, y con ella `decodeProfile`, admite solo `bls-unchained-g1-rfc9380`, con la clave pública en G2, como `validateDrand` de Go desde `c041fa3`: un nombre que drand no conoce sigue siendo «is not a drand scheme», y cualquier otro scheme de drand, `pedersen-bls-unchained` y `bls-unchained-on-g1` incluidos, falla con `ERR_UNKNOWN_PROFILE` y el texto de Go, byte a byte, antes de mirar la clave y el `chain_hash`. Ningún perfil fijado ni ninguna cápsula válida cambian.
- **`tlock_steps.json`.** Un bloque nuevo de `vectors.test.ts` lee el fichero con el formato estricto de los demás y recorre, valor a valor y con el código de la librería, los pasos 10 y 11 de las cinco stanzas: M, H(M), la ecuación de pairing, las partes del stanza, e(firma, U), H2, sigma, H4, la file key, cada intento de H3 y r, y r·G2 = U; y las comprobaciones negativas: el DST de G2, la ronda sin SHA-256, el bit más alto puesto a cero, una firma de otra ronda y un V o un W editados. La guarda de `testdata` lo exige. `ibe.ts` exporta para ello `h3Base`, `h3Try` y `hashToG1`, que `h3`, el cifrado y `release.ts` usan ahora; `index.ts` no los exporta.
- El comentario de `h3` decía que se pone a cero el bit más alto de cada intento: el código desplaza el primer byte un bit a la derecha, como kyber, y así lo dice ahora.
## 0.2.0 — 6 de octubre de 2026 ## 0.2.0 — 6 de octubre de 2026

@ -21,7 +21,7 @@ Hay tres números de versión, cada uno con su significado, como en la referenci
| Versión | Dónde | Cambia cuando | | Versión | Dónde | Cambia cuando |
|---|---|---| |---|---|---|
| Formato | Dentro de los objetos: el formato de la cápsula, el `VERSION` del prelude de DKC1, 1, 2 o 3 al leer, que fija también la versión de schema de CONTROL_CBOR; y 1 en la trama DKK1 y en el schema de los demás objetos | Cambia el formato. Un lector rechaza una versión que no conoce (§22, §70) | | Formato | Dentro de los objetos: el formato de la cápsula, el `VERSION` del prelude de DKC1, 1, 2 o 3 al leer, que fija también la versión de schema de CONTROL_CBOR; y 1 en la trama DKK1 y en el schema de los demás objetos | Cambia el formato. Un lector rechaza una versión que no conoce (§22, §70) |
| Especificación | `SPEC_VERSION` de `src/lib/dkc/version.ts`, hoy `0.13`: la del tag `spec-v0.13` de `datekeys-go`, que aprobó el autor el 6 de octubre de 2026. `testdata` está en ese tag (`913dd60`), y todos sus ficheros dicen `0.13` | Cambia el texto normativo | | Especificación | `SPEC_VERSION` de `src/lib/dkc/version.ts`, hoy `0.14`: la del tag `spec-v0.14` de `datekeys-go`, que aprobó el autor el 6 de octubre de 2026. `testdata` está en ese tag (`39b2033`), y todos sus ficheros dicen `0.14` | Cambia el texto normativo |
| Librería | `VERSION` de `src/lib/dkc/version.ts`, igual al campo `version` de `package.json` | Cambia la API o el comportamiento. Versionado semántico, sin promesa de estabilidad antes de 1.0.0 | | Librería | `VERSION` de `src/lib/dkc/version.ts`, igual al campo `version` de `package.json` | Cambia la API o el comportamiento. Versionado semántico, sin promesa de estabilidad antes de 1.0.0 |
`version.test.ts` comprueba que `VERSION` coincide con `package.json` y con su lockfile, y que `SPEC_VERSION` es la versión que nombran los vectores y fixtures compartidos; `vectors.test.ts` exige esa versión a cada fichero. El pie de la página muestra las dos. `version.test.ts` comprueba que `VERSION` coincide con `package.json` y con su lockfile, y que `SPEC_VERSION` es la versión que nombran los vectores y fixtures compartidos; `vectors.test.ts` exige esa versión a cada fichero. El pie de la página muestra las dos.
@ -52,10 +52,10 @@ La inspección (pasos 1 a 8) no importa ninguna dependencia. Funciona en navegad
| `cbor.ts` | El codec propio de la referencia, con las mismas lecturas, las mismas comprobaciones en el mismo orden y los mismos textos de error: `Encoder` con error persistente; `Decoder`, cursor estricto (`map`/`key`/`endMap`, `array`, `uint`/`uint64`, `bstr`, `text`, `done`); `unmarshal` (decodifica, reencodifica y compara; `onReject` para borrar secretos); `peek`/`checkSchema` (capa 2 de §69.1: tipo y versión antes que nada) y `walk` (lector genérico acotado en profundidad y longitud) | `codec` | | `cbor.ts` | El codec propio de la referencia, con las mismas lecturas, las mismas comprobaciones en el mismo orden y los mismos textos de error: `Encoder` con error persistente; `Decoder`, cursor estricto (`map`/`key`/`endMap`, `array`, `uint`/`uint64`, `bstr`, `text`, `done`); `unmarshal` (decodifica, reencodifica y compara; `onReject` para borrar secretos); `peek`/`checkSchema` (capa 2 de §69.1: tipo y versión antes que nada) y `walk` (lector genérico acotado en profundidad y longitud) | `codec` |
| `schema.ts` | Lo que comparten los decodificadores de PUBLIC_HEADER, CONTROL_CBOR y el cuerpo de la `.dkk`: `key N: ` en los errores, claves obligatorias y arrays de extensiones | `capsule/framing.go`, `accesskey` | | `schema.ts` | Lo que comparten los decodificadores de PUBLIC_HEADER, CONTROL_CBOR y el cuerpo de la `.dkk`: `key N: ` en los errores, claves obligatorias y arrays de extensiones | `capsule/framing.go`, `accesskey` |
| `extension.ts` | Arrays de extensiones, leídos con su objeto (capa 3 de §69.1). Registros con ubicación opcional (`registeredIn`): una extensión conocida fuera de los objetos y arrays de su registro cuenta allí como desconocida (§54, §72), como `extension.Placement` en Go. Reglas del array: de 1 a 64, en orden estrictamente ascendente de los bytes UTF-8 de `extension_id` (nunca por unidades UTF-16), `extension_version` hasta 2³² − 1, `data` ausente o `bstr` no vacío, ningún id en los dos arrays; registros, críticas y no críticas (capa 4). `checkWrite` es la regla de los codificadores del §72 para las extensiones de la especificación (`NOTE_ID`, `CAPSULE_ID`): `datekeys.note` solo en el array no crítico de la cabecera y `datekeys.capsule` solo en el de una `.dkk`, con datos válidos; la aplican el escritor de cápsulas y el de `.dkk` | `extension` (`CheckWrite` y el registro `Standard`) | | `extension.ts` | Arrays de extensiones, leídos con su objeto (capa 3 de §69.1). Registros con ubicación opcional (`registeredIn`): una extensión conocida fuera de los objetos y arrays de su registro cuenta allí como desconocida (§54, §72), como `extension.Placement` en Go. Reglas del array: de 1 a 64, en orden estrictamente ascendente de los bytes UTF-8 de `extension_id` (nunca por unidades UTF-16), `extension_version` hasta 2³² − 1, `data` ausente o `bstr` no vacío, ningún id en los dos arrays; registros, críticas y no críticas (capa 4). `checkWrite` es la regla de los codificadores del §72 para las extensiones de la especificación (`NOTE_ID`, `CAPSULE_ID`): `datekeys.note` solo en el array no crítico de la cabecera y `datekeys.capsule` solo en el de una `.dkk`, con datos válidos; la aplican el escritor de cápsulas y el de `.dkk` | `extension` (`CheckWrite` y el registro `Standard`) |
| `profile.ts` | Provider Profile: CBOR exacto, `profile_hash`, reglas 1 a 4 de §12.1 en su orden (el límite de `period` de §74 en la capa del esquema; alfabetos, clave pública del grupo del scheme y fórmula de `chain_hash`), registro pinneado; Quicknet fijado por su CBOR y su hash | `profile` | | `profile.ts` | Provider Profile: CBOR exacto, `profile_hash`, reglas 1 a 4 de §12.1 en su orden (el límite de `period` de §74 en la capa del esquema; alfabetos, el único scheme que admite la v0.14, `bls-unchained-g1-rfc9380`, con los textos de `validateDrand` de Go, clave pública de G2 y fórmula de `chain_hash`), registro pinneado; Quicknet fijado por su CBOR y su hash | `profile` |
| `bls12381.ts` | Pertenencia de claves públicas BLS12-381 comprimidas (G1 y G2) al subgrupo, como `FromCompressed` de kilic | `kyber-bls12381` | | `bls12381.ts` | Pertenencia de claves públicas BLS12-381 comprimidas (G1 y G2) al subgrupo, como `FromCompressed` de kilic | `kyber-bls12381` |
| `ibe.ts` | IBE-CCA de tlock sobre G2 para Quicknet (§63 paso 11): `decryptOnG2` y `encryptOnG2RFC9380` (Qid = H(id) en G1 con el DST de RFC 9380, sigma aleatorio, U = r·G2), con la puerta de codificación canónica de `bls12381.ts` sobre la firma y U; H2 sobre GT serializado en el orden de kilic (nunca `Fp12.toBytes` de noble), H3 y H4; `roundIdentity`; el cuerpo `U ‖ V ‖ W` de 128 bytes del stanza. Errores `IbeError` con motivo (`length`, `encoding`, `identity`, `proof`) y texto fijos, sin ningún valor del cálculo; borra sigma y los hashes derivados. Sobre `@noble/curves` 2.4.0; lleva el aviso MIT de `tlock-js`, cuya estructura sigue. Lo usa la apertura (`open.ts`) | `encrypt/ibe` de drand/kyber (`DecryptCCAonG2`), `tlock.BytesToCiphertext` y `TimeUnlock` | | `ibe.ts` | IBE-CCA de tlock sobre G2 para Quicknet (§63 paso 11): `decryptOnG2` y `encryptOnG2RFC9380` (Qid = H(id) en G1 con el DST de RFC 9380, sigma aleatorio, U = r·G2), con la puerta de codificación canónica de `bls12381.ts` sobre la firma y U; H2 sobre GT serializado en el orden de kilic (nunca `Fp12.toBytes` de noble), H3 (`h3Base` y `h3Try`, que desplaza el primer byte de cada intento un bit a la derecha, como kyber) y H4; `roundIdentity` y `hashToG1`, el hash a G1 de RFC 9380 que usan también `release.ts` y el cifrado; el cuerpo `U ‖ V ‖ W` de 128 bytes del stanza. Errores `IbeError` con motivo (`length`, `encoding`, `identity`, `proof`) y texto fijos, sin ningún valor del cálculo; borra sigma y los hashes derivados. Sobre `@noble/curves` 2.4.0; lleva el aviso MIT de `tlock-js`, cuya estructura sigue. Lo usa la apertura (`open.ts`) | `encrypt/ibe` de drand/kyber (`DecryptCCAonG2`), `tlock.BytesToCiphertext` y `TimeUnlock` |
| `release.ts` | Verificación local del release (§17, §51, §63 paso 10), en el orden y con los textos de `provider.Verify`:<br>1. el rango de la ronda (`ERR_DATEKEY_INVALID`);<br>2. la ronda del release antes que la firma (`ERR_ROUND_MISMATCH`);<br>3. la longitud de la firma;<br>4. la clave pinneada (`ERR_UNKNOWN_PROFILE`);<br>5. la firma: codificación canónica de un punto de G1 que no sea el infinito, y firma BLS válida de la ronda sobre `@noble/curves` 2.4.0, con el DST de RFC 9380 para G1 (`ERR_RELEASE_INVALID`).<br>Nada de noble se copia a los errores. Solo verifica el scheme de Quicknet: un perfil de otro scheme falla con `ERR_UNKNOWN_PROFILE` tras las comprobaciones de ronda, donde la referencia sí lo verificaría (decisión 3 del plan de la fase 2). También define `ReleaseSource`, con su contrato de fuentes de red y de la corrección 6, y `suppliedRelease`, el release que entrega quien llama | `provider` (`Verify`, `ReleaseSource`) | | `release.ts` | Verificación local del release (§17, §51, §63 paso 10), en el orden y con los textos de `provider.Verify`:<br>1. el rango de la ronda (`ERR_DATEKEY_INVALID`);<br>2. la ronda del release antes que la firma (`ERR_ROUND_MISMATCH`);<br>3. la longitud de la firma;<br>4. la clave pinneada (`ERR_UNKNOWN_PROFILE`);<br>5. la firma: codificación canónica de un punto de G1 que no sea el infinito, y firma BLS válida de la ronda sobre `@noble/curves` 2.4.0, con el DST de RFC 9380 para G1 (`ERR_RELEASE_INVALID`).<br>Nada de noble se copia a los errores. Solo verifica el scheme de Quicknet, el único que admite un perfil desde la v0.14: un `Profile` de otro scheme, que `validateProfile` rechaza, falla aquí con `ERR_UNKNOWN_PROFILE` tras las comprobaciones de ronda (decisión 3 del plan de la fase 2). También define `ReleaseSource`, con su contrato de fuentes de red y de la corrección 6, y `suppliedRelease`, el release que entrega quien llama | `provider` (`Verify`, `ReleaseSource`) |
| `open.ts` | Los pasos 9 a 18 de §63 sobre los pasos 1 a 8 de `inspectWith`, con los checks, códigos y textos de `capsule.Open`:<br>- las credenciales y el release (paso 9), que cualquier fallo de la fuente convierte en `ERR_RELEASE_UNAVAILABLE` (corrección 6);<br>- la verificación del release (10);<br>- `OUTER_TIME_AGE` (11), la estructura frente a `access_policy` (12) e `INNER_ACCESS_AGE` (13);<br>- `CONTROL_CBOR` (14), `header_binding` (15), `I_PAYLOAD` (16), `PAYLOAD_AGE` (17) y el commit (18).<br>Lee los dos formatos (§22, §70). En el formato 2, `INNER_ACCESS_AGE` tiene exactamente 16 stanzas (paso 12); `CONTROL_CBOR` es de la versión de schema 2, con L y la regla de relleno (14); el paso 16 calcula P, y el 17 exige un texto en claro de exactamente P bytes con ceros tras el contenido, `ERR_INTEGRITY` en otro caso. Solo se entregan los L primeros bytes, nunca el relleno (§29.1, §56). `Opened` da el formato y, en los formatos 2 y 3, L, la regla y P.<br>En el formato 3, el paso 17 lo hace `open3.ts`, y los ficheros van a `sink`; sin él, `open` rechaza con un `TypeError` justo tras el paso 2, antes de pedir nada, como `ErrSinkRequired`. `Opened` da entonces el head, los veredictos del área de seguridad y el tamaño del área.<br>Abre los tres ficheros `age` con el `Decrypter` de `age-encryption` y con identidades propias que aplican las reglas de `agewrap`: la de tiempo, sobre `ibe.ts`; las de acceso y payload, sobre `x25519.ts`, stanza a stanza. Los fallos de `age` que no informa una identidad son `ERR_INTEGRITY` con el motivo fijo de su fase, cabecera o STREAM, sin copiar el texto de `age-encryption`.<br>La entrada puede ser un `Uint8Array` o un `Blob`, como un `File`. De un `Blob` solo se lee el prefijo de los pasos 1 a 8 (`prefix.ts`), el `capsule_digest` de la `.dkk` se calcula sobre su stream (`digest.ts`) y `PAYLOAD_AGE` se descifra en streaming.<br>El texto en claro va a memoria o a `output`, un `WritableStream`. Se escribe a medida que `age` autentica cada chunk, se cierra solo tras el paso 18 y se aborta ante cualquier fallo, en cualquier paso (§56). Un fallo del stream de salida es `ERR_INTEGRITY` con su texto, como en Go. El `WritableStream` de un fichero OPFS guarda lo escrito en un fichero de intercambio hasta el cierre: comprobado en el navegador, un fallo de STREAM deja intacto el contenido anterior | `capsule.Open`, `agewrap` (`TimeIdentity`, `AccessIdentity`, `PayloadIdentity`) | | `open.ts` | Los pasos 9 a 18 de §63 sobre los pasos 1 a 8 de `inspectWith`, con los checks, códigos y textos de `capsule.Open`:<br>- las credenciales y el release (paso 9), que cualquier fallo de la fuente convierte en `ERR_RELEASE_UNAVAILABLE` (corrección 6);<br>- la verificación del release (10);<br>- `OUTER_TIME_AGE` (11), la estructura frente a `access_policy` (12) e `INNER_ACCESS_AGE` (13);<br>- `CONTROL_CBOR` (14), `header_binding` (15), `I_PAYLOAD` (16), `PAYLOAD_AGE` (17) y el commit (18).<br>Lee los dos formatos (§22, §70). En el formato 2, `INNER_ACCESS_AGE` tiene exactamente 16 stanzas (paso 12); `CONTROL_CBOR` es de la versión de schema 2, con L y la regla de relleno (14); el paso 16 calcula P, y el 17 exige un texto en claro de exactamente P bytes con ceros tras el contenido, `ERR_INTEGRITY` en otro caso. Solo se entregan los L primeros bytes, nunca el relleno (§29.1, §56). `Opened` da el formato y, en los formatos 2 y 3, L, la regla y P.<br>En el formato 3, el paso 17 lo hace `open3.ts`, y los ficheros van a `sink`; sin él, `open` rechaza con un `TypeError` justo tras el paso 2, antes de pedir nada, como `ErrSinkRequired`. `Opened` da entonces el head, los veredictos del área de seguridad y el tamaño del área.<br>Abre los tres ficheros `age` con el `Decrypter` de `age-encryption` y con identidades propias que aplican las reglas de `agewrap`: la de tiempo, sobre `ibe.ts`; las de acceso y payload, sobre `x25519.ts`, stanza a stanza. Los fallos de `age` que no informa una identidad son `ERR_INTEGRITY` con el motivo fijo de su fase, cabecera o STREAM, sin copiar el texto de `age-encryption`.<br>La entrada puede ser un `Uint8Array` o un `Blob`, como un `File`. De un `Blob` solo se lee el prefijo de los pasos 1 a 8 (`prefix.ts`), el `capsule_digest` de la `.dkk` se calcula sobre su stream (`digest.ts`) y `PAYLOAD_AGE` se descifra en streaming.<br>El texto en claro va a memoria o a `output`, un `WritableStream`. Se escribe a medida que `age` autentica cada chunk, se cierra solo tras el paso 18 y se aborta ante cualquier fallo, en cualquier paso (§56). Un fallo del stream de salida es `ERR_INTEGRITY` con su texto, como en Go. El `WritableStream` de un fichero OPFS guarda lo escrito en un fichero de intercambio hasta el cierre: comprobado en el navegador, un fallo de STREAM deja intacto el contenido anterior | `capsule.Open`, `agewrap` (`TimeIdentity`, `AccessIdentity`, `PayloadIdentity`) |
| `encrypt.ts`, `writer.ts` | Los writers. `encryptFiles(files, opts)` escribe un `.dkc` de formato 3, como `capsule.EncryptFiles`: comprueba las rutas y los textos con las reglas del lector y con los textos de Go, pone los ficheros en el orden de los bytes de sus rutas, mide L con un head de sal y hashes a cero, lee cada fichero dos veces y falla si cambió entre las dos lecturas; el head, el control y el área de seguridad se decodifican antes de escribir. El área de seguridad mide 32 KiB sea lo que sea lo que guarde la cápsula (§62.1, regla 13), y va vacía o con la firma y el sello de los enganches de Go: `authorKey` firma con `alg` 1 (un `AuthorKey` de `authorkey.ts` o cualquier `AuthorSigner`), `cmsSigner` con `alg` 2, la firma con certificados, y `sealer` pide el sello de `seal_type` 2; `largeArea` deja ensanchar el área a 64 KiB solo si lo firmado no cabe en 32 KiB. Los enganches pueden ser asíncronos. Se comprueban como en `newSealer` de Go, en su orden y con sus textos: una sola firma, y con `cmsSigner` los sellos van dentro de cada firma. Se llaman cuando el control y el head ya son los finales y antes de escribir nada: la firma se compromete con ellos y el sello con la firma (§29.8, §29.11). El área se evalúa con el lector de la librería en el contexto de la cápsula antes de escribirla, como `security` de Go, y una firma que no daría F4 o F6, o un sello que no daría S4 o S5, la hace fallar con el texto de Go (reglas 17, 19 y 21). Lo que lanza `cmsSigner` o `sealer` llega con `capsule: signing: ` o `capsule: sealing: ` y su mensaje, y el error como `cause`. `publicNote` es la nota pública de la cabecera (§24.1), que se rechaza con los textos de `extension.CheckNote` tras `capsule: `, y nunca se corrige; las opciones se comprueban en el orden de `newSealer` de Go. Con un área de 512 bytes, que solo puede pedir un generador de vectores, reproduce byte a byte `PRELUDE`, PUBLIC_HEADER, CONTROL_CBOR y `BODY` de los cinco fixtures que escribió `EncryptFiles` en la v0.10. `fileSource` hace la fuente de un `File`.<br>El formato 2 solo lo escribe un generador de vectores (§62.1, regla 1). `encrypt(src, opts)` tiene la forma de `capsule.Encrypt`, pero sus opciones no pueden pedirlo, así que falla con el texto de Go. Lo que solo pide un generador, el formato 2 y otra área (`TestVectors`, como `EncryptOptions.TestVectors` de Go), solo lo pasan al núcleo los ayudantes de `testing/encrypt.ts` (`encryptVectors`, `encryptWith` y `encryptFilesWith`), que ninguna página puede cargar. Con ellos, las pruebas y los scripts escriben un `.dkc` de formato 2, sin head, área ni nota, y, si se pide, una `.dkk` portable (§61, §62, §62.1), en el orden y con los textos y códigos de `capsule.Encrypt`:<br>- el formato 2 siempre; L conocida de antemano (el tamaño de un `Uint8Array` o un `Blob`, o `length` con un `ReadableStream`), y una fuente que da más o menos bytes falla con los textos de Go;<br>- el relleno `reforzado` por defecto, o `bloque256`;<br>- de 1 a 16 credenciales, canónicas y no de orden bajo, un señuelo en cada hueco libre, cuyo escalar se borra al derivar su clave pública, y un orden uniforme de los 16 (`random.ts`);<br>- `SEALED_CONTROL_LEN` con la fórmula del §62.1, comprobada con el sellado real;<br>- las autocomprobaciones de la regla 11 y dos más: `OUTER_TIME_AGE` con las reglas del lector, y la cabecera de `PAYLOAD_AGE`, que `I_PAYLOAD` abre antes de escribir nada.<br>Nada se escribe hasta que todo lo anterior al contenido está comprobado. El contenido va en trozos de 64 KiB, seguido de los ceros del relleno, con presión inversa, hacia memoria (hasta `MAX_MEMORY_DKC`, 1 GiB) o hacia `output`, que se cierra solo con la cápsula completa y comprobada y se aborta ante cualquier fallo. Los errores de la fuente y de la salida se relanzan tal cual.<br>El núcleo, `writer.ts`, recibe la aleatoriedad de quien lo llama: `encrypt.ts` le da la de `crypto.getRandomValues`, y solo `testing/encrypt.ts` la fija, para reproducir los fixtures de Go | `capsule.Encrypt`, `accesskey.Encode` | | `encrypt.ts`, `writer.ts` | Los writers. `encryptFiles(files, opts)` escribe un `.dkc` de formato 3, como `capsule.EncryptFiles`: comprueba las rutas y los textos con las reglas del lector y con los textos de Go, pone los ficheros en el orden de los bytes de sus rutas, mide L con un head de sal y hashes a cero, lee cada fichero dos veces y falla si cambió entre las dos lecturas; el head, el control y el área de seguridad se decodifican antes de escribir. El área de seguridad mide 32 KiB sea lo que sea lo que guarde la cápsula (§62.1, regla 13), y va vacía o con la firma y el sello de los enganches de Go: `authorKey` firma con `alg` 1 (un `AuthorKey` de `authorkey.ts` o cualquier `AuthorSigner`), `cmsSigner` con `alg` 2, la firma con certificados, y `sealer` pide el sello de `seal_type` 2; `largeArea` deja ensanchar el área a 64 KiB solo si lo firmado no cabe en 32 KiB. Los enganches pueden ser asíncronos. Se comprueban como en `newSealer` de Go, en su orden y con sus textos: una sola firma, y con `cmsSigner` los sellos van dentro de cada firma. Se llaman cuando el control y el head ya son los finales y antes de escribir nada: la firma se compromete con ellos y el sello con la firma (§29.8, §29.11). El área se evalúa con el lector de la librería en el contexto de la cápsula antes de escribirla, como `security` de Go, y una firma que no daría F4 o F6, o un sello que no daría S4 o S5, la hace fallar con el texto de Go (reglas 17, 19 y 21). Lo que lanza `cmsSigner` o `sealer` llega con `capsule: signing: ` o `capsule: sealing: ` y su mensaje, y el error como `cause`. `publicNote` es la nota pública de la cabecera (§24.1), que se rechaza con los textos de `extension.CheckNote` tras `capsule: `, y nunca se corrige; las opciones se comprueban en el orden de `newSealer` de Go. Con un área de 512 bytes, que solo puede pedir un generador de vectores, reproduce byte a byte `PRELUDE`, PUBLIC_HEADER, CONTROL_CBOR y `BODY` de los cinco fixtures que escribió `EncryptFiles` en la v0.10. `fileSource` hace la fuente de un `File`.<br>El formato 2 solo lo escribe un generador de vectores (§62.1, regla 1). `encrypt(src, opts)` tiene la forma de `capsule.Encrypt`, pero sus opciones no pueden pedirlo, así que falla con el texto de Go. Lo que solo pide un generador, el formato 2 y otra área (`TestVectors`, como `EncryptOptions.TestVectors` de Go), solo lo pasan al núcleo los ayudantes de `testing/encrypt.ts` (`encryptVectors`, `encryptWith` y `encryptFilesWith`), que ninguna página puede cargar. Con ellos, las pruebas y los scripts escriben un `.dkc` de formato 2, sin head, área ni nota, y, si se pide, una `.dkk` portable (§61, §62, §62.1), en el orden y con los textos y códigos de `capsule.Encrypt`:<br>- el formato 2 siempre; L conocida de antemano (el tamaño de un `Uint8Array` o un `Blob`, o `length` con un `ReadableStream`), y una fuente que da más o menos bytes falla con los textos de Go;<br>- el relleno `reforzado` por defecto, o `bloque256`;<br>- de 1 a 16 credenciales, canónicas y no de orden bajo, un señuelo en cada hueco libre, cuyo escalar se borra al derivar su clave pública, y un orden uniforme de los 16 (`random.ts`);<br>- `SEALED_CONTROL_LEN` con la fórmula del §62.1, comprobada con el sellado real;<br>- las autocomprobaciones de la regla 11 y dos más: `OUTER_TIME_AGE` con las reglas del lector, y la cabecera de `PAYLOAD_AGE`, que `I_PAYLOAD` abre antes de escribir nada.<br>Nada se escribe hasta que todo lo anterior al contenido está comprobado. El contenido va en trozos de 64 KiB, seguido de los ceros del relleno, con presión inversa, hacia memoria (hasta `MAX_MEMORY_DKC`, 1 GiB) o hacia `output`, que se cierra solo con la cápsula completa y comprobada y se aborta ante cualquier fallo. Los errores de la fuente y de la salida se relanzan tal cual.<br>El núcleo, `writer.ts`, recibe la aleatoriedad de quien lo llama: `encrypt.ts` le da la de `crypto.getRandomValues`, y solo `testing/encrypt.ts` la fija, para reproducir los fixtures de Go | `capsule.Encrypt`, `accesskey.Encode` |
| `tlock.ts` | `timeRecipient`, el `Recipient` de `age-encryption` para `OUTER_TIME_AGE` (§32, §35), como `agewrap.TimeRecipient`: cifra la file key con `ibe.ts` para una ronda de un perfil pinneado y escribe el stanza `tlock <ronda> <chain hash>` de tlock. Comprueba el perfil y luego el rango de la ronda, con los textos de `NewTimeRecipient`. `age-encryption` no tiene etiquetas, así que quien escriba `OUTER_TIME_AGE` (fase 3) lo añade como único recipient | `agewrap.TimeRecipient` | | `tlock.ts` | `timeRecipient`, el `Recipient` de `age-encryption` para `OUTER_TIME_AGE` (§32, §35), como `agewrap.TimeRecipient`: cifra la file key con `ibe.ts` para una ronda de un perfil pinneado y escribe el stanza `tlock <ronda> <chain hash>` de tlock. Comprueba el perfil y luego el rango de la ronda, con los textos de `NewTimeRecipient`. `age-encryption` no tiene etiquetas, así que quien escriba `OUTER_TIME_AGE` (fase 3) lo añade como único recipient | `agewrap.TimeRecipient` |
@ -292,6 +292,7 @@ Umbrales de cobertura (`vitest.config.ts`), al 100 % en líneas, ramas, funcione
- `testdata/vectors/cbor.json`: cada vector genérico (`accept` y `reject`) pasa por `walk` con los `max_depth` y `max_len` del fichero; los enteros aceptados comparan su `value` (número o, por encima de 2⁵³ − 1, `bigint`), y los rechazados «above max_len» o «above max_depth» se aceptan sin ese límite. Cada vector de `schemas` pasa por el decodificador de su esquema (`decodeProfile`, `decodeHeader`, `decodeControl` con el formato del vector, 1 si no lo trae, también el 3, `decodeAccessKeyBody`) con el código exacto, y un objeto aceptado se reescribe a los mismos bytes. - `testdata/vectors/cbor.json`: cada vector genérico (`accept` y `reject`) pasa por `walk` con los `max_depth` y `max_len` del fichero; los enteros aceptados comparan su `value` (número o, por encima de 2⁵³ − 1, `bigint`), y los rechazados «above max_len» o «above max_depth» se aceptan sin ese límite. Cada vector de `schemas` pasa por el decodificador de su esquema (`decodeProfile`, `decodeHeader`, `decodeControl` con el formato del vector, 1 si no lo trae, también el 3, `decodeAccessKeyBody`) con el código exacto, y un objeto aceptado se reescribe a los mismos bytes.
- `testdata/vectors/padding.json`: P con las dos reglas y la longitud de `PAYLOAD_AGE` de cada L, incluidas las fronteras en que fallan las operaciones de 32 bits y un logaritmo en coma flotante, y las longitudes por encima de L_MAX, que se rechazan. `padding.test.ts` contrasta además `paddedLength` con el §29.1 escrito en `BigInt` sobre 20 000 longitudes de todo el rango. - `testdata/vectors/padding.json`: P con las dos reglas y la longitud de `PAYLOAD_AGE` de cada L, incluidas las fronteras en que fallan las operaciones de 32 bits y un logaritmo en coma flotante, y las longitudes por encima de L_MAX, que se rechazan. `padding.test.ts` contrasta además `paddedLength` con el §29.1 escrito en `BigInt` sobre 20 000 longitudes de todo el rango.
- `testdata/vectors/tlock_ibe.json`: el vector de H2 del IBE de tlock (§63 paso 11). Hasta que llegue `ibe.ts` (fase 2), el test lo recalcula con `@noble/curves` 2.4.0: los puntos son canónicos para `bls12381.ts`, el pairing serializado en el orden de kilic es el GT del vector y su H2 coincide; el orden propio de noble (`Fp12.toBytes`) da otro hash. - `testdata/vectors/tlock_ibe.json`: el vector de H2 del IBE de tlock (§63 paso 11). Hasta que llegue `ibe.ts` (fase 2), el test lo recalcula con `@noble/curves` 2.4.0: los puntos son canónicos para `bls12381.ts`, el pairing serializado en el orden de kilic es el GT del vector y su H2 coincide; el orden propio de noble (`Fp12.toBytes`) da otro hash.
- `testdata/vectors/tlock_steps.json`: los pasos 10 y 11 de §63 para Quicknet, valor a valor (v0.14), con el código de la librería: M con `roundIdentity`, H(M) con `hashToG1`, el release con `verifyRelease` y la ecuación de pairing; las tres partes del stanza con `ciphertextFromBody`, e(firma, U) con `gtBytes`, H2, sigma, H4 y la file key; la base de H3 con `h3Base`, cada intento con `h3Try` y su digest, el desplazamiento del primer byte y su aceptación, r con `h3`, y r·G2 = U con `proofHolds`; y `decryptOnG2` sobre el cuerpo entero. También las lecturas erróneas que descarta el generador: el DST de G2 o la ronda sin SHA-256 no verifican, y poner a cero el bit más alto en vez de desplazar el byte da otra r, que U no prueba; una firma de otra ronda y un V o un W editados no descifran.
- `testdata/vectors/mutations.json`: se leen los 218 casos enteros (ediciones sobre un fixture o hex congelado, release, reloj, registro, extensiones, `.dkk`, identidades y, en los once que abren, sus veredictos). Los 218 pasan por `open` con su release, su reloj, su registro, sus extensiones, su `.dkk`, sus identidades y un `MemorySink`, y dan el mismo código en el mismo paso que Go y el mismo texto que `capsule.Open` (`testing/mutation-texts.json`); los cuatro de seguridad del formato 3 abren con los veredictos X, F1, F2 y S1 del registro, y siete de la lista de la v0.11 con los suyos. También pasan como `Blob` con un stream de salida, que termina abortado en los 207 que fallan, y un sumidero que nunca se publica. Son los 178 del §64: las 33 mutaciones de las dos primeras listas en cada formato, las 23 de la lista del formato 2, las 48 de la del formato 3 y las 8 de la lista de la v0.11; y 40 más. Ninguno de los que fallan sin red pide un release. Los 57 de los pasos 1 a 8 pasan además por `inspect`, y un test fija los recuentos y el orden. Las `.dkk` ofrecidas se decodifican. - `testdata/vectors/mutations.json`: se leen los 218 casos enteros (ediciones sobre un fixture o hex congelado, release, reloj, registro, extensiones, `.dkk`, identidades y, en los once que abren, sus veredictos). Los 218 pasan por `open` con su release, su reloj, su registro, sus extensiones, su `.dkk`, sus identidades y un `MemorySink`, y dan el mismo código en el mismo paso que Go y el mismo texto que `capsule.Open` (`testing/mutation-texts.json`); los cuatro de seguridad del formato 3 abren con los veredictos X, F1, F2 y S1 del registro, y siete de la lista de la v0.11 con los suyos. También pasan como `Blob` con un stream de salida, que termina abortado en los 207 que fallan, y un sumidero que nunca se publica. Son los 178 del §64: las 33 mutaciones de las dos primeras listas en cada formato, las 23 de la lista del formato 2, las 48 de la del formato 3 y las 8 de la lista de la v0.11; y 40 más. Ninguno de los que fallan sin red pide un release. Los 57 de los pasos 1 a 8 pasan además por `inspect`, y un test fija los recuentos y el orden. Las `.dkk` ofrecidas se decodifican.
- `testdata/vectors/inspect_differential.json`: las 5 110 mutaciones de los catorce fixtures de base dan el mismo veredicto, código y paso que Go; los `bases` se comprueban por su SHA-256. - `testdata/vectors/inspect_differential.json`: las 5 110 mutaciones de los catorce fixtures de base dan el mismo veredicto, código y paso que Go; los `bases` se comprueban por su SHA-256.
- `testdata/vectors/paths.json` y `path_fold.json`, con las tablas cuyo digest nombran: cada ruta pasa por las reglas de una entrada con el texto exacto, cada árbol por la decodificación de un head de ficheros de 0 bytes, y cada segmento da su NFD y su clave de R7. - `testdata/vectors/paths.json` y `path_fold.json`, con las tablas cuyo digest nombran: cada ruta pasa por las reglas de una entrada con el texto exacto, cada árbol por la decodificación de un head de ficheros de 0 bytes, y cada segmento da su NFD y su clave de R7.
@ -461,7 +462,7 @@ Comprueba que los ficheros coinciden con `SOURCE.json`, sin faltantes ni sobrant
`.gitattributes` marca `testdata/**` como binario para que git no altere ningún byte. `.gitattributes` marca `testdata/**` como binario para que git no altere ningún byte.
Copia actual: la de `testdata/SOURCE.json` (el tag `spec-v0.13` de `datekeys-go`, `913dd60`), que se sincroniza con `node scripts/sync-testdata.mjs sync --commit spec-v0.13`. Copia actual: la de `testdata/SOURCE.json` (el tag `spec-v0.14` de `datekeys-go`, `39b2033`), que se sincroniza con `node scripts/sync-testdata.mjs sync --commit spec-v0.14`.
## Licencia ## Licencia

@ -2,11 +2,11 @@
// Prints the Go reference verdict for every encoding in // Prints the Go reference verdict for every encoding in
// src/lib/dkc/testing/bls12381-vectors.json, as a JSON object from label to // src/lib/dkc/testing/bls12381-vectors.json, as a JSON object from label to
// "point", "identity" or "invalid". The decoding is the one profile.Validate // "point", "identity" or "invalid". The decoding is the KeyGroup of the drand
// uses: the KeyGroup of the drand crypto scheme (G1 for the unchained scheme, // crypto scheme (G1 for the unchained scheme, G2 for bls-unchained-g1-rfc9380,
// G2 for bls-unchained-g1-rfc9380, Quicknet), whose UnmarshalBinary is // Quicknet, the one profile.Validate admits since spec v0.14), whose
// kyber-bls12381 over kilic/bls12-381 FromCompressed, and Equal(Null()) for the // UnmarshalBinary is kyber-bls12381 over kilic/bls12-381 FromCompressed, and
// identity. Run it from a scratch module that requires the reference // Equal(Null()) for the identity. Run it from a scratch module that requires the reference
// implementation (replace g.activething.com/go/DateKeys => ../datekeys-go and // implementation (replace g.activething.com/go/DateKeys => ../datekeys-go and
// GOFLAGS=-mod=mod), passing the path of the vectors file: // GOFLAGS=-mod=mod), passing the path of the vectors file:
// //

@ -142,19 +142,34 @@ export function h4(sigma: Uint8Array, n: number): Uint8Array {
return hashTo(n, H4_TAG, sigma); return hashTo(n, H4_TAG, sigma);
} }
/** The base of H3: SHA-256("IBE-H3" || sigma || msg). The caller wipes it. */
export function h3Base(sigma: Uint8Array, msg: Uint8Array): Uint8Array {
return hashTo(32, H3_TAG, sigma, msg);
}
/**
* Try i of H3, i in 1..65535: d = SHA-256(uint16le(i) || base) with its
* first byte shifted one bit to the right, as kyber does (spec §63, "H3 y
* H4"). Shifting moves every bit of that byte; clearing only its top bit
* would give another r. Read big-endian, d is r when it is below the order
* of the scalar field. The caller wipes it.
*/
export function h3Try(base: Uint8Array, i: number): Uint8Array {
const d = hashTo(32, new Uint8Array([i & 0xff, i >> 8]), base);
d[0] = d[0]! >> 1;
return d;
}
/** /**
* H3, the scalar r of sigma and the message: with base = SHA-256("IBE-H3" || * H3, the scalar r of sigma and the message: the first try of h3Try over
* sigma || msg), the first d = SHA-256(uint16le(i) || base), i = 1, 2, ..., * h3Base, i = 1, 2, ..., that is below the order of the scalar field.
* whose top bit cleared makes it a big-endian integer below the order of * `iterations` bounds i, for tests; after it, the proof fails, as in kyber.
* the scalar field. `iterations` bounds i, for tests; after it, the proof
* fails, as in kyber.
*/ */
export function h3(sigma: Uint8Array, msg: Uint8Array, iterations = H3_ITERATIONS): bigint { export function h3(sigma: Uint8Array, msg: Uint8Array, iterations = H3_ITERATIONS): bigint {
const base = hashTo(32, H3_TAG, sigma, msg); const base = h3Base(sigma, msg);
try { try {
for (let i = 1; i <= iterations; i++) { for (let i = 1; i <= iterations; i++) {
const d = hashTo(32, new Uint8Array([i & 0xff, i >> 8]), base); const d = h3Try(base, i);
d[0] = d[0]! >> 1;
const r = bytesToNumberBE(d); const r = bytesToNumberBE(d);
d.fill(0); d.fill(0);
if (r < Fr.ORDER) return r; if (r < Fr.ORDER) return r;
@ -174,6 +189,17 @@ export function proofHolds(r: bigint, u: InstanceType<typeof G2.Point>): boolean
return r !== 0n && G2.Point.BASE.multiply(r).equals(u); return r !== 0n && G2.Point.BASE.multiply(r).equals(u);
} }
/**
* The hash of a message to G1 of RFC 9380, with the suite
* BLS12381G1_XMD:SHA-256_SSWU_RO_ and the DST of drand's
* bls-unchained-g1-rfc9380 (spec §63, "Mensaje de ronda y hash a G1"): of
* roundIdentity(round), the point that the release of the round signs and
* the identity of the round in tlock.
*/
export function hashToG1(msg: Uint8Array): InstanceType<typeof G1.Point> {
return shortSignatures.hash(msg, DST_G1);
}
/** The identity of a round for tlock: SHA-256 of its 8 big-endian bytes (drand DigestBeacon). */ /** The identity of a round for tlock: SHA-256 of its 8 big-endian bytes (drand DigestBeacon). */
export function roundIdentity(round: number): Uint8Array { export function roundIdentity(round: number): Uint8Array {
if (!Number.isSafeInteger(round) || round < 0) throw new RangeError(`ibe: round ${round} is not a safe non-negative integer`); if (!Number.isSafeInteger(round) || round < 0) throw new RangeError(`ibe: round ${round} is not a safe non-negative integer`);
@ -294,7 +320,7 @@ export function encryptOnG2WithSigma(publicKey: Uint8Array, id: Uint8Array, msg:
gate('G2', publicKey, 'the public key'); gate('G2', publicKey, 'the public key');
const key = G2.Point.fromBytes(publicKey); const key = G2.Point.fromBytes(publicKey);
key.assertValidity(); key.assertValidity();
const gid = pairing(shortSignatures.hash(id, DST_G1), key); const gid = pairing(hashToG1(id), key);
const r = h3(sigma, msg); const r = h3(sigma, msg);
// r = 0 would make U the point at infinity; H3 gives it with probability // r = 0 would make U the point at infinity; H3 gives it with probability
// 2^-255, and kyber does not check it either. // 2^-255, and kyber does not check it either.

@ -179,19 +179,31 @@ describe('decodeProfile', () => {
{ 6: b('c0' + zeros(95)) }, { 6: b('c0' + zeros(95)) },
{ 6: b(G1_GENERATOR) }, { 6: b(G1_GENERATOR) },
{ 9: t('pedersen-bls-unchained') }, { 9: t('pedersen-bls-unchained') },
{ 9: t('bls-unchained-on-g1') },
]; ];
for (const over of cases) await expectCodeAsync(() => decodeProfile(profile(over)), UP); for (const over of cases) await expectCodeAsync(() => decodeProfile(profile(over)), UP);
}); });
it('admits only the scheme bls-unchained-g1-rfc9380, with the texts of Go (spec v0.14 §12.1)', async () => {
// Go's validateDrand: a name drand does not know, then any drand scheme
// but bls-unchained-g1-rfc9380, both before the key and the chain hash.
const id = 'profile datekeys:quicknet:v1: ';
for (const scheme of ['pedersen-bls-chained', 'pedersen-bls-unchained', 'bls-unchained-on-g1', 'bls-bn254-unchained-on-g1']) {
const text = `${id}scheme "${scheme}" is not bls-unchained-g1-rfc9380, the only scheme of V1: ERR_UNKNOWN_PROFILE`;
await expectCodeAsync(() => decodeProfile(profile({ 9: t(scheme) })), UP, new RegExp(`^${text}$`));
// The scheme is refused before a key of another group and before a
// chain hash that does not match.
await expectCodeAsync(() => decodeProfile(profile({ 9: t(scheme), 6: b(G1_GENERATOR), 5: bn(32) })), UP, new RegExp(`^${text}$`));
}
await expectCodeAsync(() => decodeProfile(profile({ 9: t('nope'), 5: bn(32) })), UP, /^profile datekeys:quicknet:v1: "nope" is not a drand scheme: ERR_UNKNOWN_PROFILE$/);
await expectCodeAsync(() => decodeProfile(profile({ 6: b(G1_GENERATOR), 5: bn(32) })), UP, /^profile datekeys:quicknet:v1: public key is not the canonical encoding of a point of the key group of bls-unchained-g1-rfc9380: ERR_UNKNOWN_PROFILE$/);
});
it('rejects parameters that do not hash to the chain hash', async () => { it('rejects parameters that do not hash to the chain hash', async () => {
await expectCodeAsync(() => decodeProfile(profile({ 5: bn(32) })), 'ERR_PROFILE_MISMATCH', /parameters hash to chain 52db9ba7/); await expectCodeAsync(() => decodeProfile(profile({ 5: bn(32) })), 'ERR_PROFILE_MISMATCH', /parameters hash to chain 52db9ba7/);
await expectCodeAsync(() => decodeProfile(profile({ 7: u(4) })), 'ERR_PROFILE_MISMATCH'); await expectCodeAsync(() => decodeProfile(profile({ 7: u(4) })), 'ERR_PROFILE_MISMATCH');
await expectCodeAsync(() => decodeProfile(profile({ 4: t('default') })), 'ERR_PROFILE_MISMATCH'); await expectCodeAsync(() => decodeProfile(profile({ 4: t('default') })), 'ERR_PROFILE_MISMATCH');
await expectCodeAsync(() => decodeProfile(profile({ 6: b(G2_GENERATOR) })), 'ERR_PROFILE_MISMATCH'); await expectCodeAsync(() => decodeProfile(profile({ 6: b(G2_GENERATOR) })), 'ERR_PROFILE_MISMATCH');
await expectCodeAsync(() => decodeProfile(profile({ 6: b(DRAND_DEFAULT_KEY), 9: t('pedersen-bls-unchained') })), 'ERR_PROFILE_MISMATCH');
// The chain hash does not cover the scheme: another scheme with a key of
// the same group validates, as in the reference.
expect((await decodeProfile(profile({ 9: t('bls-unchained-on-g1') }))).scheme).toBe('bls-unchained-on-g1');
}); });
it('computes chain_hash with the formula of spec §12.1 rule 3', async () => { it('computes chain_hash with the formula of spec §12.1 rule 3', async () => {
@ -212,10 +224,10 @@ describe('decodeProfile', () => {
await expectCodeAsync(() => validateProfile({ ...QN, genesisSeed: new Uint8Array(33) }), NC, /chain hash and genesis seed must be 32 bytes/); await expectCodeAsync(() => validateProfile({ ...QN, genesisSeed: new Uint8Array(33) }), NC, /chain hash and genesis seed must be 32 bytes/);
}); });
it('accepts other drand parameters that hash to their own chain hash', async () => { it('refuses other drand networks whose parameters hash to their own chain hash', async () => {
// The drand default network: pedersen-bls-chained is refused, but the // The drand default network, with the unchained scheme of its G1 key:
// same parameters with the unchained G1-key scheme validate, since the // its parameters hash to its chain hash, but since spec v0.14 the scheme
// chain hash does not cover the scheme. // is refused before the key and the chain hash are looked at.
const seed = '176f93498eac9ca337150b46d21dd58673ea4e3581185f869672e59fa4cb390a'; const seed = '176f93498eac9ca337150b46d21dd58673ea4e3581185f869672e59fa4cb390a';
const p: Profile = { const p: Profile = {
id: 'drand:default:v1', id: 'drand:default:v1',
@ -228,10 +240,12 @@ describe('decodeProfile', () => {
scheme: 'pedersen-bls-unchained', scheme: 'pedersen-bls-unchained',
genesisSeed: h(seed), genesisSeed: h(seed),
}; };
await validateProfile(p); expect(hx(await chainInfoHash(p))).toBe(hx(p.chainHash));
const back = await decodeProfile(canonicalCBOR(p)); for (const scheme of ['pedersen-bls-unchained', 'pedersen-bls-chained']) {
expect(back).toEqual(p); const text = `profile drand:default:v1: scheme "${scheme}" is not bls-unchained-g1-rfc9380, the only scheme of V1: ERR_UNKNOWN_PROFILE`;
await expectCodeAsync(() => validateProfile({ ...p, scheme: 'pedersen-bls-chained' }), UP, /not supported by tlock/); await expectCodeAsync(() => validateProfile({ ...p, scheme }), UP, new RegExp(`^${text}$`));
await expectCodeAsync(() => decodeProfile(canonicalCBOR({ ...p, scheme })), UP, new RegExp(`^${text}$`));
}
}); });
it('validates profiles built in memory with the code their encoding would get (spec §12.1)', async () => { it('validates profiles built in memory with the code their encoding would get (spec §12.1)', async () => {

@ -2,7 +2,7 @@
// their Deterministic CBOR, profile_hash, validation and the locally pinned // their Deterministic CBOR, profile_hash, validation and the locally pinned
// registry that forms the root of trust. // registry that forms the root of trust.
import { checkCompressedPoint, type Group } from './bls12381.ts'; import { checkCompressedPoint } from './bls12381.ts';
import { concatBytes, copyBytes, equalBytes, goQuote, fromHex, sha256, toHex, utf8Bytes, utf8Length } from './bytes.ts'; import { concatBytes, copyBytes, equalBytes, goQuote, fromHex, sha256, toHex, utf8Bytes, utf8Length } from './bytes.ts';
import { checkSchema, type Decoder, Encoder, MAX_SAFE_UINT, unmarshal } from './cbor.ts'; import { checkSchema, type Decoder, Encoder, MAX_SAFE_UINT, unmarshal } from './cbor.ts';
import { DateKeysError, withContext } from './errors.ts'; import { DateKeysError, withContext } from './errors.ts';
@ -295,9 +295,9 @@ export async function decodeProfile(b: Uint8Array): Promise<Profile> {
* bytes; * bytes;
* 2. the rules of each field (ERR_UNKNOWN_PROFILE): the name alphabets and * 2. the rules of each field (ERR_UNKNOWN_PROFILE): the name alphabets and
* their length limits, the public key length limit, genesis_time in * their length limits, the public key length limit, genesis_time in
* 1..253402300798, the provider drand, a scheme tlock supports, and a * 1..253402300798, the provider drand, the scheme
* public key in the prime-order subgroup of the key group of the scheme, * bls-unchained-g1-rfc9380 (since spec v0.14), and a public key in the
* not the identity; period at most 2^32-1 is also a rule of this point, * prime-order subgroup of G2, its key group, not the identity; period at most 2^32-1 is also a rule of this point,
* which the limit of point 1 makes unreachable here (chainInfoHash still * which the limit of point 1 makes unreachable here (chainInfoHash still
* enforces it); * enforces it);
* 3. the chain-hash self-check (ERR_PROFILE_MISMATCH): chain_hash is the * 3. the chain-hash self-check (ERR_PROFILE_MISMATCH): chain_hash is the
@ -337,24 +337,30 @@ export async function validateProfile(p: Profile): Promise<void> {
await validateDrand(p); await validateDrand(p);
} }
// Key group of each drand scheme tlock supports; the other drand schemes are // The schemes drand knows. Since spec v0.14 (§12.1, change 7 of §76), the
// known to drand but refused, anything else is not a drand scheme. // only one a profile may name is bls-unchained-g1-rfc9380, whose public key
const TLOCK_SCHEMES: ReadonlyMap<string, Group> = new Map([ // is in G2: the one scheme whose release and tlock decryption the
['bls-unchained-g1-rfc9380', 'G2'], // specification writes byte for byte. The others are drand schemes refused
['pedersen-bls-unchained', 'G1'], // with their own text; anything else is not a drand scheme.
['bls-unchained-on-g1', 'G2'], const DRAND_SCHEMES: ReadonlySet<string> = new Set([
'pedersen-bls-chained',
'pedersen-bls-unchained',
'bls-unchained-on-g1',
QUICKNET_SCHEME,
'bls-bn254-unchained-on-g1',
]); ]);
const OTHER_DRAND_SCHEMES: ReadonlySet<string> = new Set(['pedersen-bls-chained', 'bls-bn254-unchained-on-g1']);
async function validateDrand(p: Profile): Promise<void> { async function validateDrand(p: Profile): Promise<void> {
const group = TLOCK_SCHEMES.get(p.scheme); if (!DRAND_SCHEMES.has(p.scheme)) {
if (group === undefined) {
if (OTHER_DRAND_SCHEMES.has(p.scheme)) {
throw new DateKeysError('ERR_UNKNOWN_PROFILE', `profile ${p.id}: scheme ${goQuote(p.scheme)} is not supported by tlock`);
}
throw new DateKeysError('ERR_UNKNOWN_PROFILE', `profile ${p.id}: ${goQuote(p.scheme)} is not a drand scheme`); throw new DateKeysError('ERR_UNKNOWN_PROFILE', `profile ${p.id}: ${goQuote(p.scheme)} is not a drand scheme`);
} }
const point = checkCompressedPoint(group, p.publicKey); if (p.scheme !== QUICKNET_SCHEME) {
throw new DateKeysError(
'ERR_UNKNOWN_PROFILE',
`profile ${p.id}: scheme ${goQuote(p.scheme)} is not ${QUICKNET_SCHEME}, the only scheme of V1`,
);
}
const point = checkCompressedPoint('G2', p.publicKey);
if (point === 'invalid') { if (point === 'invalid') {
throw new DateKeysError('ERR_UNKNOWN_PROFILE', `profile ${p.id}: public key is not the canonical encoding of a point of the key group of ${p.scheme}`); throw new DateKeysError('ERR_UNKNOWN_PROFILE', `profile ${p.id}: public key is not the canonical encoding of a point of the key group of ${p.scheme}`);
} }

@ -14,14 +14,14 @@
// ERR_RELEASE_INVALID, and no text of noble is copied. // ERR_RELEASE_INVALID, and no text of noble is copied.
// //
// Only the scheme of Quicknet, bls-unchained-g1-rfc9380, is verified (plan of // Only the scheme of Quicknet, bls-unchained-g1-rfc9380, is verified (plan of
// phase 2, decision 3): a profile of another scheme fails with // phase 2, decision 3), the only one a profile may name since spec v0.14
// ERR_UNKNOWN_PROFILE after the round checks, where the reference would verify // (§12.1): a Profile value of another scheme, which validateProfile refuses,
// it. // fails here with ERR_UNKNOWN_PROFILE after the round checks.
import { bls12_381 } from '@noble/curves/bls12-381.js'; import { bls12_381 } from '@noble/curves/bls12-381.js';
import { checkCompressedPoint } from './bls12381.ts'; import { checkCompressedPoint } from './bls12381.ts';
import { DateKeysError } from './errors.ts'; import { DateKeysError } from './errors.ts';
import { roundIdentity } from './ibe.ts'; import { hashToG1, roundIdentity } from './ibe.ts';
import { maxRound, QUICKNET_SCHEME, type Profile } from './profile.ts'; import { maxRound, QUICKNET_SCHEME, type Profile } from './profile.ts';
const { G1, G2, shortSignatures } = bls12_381; const { G1, G2, shortSignatures } = bls12_381;
@ -79,7 +79,7 @@ function verifies(r: Release, publicKey: Uint8Array): boolean {
signature.assertValidity(); signature.assertValidity();
const key = G2.Point.fromBytes(publicKey); const key = G2.Point.fromBytes(publicKey);
key.assertValidity(); key.assertValidity();
return shortSignatures.verify(signature, shortSignatures.hash(roundIdentity(r.round), QUICKNET_DST), key); return shortSignatures.verify(signature, hashToG1(roundIdentity(r.round)), key);
} catch { } catch {
return false; return false;
} }

@ -1,5 +1,5 @@
{ {
"description": "Edge-case compressed BLS12-381 encodings (valid points, sort-bit flips, identity encodings with stray flags or payload, missing compression flag, wrong lengths, uncompressed forms, x + p, points on the curve outside the subgroup) with the verdict of the Go reference: the KeyGroup of the drand/drand/v2 crypto schemes (G1 for the unchained scheme, G2 for bls-unchained-g1-rfc9380), backed by github.com/drand/kyber-bls12381 v0.3.4 over github.com/kilic/bls12-381 v0.1.0, as profile.Validate uses it. The first 41 encodings were generated with @noble/curves 2.4.0 arithmetic; the rest are two samples of every class of a 41,686-input differential corpus and a 2,765-input adversarial corpus (cofactor torsion, small-order points, points plus torsion, sign edge cases, coordinates >= p, every flag combination, other lengths), on which this implementation, kilic and noble >= 2.3.0 with a length check agreed on every input; verdicts from scripts/bls12381-go-verdicts.go.", "description": "Edge-case compressed BLS12-381 encodings (valid points, sort-bit flips, identity encodings with stray flags or payload, missing compression flag, wrong lengths, uncompressed forms, x + p, points on the curve outside the subgroup) with the verdict of the Go reference: the KeyGroup of the drand/drand/v2 crypto schemes (G1 for the unchained scheme, G2 for bls-unchained-g1-rfc9380), backed by github.com/drand/kyber-bls12381 v0.3.4 over github.com/kilic/bls12-381 v0.1.0, as profile.Validate uses it for G2, the key group of the one scheme it admits since spec v0.14. The first 41 encodings were generated with @noble/curves 2.4.0 arithmetic; the rest are two samples of every class of a 41,686-input differential corpus and a 2,765-input adversarial corpus (cofactor torsion, small-order points, points plus torsion, sign edge cases, coordinates >= p, every flag combination, other lengths), on which this implementation, kilic and noble >= 2.3.0 with a length check agreed on every input; verdicts from scripts/bls12381-go-verdicts.go.",
"vectors": [ "vectors": [
{ {
"label": "g1_generator", "label": "g1_generator",

@ -1,7 +1,7 @@
{ {
"description": "The text of the error of capsule.Open for every case of testdata/vectors/mutations.json, or ok for a capsule that opens; see the header of scripts/mutation-go-texts.go.", "description": "The text of the error of capsule.Open for every case of testdata/vectors/mutations.json, or ok for a capsule that opens; see the header of scripts/mutation-go-texts.go.",
"generator": "scripts/mutation-go-texts.go", "generator": "scripts/mutation-go-texts.go",
"spec": "0.13", "spec": "0.14",
"cases": [ "cases": [
{ {
"name": "PUBLIC_HEADER_A + SEALED_CONTROL_B", "name": "PUBLIC_HEADER_A + SEALED_CONTROL_B",

@ -7,6 +7,8 @@
// max_depth and max_len, and every schema vector through the decoder of // max_depth and max_len, and every schema vector through the decoder of
// its schema, CONTROL_CBOR in the format of the vector, with the exact // its schema, CONTROL_CBOR in the format of the vector, with the exact
// result; // result;
// - vectors/tlock_steps.json: steps 10 and 11 for Quicknet value by value,
// with the code of ibe.ts, release.ts and bls12381.ts;
// - vectors/padding.json: P with both rules and the length of PAYLOAD_AGE // - vectors/padding.json: P with both rules and the length of PAYLOAD_AGE
// for every L, and the lengths above L_MAX rejected; // for every L, and the lengths above L_MAX rejected;
// - vectors/mutations.json: every case whose step is 1 to 8 through // - vectors/mutations.json: every case whose step is 1 to 8 through
@ -42,6 +44,20 @@ import { type Format, FORMAT_1, FORMAT_2, FORMAT_3, isFormat } from './framing.t
import { BLOQUE256, MAX_PAYLOAD_LENGTH, padmeParameters, paddedLength, payloadAgeLength, REFORZADO } from './padding.ts'; import { BLOQUE256, MAX_PAYLOAD_LENGTH, padmeParameters, paddedLength, payloadAgeLength, REFORZADO } from './padding.ts';
import { canonicalJSON, compactDateKey, formatRFC3339, formatRFC3339Nano, type Instant, parseDateKey, parseRFC3339, resolveDateKey, unlockAt } from './datekey.ts'; import { canonicalJSON, compactDateKey, formatRFC3339, formatRFC3339Nano, type Instant, parseDateKey, parseRFC3339, resolveDateKey, unlockAt } from './datekey.ts';
import { DateKeysError, errorCode } from './errors.ts'; import { DateKeysError, errorCode } from './errors.ts';
import {
ciphertextFromBody,
decryptOnG2,
gtBytes,
h2 as ibeH2,
h3,
h3Base,
h3Try,
h4 as ibeH4,
hashToG1,
IbeError,
proofHolds,
roundIdentity,
} from './ibe.ts';
import { openEnvelope, openSealed } from './envelope.ts'; import { openEnvelope, openSealed } from './envelope.ts';
import { CAPSULE_ID, type Extension, type ExtensionRegistry } from './extension.ts'; import { CAPSULE_ID, type Extension, type ExtensionRegistry } from './extension.ts';
import { decodeHead, encodeHead, type HeadFile } from './head.ts'; import { decodeHead, encodeHead, type HeadFile } from './head.ts';
@ -73,9 +89,10 @@ import {
profileHash, profileHash,
type ProfileRegistry, type ProfileRegistry,
QUICKNET_ID, QUICKNET_ID,
QUICKNET_SCHEME,
quicknet, quicknet,
} from './profile.ts'; } from './profile.ts';
import type { Release, ReleaseSource } from './release.ts'; import { QUICKNET_DST, type Release, type ReleaseSource, verifyRelease } from './release.ts';
import { evaluateSecurity, type Verdict, verdictLines } from './security.ts'; import { evaluateSecurity, type Verdict, verdictLines } from './security.ts';
import { MemorySink } from './sink.ts'; import { MemorySink } from './sink.ts';
import { readVectors as readLocatorVectors } from './testing/locator.ts'; import { readVectors as readLocatorVectors } from './testing/locator.ts';
@ -1065,6 +1082,219 @@ describe('vectors/tlock_ibe.json', () => {
}); });
}); });
// ---------------------------------------------------------------------------
// vectors/tlock_steps.json
//
// Steps 10 and 11 of spec §63 for Quicknet, value by value (spec v0.14, the
// paragraphs "Mensaje de ronda y hash a G1" and "H3 y H4"), walked with the
// code of this library: roundIdentity and hashToG1 of ibe.ts for M and H(M),
// verifyRelease of release.ts and the pairing equation for the release, the
// gate of bls12381.ts on the points, then ciphertextFromBody, gtBytes, h2,
// h4, h3Base, h3Try, h3 and proofHolds of ibe.ts for the stanza, and
// decryptOnG2 on the whole body. The negative checks are the misreadings the
// generator rules out: the DST of G2 or the round itself as the message, the
// top bit of H3 cleared instead of its first byte shifted; and a signature of
// another round and an edited V or W, which do not decrypt.
interface TlockTry {
i: number;
digest: Uint8Array;
shifted: Uint8Array;
accepted: boolean;
}
interface TlockStep {
name: string;
round: number;
signature: Uint8Array;
message: Uint8Array;
hashToG1: Uint8Array;
body: Uint8Array;
u: Uint8Array;
v: Uint8Array;
w: Uint8Array;
pairing: Uint8Array;
h2: Uint8Array;
sigma: Uint8Array;
h4: Uint8Array;
fileKey: Uint8Array;
h3Base: Uint8Array;
h3Tries: TlockTry[];
r: Uint8Array;
}
const G2_DST = 'BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_NUL_';
const xorBytes = (a: Uint8Array, b: Uint8Array): Uint8Array => a.map((x, i) => x ^ b[i]!);
const bigBE = (b: Uint8Array): bigint => BigInt(`0x${toHex(b)}`);
const topBitCleared = (d: Uint8Array): Uint8Array => Uint8Array.of(d[0]! & 0x7f, ...d.subarray(1));
const gtHex = (p: InstanceType<typeof bls12_381.G1.Point>, q: InstanceType<typeof bls12_381.G2.Point>): string =>
toHex(gtBytes(bls12_381.pairing(p, q)));
function sizedHex(c: Record<string, unknown>, w: string, k: string, n: number): Uint8Array {
const b = hexBytes(c[k], `${w}.${k}`);
if (b.length !== n) throw new FormatError(`${w}.${k}`, `${b.length} bytes, want ${n}`);
return b;
}
describe('vectors/tlock_steps.json', () => {
const f = load('vectors/tlock_steps.json', (json) => {
const file = 'tlock_steps.json';
const o = object(json, file);
keys(o, file, ['spec', 'description', 'profile', 'scheme', 'chain_hash', 'public_key', 'dst', 'tags', 'vectors']);
checkSpec(o, file);
str(o.description, `${file}.description`);
const tags = object(o.tags, `${file}.tags`);
keys(tags, `${file}.tags`, ['h2', 'h3', 'h4']);
const vectors = array(o.vectors, `${file}.vectors`).map((v, i): TlockStep => {
const w = `${file}.vectors[${i}]`;
const c = object(v, w);
keys(c, w, ['name', 'round', 'signature', 'message', 'hash_to_g1', 'body', 'u', 'v', 'w', 'pairing', 'h2', 'sigma', 'h4', 'file_key', 'h3_base', 'h3_tries', 'r']);
const h3Tries = array(c.h3_tries, `${w}.h3_tries`).map((t, j): TlockTry => {
const tw = `${w}.h3_tries[${j}]`;
const tc = object(t, tw);
keys(tc, tw, ['i', 'digest', 'shifted', 'accepted']);
return {
i: int(tc.i, `${tw}.i`),
digest: sizedHex(tc, tw, 'digest', 32),
shifted: sizedHex(tc, tw, 'shifted', 32),
accepted: bool(tc.accepted, `${tw}.accepted`),
};
});
return {
name: str(c.name, `${w}.name`),
round: int(c.round, `${w}.round`),
signature: sizedHex(c, w, 'signature', 48),
message: sizedHex(c, w, 'message', 32),
hashToG1: sizedHex(c, w, 'hash_to_g1', 48),
body: sizedHex(c, w, 'body', 128),
u: sizedHex(c, w, 'u', 96),
v: sizedHex(c, w, 'v', 16),
w: sizedHex(c, w, 'w', 16),
pairing: sizedHex(c, w, 'pairing', 576),
h2: sizedHex(c, w, 'h2', 16),
sigma: sizedHex(c, w, 'sigma', 16),
h4: sizedHex(c, w, 'h4', 16),
fileKey: sizedHex(c, w, 'file_key', 16),
h3Base: sizedHex(c, w, 'h3_base', 32),
h3Tries,
r: sizedHex(c, w, 'r', 32),
};
});
return {
profile: str(o.profile, `${file}.profile`),
scheme: str(o.scheme, `${file}.scheme`),
chainHash: sizedHex(o, file, 'chain_hash', 32),
publicKey: sizedHex(o, file, 'public_key', 96),
dst: str(o.dst, `${file}.dst`),
tags: { h2: hexBytes(tags.h2, `${file}.tags.h2`), h3: hexBytes(tags.h3, `${file}.tags.h3`), h4: hexBytes(tags.h4, `${file}.tags.h4`) },
vectors,
};
});
if (f === undefined) return;
const q = quicknet();
const key = bls12_381.G2.Point.fromBytes(q.publicKey);
const order = bls12_381.fields.Fr.ORDER;
it('is the pinned profile of Quicknet, with the DST and the tags of spec §63', () => {
expect(f.profile).toBe(QUICKNET_ID);
expect(f.scheme).toBe(QUICKNET_SCHEME);
expect(toHex(f.chainHash)).toBe(toHex(q.chainHash));
expect(toHex(f.publicKey)).toBe(toHex(q.publicKey));
expect(f.dst).toBe(QUICKNET_DST);
expect(decodeUtf8(f.tags.h2)).toBe('IBE-H2');
expect(decodeUtf8(f.tags.h3)).toBe('IBE-H3');
expect(decodeUtf8(f.tags.h4)).toBe('IBE-H4');
expect(f.vectors.length).toBeGreaterThan(0);
});
it('has a stanza whose H3 accepts a later try than the top bit cleared would', () => {
// The vector that tells the shift from the misreading of spec §63: the
// try that clearing the top bit accepts comes before the right one.
const earlier = f.vectors.some((v) => {
const cleared = v.h3Tries.findIndex((t) => bigBE(topBitCleared(t.digest)) < order);
return cleared >= 0 && cleared < v.h3Tries.length - 1;
});
expect(earlier).toBe(true);
});
it.each(f.vectors.map((v) => [v.name, v] as const))('%s', async (_n, v) => {
// Step 10: M, H(M), the release and the pairing equation.
expect(toHex(roundIdentity(v.round))).toBe(toHex(v.message));
const hm = hashToG1(v.message);
expect(toHex(hm.toBytes())).toBe(toHex(v.hashToG1));
expect(checkCompressedPoint('G1', v.hashToG1)).toBe('point');
expect(checkCompressedPoint('G1', v.signature)).toBe('point');
expect(() => verifyRelease(q, v.round, { round: v.round, signature: v.signature })).not.toThrow();
const sig = bls12_381.G1.Point.fromBytes(v.signature);
const signed = gtHex(sig, bls12_381.G2.Point.BASE);
expect(gtHex(hm, key)).toBe(signed);
// The DST of G2, and the round itself as the message, do not verify.
expect(gtHex(bls12_381.shortSignatures.hash(v.message, G2_DST), key)).not.toBe(signed);
const roundBytes = new Uint8Array(8);
new DataView(roundBytes.buffer).setBigUint64(0, BigInt(v.round));
expect(gtHex(hashToG1(roundBytes), key)).not.toBe(signed);
// Step 11: the parts of the stanza.
const ct = ciphertextFromBody(v.body);
expect(toHex(ct.U)).toBe(toHex(v.u));
expect(toHex(ct.V)).toBe(toHex(v.v));
expect(toHex(ct.W)).toBe(toHex(v.w));
expect(toHex(concatBytes(v.u, v.v, v.w))).toBe(toHex(v.body));
expect(checkCompressedPoint('G2', v.u)).toBe('point');
const u = bls12_381.G2.Point.fromBytes(v.u);
// e(signature, U), which is e(H(M), public key)^r, then H2, sigma, H4
// and the file key.
const gt = bls12_381.pairing(sig, u);
expect(toHex(gtBytes(gt))).toBe(toHex(v.pairing));
expect(toHex(gtBytes(bls12_381.fields.Fp12.pow(bls12_381.pairing(hm, key), bigBE(v.r))))).toBe(toHex(v.pairing));
expect(toHex(ibeH2(gt, 16))).toBe(toHex(v.h2));
expect(toHex(xorBytes(v.v, v.h2))).toBe(toHex(v.sigma));
expect(toHex(ibeH4(v.sigma, 16))).toBe(toHex(v.h4));
expect(toHex(xorBytes(v.w, v.h4))).toBe(toHex(v.fileKey));
// H3: the base, every try in order, and r.
expect(toHex(h3Base(v.sigma, v.fileKey))).toBe(toHex(v.h3Base));
expect(v.h3Tries.length).toBeGreaterThan(0);
for (const [j, t] of v.h3Tries.entries()) {
const at = `try ${t.i}`;
expect(t.i, at).toBe(j + 1);
expect(toHex(await sha256(concatBytes(Uint8Array.of(t.i & 0xff, t.i >> 8), v.h3Base))), at).toBe(toHex(t.digest));
expect(toHex(h3Try(v.h3Base, t.i)), at).toBe(toHex(t.shifted));
expect(t.shifted[0], at).toBe(t.digest[0]! >> 1);
expect(toHex(t.shifted.subarray(1)), at).toBe(toHex(t.digest.subarray(1)));
expect(t.accepted, at).toBe(bigBE(t.shifted) < order);
expect(t.accepted, at).toBe(j === v.h3Tries.length - 1);
if (!t.accepted) expect(() => h3(v.sigma, v.fileKey, t.i), at).toThrow(IbeError);
}
const last = v.h3Tries[v.h3Tries.length - 1]!;
expect(toHex(v.r)).toBe(toHex(last.shifted));
const r = h3(v.sigma, v.fileKey);
expect(r).toBe(bigBE(v.r));
expect(h3(v.sigma, v.fileKey, last.i)).toBe(r);
// r·G2 = U, and the whole stanza decrypts to the file key.
expect(proofHolds(r, u)).toBe(true);
expect(toHex(bls12_381.G2.Point.BASE.multiply(r).toBytes())).toBe(toHex(v.u));
expect(toHex(decryptOnG2(v.signature, ct))).toBe(toHex(v.fileKey));
// The top bit cleared instead of the first byte shifted gives another
// r, which U does not prove.
const cleared = v.h3Tries.map((t) => topBitCleared(t.digest)).find((d) => bigBE(d) < order);
if (cleared !== undefined) {
expect(bigBE(cleared)).not.toBe(r);
expect(proofHolds(bigBE(cleared), u)).toBe(false);
}
// A signature of another round, and an edited V or W, do not decrypt.
const other = f.vectors.find((x) => x.round !== v.round)!;
expect(other).toBeDefined();
expect(() => verifyRelease(q, v.round, { round: v.round, signature: other.signature })).toThrow(/ERR_RELEASE_INVALID$/);
expect(() => decryptOnG2(other.signature, ct)).toThrow(IbeError);
for (const at of [96, 111, 112, 127]) {
const edited = v.body.slice();
edited[at]! ^= 1;
expect(() => decryptOnG2(v.signature, ciphertextFromBody(edited)), `bit flipped at ${at}`).toThrow(IbeError);
}
});
});
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// vectors/paths.json and vectors/path_fold.json // vectors/paths.json and vectors/path_fold.json
// //
@ -1619,6 +1849,7 @@ const VECTOR_FILES = [
'vectors/security.json', 'vectors/security.json',
'vectors/security_cms.json', 'vectors/security_cms.json',
'vectors/tlock_ibe.json', 'vectors/tlock_ibe.json',
'vectors/tlock_steps.json',
'vectors/wordkey.json', 'vectors/wordkey.json',
]; ];

@ -14,7 +14,7 @@ export const VERSION = '0.3.0-dev';
/** /**
* The version of the DateKeys Protocol Specification that this library * The version of the DateKeys Protocol Specification that this library
* implements: the tag spec-v0.13 of the Go reference, whose shared vectors * implements: the tag spec-v0.14 of the Go reference, whose shared vectors
* and fixtures (testdata/) all name it. * and fixtures (testdata/) all name it.
*/ */
export const SPEC_VERSION = '0.13'; export const SPEC_VERSION = '0.14';

86
testdata/README.md vendored

@ -1,7 +1,7 @@
# DateKeys test data # DateKeys test data
Official vectors, fixtures and corpora of the DateKeys Protocol Specification Official vectors, fixtures and corpora of the DateKeys Protocol Specification
v0.13, generated by the reference implementation. v0.14, generated by the reference implementation.
Another implementation consumes them as they are: this file documents every Another implementation consumes them as they are: this file documents every
format, so that no Go code has to be read. The rules that decide each verdict format, so that no Go code has to be read. The rules that decide each verdict
are in the specification; this file points to them, and states only what are in the specification; this file points to them, and states only what
@ -21,7 +21,7 @@ added since. The local gate (`scripts/check.sh`) and CI run it and fail if any
committed file changes: every file below is exactly what the implementation committed file changes: every file below is exactly what the implementation
computes today. computes today.
The `spec` field of every file is `"0.13"`, the version this module declares. The `spec` field of every file is `"0.14"`, the version this module declares.
What v0.12 changes from v0.11, the texts of the verdicts of a certificate and What v0.12 changes from v0.11, the texts of the verdicts of a certificate and
of a seal, the profile of a certificate and the rules of the addresses and of of a seal, the profile of a certificate and the rules of the addresses and of
the padding of a locator, is in the files: the verdicts and the lines of the padding of a locator, is in the files: the verdicts and the lines of
@ -48,6 +48,7 @@ Conventions for every file:
| `vectors/dk1.json` | canonical `dk1_` strings, and rejected encodings with their code | §18, §19, §66 | | `vectors/dk1.json` | canonical `dk1_` strings, and rejected encodings with their code | §18, §19, §66 |
| `vectors/cbor.json` | the CBOR profile, and one block of vectors per schema, CONTROL_CBOR in the three formats | §58, CDDL | | `vectors/cbor.json` | the CBOR profile, and one block of vectors per schema, CONTROL_CBOR in the three formats | §58, CDDL |
| `vectors/tlock_ibe.json` | H2 of the tlock IBE: the serialization of an element of GT | §63 step 11 | | `vectors/tlock_ibe.json` | H2 of the tlock IBE: the serialization of an element of GT | §63 step 11 |
| `vectors/tlock_steps.json` | steps 10 and 11 for Quicknet value by value: the message of a round, its hash to G1, and the decryption of a tlock stanza with H2, H4, H3 and the file key | §63 steps 10 and 11 (v0.14) |
| `vectors/padding.json` | the padding of formats 2 and 3: P for each content length L, and the length of PAYLOAD_AGE | §29.1 | | `vectors/padding.json` | the padding of formats 2 and 3: P for each content length L, and the length of PAYLOAD_AGE | §29.1 |
| `vectors/paths.json` | the paths of a format 3 head: the rules of one entry, and those of the paths of a head | §29.5 | | `vectors/paths.json` | the paths of a format 3 head: the rules of one entry, and those of the paths of a head | §29.5 |
| `vectors/path_fold.json` | the key of R7 of segments, and their NFD | §29.5, §29.5.1 | | `vectors/path_fold.json` | the key of R7 of segments, and their NFD | §29.5, §29.5.1 |
@ -311,6 +312,87 @@ serialization at once. The same 576 bytes with the twelve coordinates of Fp in
reverse order, c0 first at every level as `Fp12.toBytes` of `@noble/curves` reverse order, c0 first at every level as `Fp12.toBytes` of `@noble/curves`
writes them, give `0118eea9d5971745f71e3c94926f1717` and another FK_TIME. writes them, give `0118eea9d5971745f71e3c94926f1717` and another FK_TIME.
## `vectors/tlock_steps.json`
Steps 10 and 11 of spec §63 for Quicknet, every intermediate value written
out, over the published releases of rounds 1000, 1001, 1004 and 2000 (spec
v0.14: the paragraphs "Mensaje de ronda y hash a G1" and "H3 y H4" after the
flow).
```json
{
"spec": "0.14",
"description": "…",
"profile": "datekeys:quicknet:v1",
"scheme": "bls-unchained-g1-rfc9380",
"chain_hash": "52db…",
"public_key": "83cf…",
"dst": "BLS_SIG_BLS12381G1_XMD:SHA-256_SSWU_RO_NUL_",
"tags": { "h2": "4942452d4832", "h3": "4942452d4833", "h4": "4942452d4834" },
"vectors": [
{
"name": "round 1000, stanza 0",
"round": 1000,
"signature": "b446…",
"message": "f652…",
"hash_to_g1": "8f5a…",
"body": "a73e…", "u": "a73e…", "v": "f628…", "w": "b799…",
"pairing": "13dc…",
"h2": "…", "sigma": "…", "h4": "…", "file_key": "…",
"h3_base": "…",
"h3_tries": [ { "i": 1, "digest": "…", "shifted": "…", "accepted": true } ],
"r": "20fd…"
}
]
}
```
Every byte string is hex. The top-level fields are those of the pinned
profile (spec §12), the DST of the hash to G1 as text and the tags of H2, H3
and H4 as bytes: the ASCII of `IBE-H2`, `IBE-H3` and `IBE-H4`.
Step 10, the release:
- `signature`: the published signature of `round`, the release, compressed in
G1 (spec §12.2).
- `message`: M = SHA-256 of the round as 8 bytes big-endian, the message an
unchained drand scheme signs.
- `hash_to_g1`: H(M), hash_to_curve of RFC 9380 with the suite
`BLS12381G1_XMD:SHA-256_SSWU_RO_` and the DST `dst`, compressed. The
signature verifies: e(H(M), `public_key`) = e(`signature`, G2), with G2 the
generator of G2.
Step 11, one tlock stanza of the round:
- `body`: the stanza body U || V || W, 128 bytes, and `u`, `v` and `w` its
three parts: U compressed in G2, V and W of 16 bytes.
- `pairing`: e(`signature`, U), 576 bytes in the order of `tlock_ibe.json`.
- `h2`: SHA-256 of `IBE-H2` and `pairing`, truncated to 16 bytes.
- `sigma`: V XOR `h2`.
- `h4`: SHA-256 of `IBE-H4` and `sigma`, truncated to 16 bytes.
- `file_key`: W XOR `h4`, FK_TIME, the file key of OUTER_TIME_AGE.
- `h3_base`: SHA-256 of `IBE-H3`, `sigma` and `file_key`.
- `h3_tries`: the tries of H3, in order. Try `i` hashes the counter `i` as 2
bytes little-endian followed by `h3_base` (`digest`), then shifts the first
byte of the digest one bit to the right (`shifted`); the try is accepted
when `shifted`, read as a big-endian integer, is below the order r of the
groups (spec §12.2). Only the last try is accepted. The shift moves every
bit of the first byte; clearing only its top bit gives another r.
- `r`: the accepted `shifted`, the scalar of the check r·G2 = U.
The last vector is the first stanza of round 1000, in the order of the
generator, whose H3 needs at least three tries: it accepts its fourth, where
clearing the top bit would accept the second. A reader checks every value
in this order and the check r·G2 = U.
The generator chooses `sigma` and `file_key` per stanza, derives r, U, V and W
with its own H2, H3 and H4, and checks the result against the libraries the
reference uses: `message` against `DigestBeacon` of the drand scheme,
`hash_to_g1` against the pairing equation with the published signature, and
the body against `tlock.TimeUnlock`, `DecryptCCAonG2` of drand/kyber and the
tlock identity of `agewrap`, which give back `file_key` only if their H2, H3
and H4 are the ones written here.
## `vectors/padding.json` ## `vectors/padding.json`
The padding of the payload of a capsule of format 2 or 3, spec §29.1, where L The padding of the payload of a capsule of format 2 or 3, spec §29.1, where L

105
testdata/SOURCE.json vendored

@ -1,141 +1,142 @@
{ {
"module": "g.activething.com/go/DateKeys", "module": "g.activething.com/go/DateKeys",
"commit": "913dd609dd19b31a1fb053e477d28ee142682700", "commit": "39b2033e3ccf54a91bda8d7e3ced39b26dbfa58c",
"files": { "files": {
"README.md": "dfc10417c920adafb2064a176adad4b5b833b1282a52e9b0bb29bc077d0775c8", "README.md": "799d72ac1b30d8dc3769732712db40ad3c24ae6d58099280e14b39b3fdeb232c",
"fixtures/empty_payload.dkc": "871e9bf05b52bbae17f3adfbbf97b46e7f0e53aa8f57bcaa506e43f36f53a9d4", "fixtures/empty_payload.dkc": "871e9bf05b52bbae17f3adfbbf97b46e7f0e53aa8f57bcaa506e43f36f53a9d4",
"fixtures/empty_payload.inspect.json": "373e5d012b023ad58bbb54cbdffe0bed9e50c637438a4083ddb74d5414c59f59", "fixtures/empty_payload.inspect.json": "373e5d012b023ad58bbb54cbdffe0bed9e50c637438a4083ddb74d5414c59f59",
"fixtures/empty_payload.json": "c78aa35bd1dd8988a449e5c148bc4ee84ffd5cd4139e19ddcc2e7af9f80ccf80", "fixtures/empty_payload.json": "6da4e8b868fe96c198730bd0d4416cd2133a4a601296519eca174200bce98b50",
"fixtures/empty_payload.plaintext": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "fixtures/empty_payload.plaintext": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"fixtures/format2_empty_payload.dkc": "7aea2b5aa48b1a46053716f733d50fab9cd0b80b1be67631bcc06c5bb765dc21", "fixtures/format2_empty_payload.dkc": "7aea2b5aa48b1a46053716f733d50fab9cd0b80b1be67631bcc06c5bb765dc21",
"fixtures/format2_empty_payload.inspect.json": "d0bb7356d3970986e6b197640f0b3b38abe9fabf1740b745171b358aa28903ff", "fixtures/format2_empty_payload.inspect.json": "d0bb7356d3970986e6b197640f0b3b38abe9fabf1740b745171b358aa28903ff",
"fixtures/format2_empty_payload.json": "581a952451a386a9c9effc124ce6e45cd813e2215027cef19422271921922ef6", "fixtures/format2_empty_payload.json": "46acca809abefca332fea81cc124b8506fbbb0655e66983cdf614f3c78c0e8a2",
"fixtures/format2_empty_payload.plaintext": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "fixtures/format2_empty_payload.plaintext": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"fixtures/format2_time_and_key_portable.dkc": "600892659fe4890223e895876275f656995d170fda42b07fb2bec0ca51ce4b43", "fixtures/format2_time_and_key_portable.dkc": "600892659fe4890223e895876275f656995d170fda42b07fb2bec0ca51ce4b43",
"fixtures/format2_time_and_key_portable.dkk": "095b7bc516a22bf0c2366f0af3cd48bfe857a2354d6e2a9b285278b95e450fe0", "fixtures/format2_time_and_key_portable.dkk": "095b7bc516a22bf0c2366f0af3cd48bfe857a2354d6e2a9b285278b95e450fe0",
"fixtures/format2_time_and_key_portable.dkk.json": "cde7c72fcd1250fed95af09354023c9d7feafa7e2418f7d10ae4e023261e1b5e", "fixtures/format2_time_and_key_portable.dkk.json": "e32128d0a1cba1fa1a6d8f5736728fe5d2342ac36efddfd8884cd5b256a369df",
"fixtures/format2_time_and_key_portable.inspect.json": "522c9a98e5911c86f5f24f278971cf7c7588f6c88aaede3dd1129ee4e042868a", "fixtures/format2_time_and_key_portable.inspect.json": "522c9a98e5911c86f5f24f278971cf7c7588f6c88aaede3dd1129ee4e042868a",
"fixtures/format2_time_and_key_portable.json": "2da54bb3c4cc024b0c387c8ba344e5eff0483cbfc1b1bb9ef302df3ec8509d33", "fixtures/format2_time_and_key_portable.json": "20ce55ecb3d2aec77592dd56c1930f3f53594b83c8a881317460e01b5cae1a24",
"fixtures/format2_time_and_key_portable.plaintext": "937492203d207d6fe36161b8696bf1f05b8b4cc56d855c44853f4b76aad3a05b", "fixtures/format2_time_and_key_portable.plaintext": "937492203d207d6fe36161b8696bf1f05b8b4cc56d855c44853f4b76aad3a05b",
"fixtures/format2_time_and_key_recipients.dkc": "1a44fd8708c92e2e0a10cfcb1d864a71331ea9af25d97e1a42e969dc898959e3", "fixtures/format2_time_and_key_recipients.dkc": "1a44fd8708c92e2e0a10cfcb1d864a71331ea9af25d97e1a42e969dc898959e3",
"fixtures/format2_time_and_key_recipients.dkk": "2ad99b1556086ec311d7f0b3bd3aaba05e75f45c4fa22490b0d5e8bb0b1a222e", "fixtures/format2_time_and_key_recipients.dkk": "2ad99b1556086ec311d7f0b3bd3aaba05e75f45c4fa22490b0d5e8bb0b1a222e",
"fixtures/format2_time_and_key_recipients.dkk.json": "ca0263ade14c328e3751dd81be8c35d7584ce7e574e1f2047f696fd8d89d611a", "fixtures/format2_time_and_key_recipients.dkk.json": "5223a3b01b6e0c8f9cb6244e4edb9eec0d5c2b90111b2f748f12f330431df920",
"fixtures/format2_time_and_key_recipients.inspect.json": "d975a9eddd45f5d59618ea2455d574d807e57daf08585e840d07986f261bf099", "fixtures/format2_time_and_key_recipients.inspect.json": "d975a9eddd45f5d59618ea2455d574d807e57daf08585e840d07986f261bf099",
"fixtures/format2_time_and_key_recipients.json": "76e8904faf3bbe624d5f8de1c0d07126a36e478d72a225a228400a5c0cc35cf3", "fixtures/format2_time_and_key_recipients.json": "3f3b85f0b870867335bc3b0a820d6022e490904878d65a84984e347da2f49f9c",
"fixtures/format2_time_and_key_recipients.plaintext": "0e9fd50e98a85953aa9cf07a11ee3c62bb3d7622f344f1c6ce744d1ed111659f", "fixtures/format2_time_and_key_recipients.plaintext": "0e9fd50e98a85953aa9cf07a11ee3c62bb3d7622f344f1c6ce744d1ed111659f",
"fixtures/format2_time_and_key_sixteen.dkc": "7aaac5c18f216bf53df326ecc817179640a53408cf25dfd50488910a762dc381", "fixtures/format2_time_and_key_sixteen.dkc": "7aaac5c18f216bf53df326ecc817179640a53408cf25dfd50488910a762dc381",
"fixtures/format2_time_and_key_sixteen.inspect.json": "492cd0b0dca0030df9332b098d22b4f6aa4adfb57d5540de5325e3e6d5aa3667", "fixtures/format2_time_and_key_sixteen.inspect.json": "492cd0b0dca0030df9332b098d22b4f6aa4adfb57d5540de5325e3e6d5aa3667",
"fixtures/format2_time_and_key_sixteen.json": "72fa30ba0d9d274579e5d47c579d5da7ac7201a3f6c842eb91934bf6ecf6871e", "fixtures/format2_time_and_key_sixteen.json": "ef2b4107e9b24d350681a6c5f00476d7bbf987f65b6a1a2070255cc4b08b6308",
"fixtures/format2_time_and_key_sixteen.plaintext": "e5abfb7b5fdbf297277b6cc4729c15d85435e890b653c2e2342b7031ecd9eab9", "fixtures/format2_time_and_key_sixteen.plaintext": "e5abfb7b5fdbf297277b6cc4729c15d85435e890b653c2e2342b7031ecd9eab9",
"fixtures/format2_time_only.dkc": "f5a40ac6b8a08a0c12db6114c2bca23522d6a77b512b509a217fb15f367813c4", "fixtures/format2_time_only.dkc": "f5a40ac6b8a08a0c12db6114c2bca23522d6a77b512b509a217fb15f367813c4",
"fixtures/format2_time_only.inspect.json": "40a8683f5204c7b6369558e4775ae6bb6fed978097e9e660de64c06c167b043e", "fixtures/format2_time_only.inspect.json": "40a8683f5204c7b6369558e4775ae6bb6fed978097e9e660de64c06c167b043e",
"fixtures/format2_time_only.json": "e566e020b9bd99cbed5f2e222adee9d0def16a77d536924f4027bbcbeea1b622", "fixtures/format2_time_only.json": "aa844c0b985cb6822a0ca4a2fa9acfa37260dfe3358336ee2735351a6c853648",
"fixtures/format2_time_only.plaintext": "53b8ee821fb7b678e89d4f93da1812339f6cc1ab83aac6ed1432db99df784be5", "fixtures/format2_time_only.plaintext": "53b8ee821fb7b678e89d4f93da1812339f6cc1ab83aac6ed1432db99df784be5",
"fixtures/format2_time_only_bloque256.dkc": "aae769c30d04920801d8b293d30864fbe223c9c9353ec2b4907a1ee1996e39f9", "fixtures/format2_time_only_bloque256.dkc": "aae769c30d04920801d8b293d30864fbe223c9c9353ec2b4907a1ee1996e39f9",
"fixtures/format2_time_only_bloque256.inspect.json": "767766414ad547f0ba95b40059e14b62c81b5489a2afcbc683bf227334d61be7", "fixtures/format2_time_only_bloque256.inspect.json": "767766414ad547f0ba95b40059e14b62c81b5489a2afcbc683bf227334d61be7",
"fixtures/format2_time_only_bloque256.json": "dde4588311879acc231c80ba1132a8839504d8b4119cbfa152391655645a4487", "fixtures/format2_time_only_bloque256.json": "63b9c57c6d4b8be71c584afa79584f47f6365677adcefe07db9c2162827df922",
"fixtures/format2_time_only_bloque256.plaintext": "53b8ee821fb7b678e89d4f93da1812339f6cc1ab83aac6ed1432db99df784be5", "fixtures/format2_time_only_bloque256.plaintext": "53b8ee821fb7b678e89d4f93da1812339f6cc1ab83aac6ed1432db99df784be5",
"fixtures/format2_time_only_extensions.dkc": "fb406100d5703a2e888983b3175ed34a09a34469cc722256e5cf535dd728fbe9", "fixtures/format2_time_only_extensions.dkc": "fb406100d5703a2e888983b3175ed34a09a34469cc722256e5cf535dd728fbe9",
"fixtures/format2_time_only_extensions.inspect.json": "1595d793c1d35bfdaa36576b75f53d734a9e07c2a8a12036295dbaee7f5a7f5a", "fixtures/format2_time_only_extensions.inspect.json": "1595d793c1d35bfdaa36576b75f53d734a9e07c2a8a12036295dbaee7f5a7f5a",
"fixtures/format2_time_only_extensions.json": "3a82f184a3c2a3bb3f668c24ac021ae56b9c1f8568c0e1b4e18cec0082ad2a66", "fixtures/format2_time_only_extensions.json": "2f7f4664bc9845d6f976616b8347ae5bb0d0e380c5c1bc396d83b3e22e432c2f",
"fixtures/format2_time_only_extensions.plaintext": "1129768e195e2f1e50b7a6f926b6eebef120212c29b5642c8a662c503b2a9131", "fixtures/format2_time_only_extensions.plaintext": "1129768e195e2f1e50b7a6f926b6eebef120212c29b5642c8a662c503b2a9131",
"fixtures/format3_area_1024.dkc": "41ea2eed0293e4fef7f4a307b7f16aaf1339f5bf6f4ded7a6a9ae1aebeb0133c", "fixtures/format3_area_1024.dkc": "41ea2eed0293e4fef7f4a307b7f16aaf1339f5bf6f4ded7a6a9ae1aebeb0133c",
"fixtures/format3_area_1024.inspect.json": "06e6b347926242ae5540f16a053f6a3545743986989bc0be8c39918bce968686", "fixtures/format3_area_1024.inspect.json": "06e6b347926242ae5540f16a053f6a3545743986989bc0be8c39918bce968686",
"fixtures/format3_area_1024.json": "03275837381b97c645012cd710de7447e6c2c53f639c61cfd38a356c06f9f48e", "fixtures/format3_area_1024.json": "59a9e7d5575a57154d524ddeeba6cd84ac746da6831ba66588d7bb718953e3c3",
"fixtures/format3_area_1024.plaintext": "043830350a287cba1fd50f6c063f70a74209895ff0cf03147bb4e5ccdfc206b5", "fixtures/format3_area_1024.plaintext": "043830350a287cba1fd50f6c063f70a74209895ff0cf03147bb4e5ccdfc206b5",
"fixtures/format3_bloque256.dkc": "ff18444f434164ba8e7b26d38c76c7855dc6b0593b2fc8b4e9a95dbf9252d55d", "fixtures/format3_bloque256.dkc": "ff18444f434164ba8e7b26d38c76c7855dc6b0593b2fc8b4e9a95dbf9252d55d",
"fixtures/format3_bloque256.inspect.json": "d0007080da5ce079c6ffa3a56bf8ce519d2846a31cc1082fd027f401e4f7bade", "fixtures/format3_bloque256.inspect.json": "d0007080da5ce079c6ffa3a56bf8ce519d2846a31cc1082fd027f401e4f7bade",
"fixtures/format3_bloque256.json": "9d3fc4715acde8bb1c7783bf42fb86914f442d37121e0c61d0c0937a80ad9c17", "fixtures/format3_bloque256.json": "71dd9668f9dd1121dbd86de46c6561b821bb0fd5b90135685d4c4744a02a1a06",
"fixtures/format3_bloque256.plaintext": "9ff2843e40bc1280dbfea8dce9386a42d06e8b43742c2cc6257540770cb53c73", "fixtures/format3_bloque256.plaintext": "9ff2843e40bc1280dbfea8dce9386a42d06e8b43742c2cc6257540770cb53c73",
"fixtures/format3_comment_only.dkc": "7f98a89413f08655bbbab28b96585dfa6173c1705dd81a900deba2100d19f2ef", "fixtures/format3_comment_only.dkc": "7f98a89413f08655bbbab28b96585dfa6173c1705dd81a900deba2100d19f2ef",
"fixtures/format3_comment_only.inspect.json": "fb56eca8bf42c8c47fde4a1d6b2580fcff386f2f58b566820731dce388542196", "fixtures/format3_comment_only.inspect.json": "fb56eca8bf42c8c47fde4a1d6b2580fcff386f2f58b566820731dce388542196",
"fixtures/format3_comment_only.json": "f016de795b7eedacdbe23233c45e70e68945eab831b6d558961d1250763be177", "fixtures/format3_comment_only.json": "42136f5029312236554a12569e9eca36b1ce5651d7db9e20ef3cb5fba4553234",
"fixtures/format3_comment_only.plaintext": "bc5b05885e608f036d8a14fde8738a8c53b395b71c3bcee99c1eab37ea23e80e", "fixtures/format3_comment_only.plaintext": "bc5b05885e608f036d8a14fde8738a8c53b395b71c3bcee99c1eab37ea23e80e",
"fixtures/format3_note.dkc": "da1bee54231252a0fd98439e24588125c5521f6e5a2c6641b499e6b22192c0eb", "fixtures/format3_note.dkc": "da1bee54231252a0fd98439e24588125c5521f6e5a2c6641b499e6b22192c0eb",
"fixtures/format3_note.inspect.json": "dcebb62407097c757bb62552be5d315155ba8a35dec175e95c3f6fddd6e81869", "fixtures/format3_note.inspect.json": "dcebb62407097c757bb62552be5d315155ba8a35dec175e95c3f6fddd6e81869",
"fixtures/format3_note.json": "8a4899a30e13190707c4505427e5a2bcdca50cd8e3b1642428a47052516f30fc", "fixtures/format3_note.json": "31eb7b8f64686e818ea9d621f9a1bba7b68c6781dee0919a66cd31e31f0eedec",
"fixtures/format3_note.plaintext": "0468737c5141be936f59d2823122e87661d4ae155a1df036b4cad1ea6620c17b", "fixtures/format3_note.plaintext": "0468737c5141be936f59d2823122e87661d4ae155a1df036b4cad1ea6620c17b",
"fixtures/format3_seal_unsupported.dkc": "ae3219fbdbd1de4cef6fade1a3fb3f6e5d5e2e8af54d9516b05f0a48136913ad", "fixtures/format3_seal_unsupported.dkc": "ae3219fbdbd1de4cef6fade1a3fb3f6e5d5e2e8af54d9516b05f0a48136913ad",
"fixtures/format3_seal_unsupported.inspect.json": "b3a7a1038192394c1f844fed994011646f3e78d1cf311c18cb5c936249b95f14", "fixtures/format3_seal_unsupported.inspect.json": "b3a7a1038192394c1f844fed994011646f3e78d1cf311c18cb5c936249b95f14",
"fixtures/format3_seal_unsupported.json": "c168a8aee59560d747b5a48ec34cd843ec6fd3eb588a2a41c5ffc5c84436f0ea", "fixtures/format3_seal_unsupported.json": "79d2204d7c769a54b98e3b023da6a241dadbee065142f29ffaab3fb9c0a549e8",
"fixtures/format3_seal_unsupported.plaintext": "0f865221d26545762712271faf835cb2e9980f8fb15c9d3b94fb6747cf16c1df", "fixtures/format3_seal_unsupported.plaintext": "0f865221d26545762712271faf835cb2e9980f8fb15c9d3b94fb6747cf16c1df",
"fixtures/format3_sealed.dkc": "dde5a072d8783227d28279d06d3d226a1fb967c766da626f889d1c6fd76ac9c7", "fixtures/format3_sealed.dkc": "dde5a072d8783227d28279d06d3d226a1fb967c766da626f889d1c6fd76ac9c7",
"fixtures/format3_sealed.inspect.json": "b984a0755332bad838025e47f8e917b9f18b9bb5c068c2d1ef0070db8e42849c", "fixtures/format3_sealed.inspect.json": "b984a0755332bad838025e47f8e917b9f18b9bb5c068c2d1ef0070db8e42849c",
"fixtures/format3_sealed.json": "453a142ef3e2b854e22a5c5f714b4199b614a73078e64d8bd19d4496d530476d", "fixtures/format3_sealed.json": "ffb93eff785a8bf045d3b6cbda0f8f25feb62337ccf90e7debb96fd1e9592e9f",
"fixtures/format3_sealed.plaintext": "aea0f5feb40acd81ca3b02dd21ea15510234da3ab52b374322f3206e7632d47b", "fixtures/format3_sealed.plaintext": "aea0f5feb40acd81ca3b02dd21ea15510234da3ab52b374322f3206e7632d47b",
"fixtures/format3_security_v2.dkc": "3d02b39ace010d74604554e378d22fe5ce00cecd998c0f797d657b17620b8912", "fixtures/format3_security_v2.dkc": "3d02b39ace010d74604554e378d22fe5ce00cecd998c0f797d657b17620b8912",
"fixtures/format3_security_v2.inspect.json": "dba4d21f1d4e228a17c761bae9a4b8c5a91cd9c0123e3141d3782a43c139321e", "fixtures/format3_security_v2.inspect.json": "dba4d21f1d4e228a17c761bae9a4b8c5a91cd9c0123e3141d3782a43c139321e",
"fixtures/format3_security_v2.json": "e09e265f7200713ccad07d1e45a7f4cbbd2aa8f47c7c13fc2b6ff1183cdce505", "fixtures/format3_security_v2.json": "72b980a6377ef0273ad2b82157851d37c9ba35da44b3bc6c75f13bf95ba6b3c7",
"fixtures/format3_security_v2.plaintext": "0c58ef40e4b1c7afde0f6e0a1f4ed7e3d45405757c5143a095f0c2b58042669f", "fixtures/format3_security_v2.plaintext": "0c58ef40e4b1c7afde0f6e0a1f4ed7e3d45405757c5143a095f0c2b58042669f",
"fixtures/format3_signature_unsupported.dkc": "e8e3106d8d73bb7b845062e0fe42af21df7d7cd8f63c335cab8dedb3e690df31", "fixtures/format3_signature_unsupported.dkc": "e8e3106d8d73bb7b845062e0fe42af21df7d7cd8f63c335cab8dedb3e690df31",
"fixtures/format3_signature_unsupported.inspect.json": "6db653db27604cb07e2cb2c23545fb68542c121e85002762f26c6d39e63bf00c", "fixtures/format3_signature_unsupported.inspect.json": "6db653db27604cb07e2cb2c23545fb68542c121e85002762f26c6d39e63bf00c",
"fixtures/format3_signature_unsupported.json": "33595f42dfa8f7136c627a7d8bef8378f251775437652db4dcd159e51bbe4ee4", "fixtures/format3_signature_unsupported.json": "44dacb87b9c170c5ed0b2d565cfb7542c1e1face2624f4c26a40bb4fcbe65810",
"fixtures/format3_signature_unsupported.plaintext": "9fe05e6b3a463371b33fc6a81b81d538e572789a8d03ace9f752a931f4ca4728", "fixtures/format3_signature_unsupported.plaintext": "9fe05e6b3a463371b33fc6a81b81d538e572789a8d03ace9f752a931f4ca4728",
"fixtures/format3_signed.dkc": "3c7d3c9e24c02853a0c7761b93bea1120b27fce396468d8d0f68e53aeb668c5e", "fixtures/format3_signed.dkc": "3c7d3c9e24c02853a0c7761b93bea1120b27fce396468d8d0f68e53aeb668c5e",
"fixtures/format3_signed.inspect.json": "7c37054d542869e766147350e2fa72695f209d39a03726757008e2c2291b0e97", "fixtures/format3_signed.inspect.json": "7c37054d542869e766147350e2fa72695f209d39a03726757008e2c2291b0e97",
"fixtures/format3_signed.json": "190db6be855915351271e1f6d6f3fcc352aee9f25e0485efe3d545b28880d458", "fixtures/format3_signed.json": "95e3161f90c84edb026c6d90c75e1f293646ac8bdfc73b03d76ce7ac6c2efaeb",
"fixtures/format3_signed.plaintext": "3de3ccab0ac74f95a76aa45c0f85e1749d4b4a051d87e81828eff6bf24372000", "fixtures/format3_signed.plaintext": "3de3ccab0ac74f95a76aa45c0f85e1749d4b4a051d87e81828eff6bf24372000",
"fixtures/format3_signed_cms.dkc": "d658f8d5ac2c5550c07b8f8fd6883b2f6dc02ceafc47d436ea02d8950b2548d2", "fixtures/format3_signed_cms.dkc": "d658f8d5ac2c5550c07b8f8fd6883b2f6dc02ceafc47d436ea02d8950b2548d2",
"fixtures/format3_signed_cms.inspect.json": "afadf530e8146687b25c03f26100ebff18e7f481e0ef09378816bad582270de5", "fixtures/format3_signed_cms.inspect.json": "afadf530e8146687b25c03f26100ebff18e7f481e0ef09378816bad582270de5",
"fixtures/format3_signed_cms.json": "2440f4b454cb465bfa33e9c37d151ca360b185218f092b6d1f95ec77c8428e95", "fixtures/format3_signed_cms.json": "8a6047ba60047462f41ebe2e52c5ab4c6e13c60cf0bebd478a5f1611d5e0b88a",
"fixtures/format3_signed_cms.plaintext": "31c35eeeee856277b605fe44203a8f4786bb8f591eda3b6ee58252df5b3cf2f0", "fixtures/format3_signed_cms.plaintext": "31c35eeeee856277b605fe44203a8f4786bb8f591eda3b6ee58252df5b3cf2f0",
"fixtures/format3_single.dkc": "9f68664af8733255084be9036a100b75d27bd16106bf0acff94ce469dd1d1743", "fixtures/format3_single.dkc": "9f68664af8733255084be9036a100b75d27bd16106bf0acff94ce469dd1d1743",
"fixtures/format3_single.inspect.json": "7878da921c17aada50e00d5911ea97e8558633a1684fb96acbd00d6f1b117529", "fixtures/format3_single.inspect.json": "7878da921c17aada50e00d5911ea97e8558633a1684fb96acbd00d6f1b117529",
"fixtures/format3_single.json": "08f9cdf0a8327fb65a45c78aeca5d3817d4da367145d9042a20efdefb761d637", "fixtures/format3_single.json": "45a497461b8128f0ec89cea43171b370cc5025592860c9f3fdd732a0000e7c0d",
"fixtures/format3_single.plaintext": "74f9dd84d07e95a31e6dc063bf65ce414197acf84aac445eabc76fa4e3f24936", "fixtures/format3_single.plaintext": "74f9dd84d07e95a31e6dc063bf65ce414197acf84aac445eabc76fa4e3f24936",
"fixtures/format3_time_and_key_portable.dkc": "680d29962e575689a31543df28433dae7737abd9a793e9cae92ef40920d09636", "fixtures/format3_time_and_key_portable.dkc": "680d29962e575689a31543df28433dae7737abd9a793e9cae92ef40920d09636",
"fixtures/format3_time_and_key_portable.dkk": "54cc64d849395234b3e093e47f432b72781ccc13f455c9ef394e3554ab566751", "fixtures/format3_time_and_key_portable.dkk": "54cc64d849395234b3e093e47f432b72781ccc13f455c9ef394e3554ab566751",
"fixtures/format3_time_and_key_portable.dkk.json": "20d88fce67d30d7f362085f9dd576d46a249d87ad8d56cf66456d22295c66ce8", "fixtures/format3_time_and_key_portable.dkk.json": "388e05ce647fc9399fc5ce4fcb5478320ec340013135b0fc7eb8c5b238015466",
"fixtures/format3_time_and_key_portable.inspect.json": "f269af86f5bf84c22a1038fd78db146af93166150755eb1ca35cf15e224035b4", "fixtures/format3_time_and_key_portable.inspect.json": "f269af86f5bf84c22a1038fd78db146af93166150755eb1ca35cf15e224035b4",
"fixtures/format3_time_and_key_portable.json": "dc2b1b283700bb5806692d25d27bde4f6c7954935182791df527d96bdb216ffb", "fixtures/format3_time_and_key_portable.json": "6b2831efeec32d2a92301acfa20e74446bcdc7f446d0b9cde1d5d87fd5c6d4b5",
"fixtures/format3_time_and_key_portable.plaintext": "e6684cf607c102bfa4d6977742d5a7520b0e09483282181bd6d8f5f4ba5f7726", "fixtures/format3_time_and_key_portable.plaintext": "e6684cf607c102bfa4d6977742d5a7520b0e09483282181bd6d8f5f4ba5f7726",
"fixtures/format3_tree.dkc": "217f378faaf795f6a9c416b564fb8931bb2e896918aee870120fd14f9a5da7d1", "fixtures/format3_tree.dkc": "217f378faaf795f6a9c416b564fb8931bb2e896918aee870120fd14f9a5da7d1",
"fixtures/format3_tree.inspect.json": "643a9dfdc2d0c44b8a1636909c66ed81bfd8c50df2a4cad6566832a8e47ba938", "fixtures/format3_tree.inspect.json": "643a9dfdc2d0c44b8a1636909c66ed81bfd8c50df2a4cad6566832a8e47ba938",
"fixtures/format3_tree.json": "0883c4468b75c520f9b060e54611198f03f16537eca0a1eaff6aefbba54b2199", "fixtures/format3_tree.json": "93a0880b55fedff0e66167c71b89ee7ae595b033fbcab7484233025e5ac42eaa",
"fixtures/format3_tree.plaintext": "f69ac5f450966f7d0e9161aa37451d4260b194a750e3e132c02e8a15ba561cfa", "fixtures/format3_tree.plaintext": "f69ac5f450966f7d0e9161aa37451d4260b194a750e3e132c02e8a15ba561cfa",
"fixtures/format3_unsigned.dkc": "317ab722ae3812a25ddd78b4c98c586363e5587c8d3634c881ce7c421af19168", "fixtures/format3_unsigned.dkc": "317ab722ae3812a25ddd78b4c98c586363e5587c8d3634c881ce7c421af19168",
"fixtures/format3_unsigned.inspect.json": "2f52f7286d6bd4c846ddd63b10b4989b25d17501a989a2e9deb25e4db0859e1a", "fixtures/format3_unsigned.inspect.json": "2f52f7286d6bd4c846ddd63b10b4989b25d17501a989a2e9deb25e4db0859e1a",
"fixtures/format3_unsigned.json": "5d1313ec6f0f6a498dfc78e13735be3e90a004f102338082227058278d63247a", "fixtures/format3_unsigned.json": "6098828d2be7d2f5db4b7535895274136f4ad404dddaf8fe70cd855934412da4",
"fixtures/format3_unsigned.plaintext": "25527e5e2e1ce02056d4419fb89f7b0ce35e4920f93217f58dcf62a4377f8af5", "fixtures/format3_unsigned.plaintext": "25527e5e2e1ce02056d4419fb89f7b0ce35e4920f93217f58dcf62a4377f8af5",
"fixtures/time_and_key_portable.dkc": "2e97878078bae6358037a9c264f379a3cbe839f767d69836b0343f35657b2972", "fixtures/time_and_key_portable.dkc": "2e97878078bae6358037a9c264f379a3cbe839f767d69836b0343f35657b2972",
"fixtures/time_and_key_portable.dkk": "e528fa2c832c91119f0684bb9d6fb3c4c2d0d55183482890e7c4fe92f668426a", "fixtures/time_and_key_portable.dkk": "e528fa2c832c91119f0684bb9d6fb3c4c2d0d55183482890e7c4fe92f668426a",
"fixtures/time_and_key_portable.dkk.json": "2102ce0cde9784249a0045b1e7a1526b62ef73d30fd543fa15d45dcd5187d4d8", "fixtures/time_and_key_portable.dkk.json": "fd98c997a7684e9a350c489bf6d0ff9e24e38ab8c1665cc203fa31a29fb47e6a",
"fixtures/time_and_key_portable.inspect.json": "238c1f8ca6a6bf69f20bf26f5676e89a0b07e83b4362628560fc2f7522a202c9", "fixtures/time_and_key_portable.inspect.json": "238c1f8ca6a6bf69f20bf26f5676e89a0b07e83b4362628560fc2f7522a202c9",
"fixtures/time_and_key_portable.json": "23390143f6eaa92fea1af9d0acbad21a4c0c325b78e18d9720326bbf07755665", "fixtures/time_and_key_portable.json": "45a91d8ad99a5e1265de29af4130d0c1a7c3a0a7e6caeda7f758e6372c7e4c0f",
"fixtures/time_and_key_portable.plaintext": "937492203d207d6fe36161b8696bf1f05b8b4cc56d855c44853f4b76aad3a05b", "fixtures/time_and_key_portable.plaintext": "937492203d207d6fe36161b8696bf1f05b8b4cc56d855c44853f4b76aad3a05b",
"fixtures/time_and_key_portable_extension.dkk": "0bf463a7c65627b7dda2234d728df89ec5b835816a2a37b91497d8fecc5ea548", "fixtures/time_and_key_portable_extension.dkk": "0bf463a7c65627b7dda2234d728df89ec5b835816a2a37b91497d8fecc5ea548",
"fixtures/time_and_key_portable_extension.dkk.json": "dc4036242ecdbd91f28ba4b2bd0e14be5c770bb4d42679fbf5c1ea64d8e3bf8a", "fixtures/time_and_key_portable_extension.dkk.json": "5ca66340a242c4165f1febb0400dc52f0f47011e7befa8fa6c3b2c144bb6d3c0",
"fixtures/time_and_key_recipients.dkc": "69ac110380f5d768b5b6afaa157a50ed17d8ceccfbd4604ffa5b6da38539b635", "fixtures/time_and_key_recipients.dkc": "69ac110380f5d768b5b6afaa157a50ed17d8ceccfbd4604ffa5b6da38539b635",
"fixtures/time_and_key_recipients.dkk": "19f6c47150c3194712d454f43c7392b7344e6b4e7b074d83e9ca5f563a8e072f", "fixtures/time_and_key_recipients.dkk": "19f6c47150c3194712d454f43c7392b7344e6b4e7b074d83e9ca5f563a8e072f",
"fixtures/time_and_key_recipients.dkk.json": "9b4265de639e223d99f47d05806d8d4d89d223910a69a10e6958f0e969edc0bb", "fixtures/time_and_key_recipients.dkk.json": "c9e1a2f63b8e2218026e5a2591f7acf8b42c3803f837c38ce6dc878d3450d40a",
"fixtures/time_and_key_recipients.inspect.json": "4b32c63d18febe0772837fbcd75a0c971e31378bf799201b720a9d32bdcd8c2b", "fixtures/time_and_key_recipients.inspect.json": "4b32c63d18febe0772837fbcd75a0c971e31378bf799201b720a9d32bdcd8c2b",
"fixtures/time_and_key_recipients.json": "7e64517b3016b3e3c17fde6923fa88a2046d6ef6afe597ff311668c4e41d7675", "fixtures/time_and_key_recipients.json": "db62a8647a1bfe098b05a7fe9f723f40da399d696c2bcd4a65547f7458670350",
"fixtures/time_and_key_recipients.plaintext": "0e9fd50e98a85953aa9cf07a11ee3c62bb3d7622f344f1c6ce744d1ed111659f", "fixtures/time_and_key_recipients.plaintext": "0e9fd50e98a85953aa9cf07a11ee3c62bb3d7622f344f1c6ce744d1ed111659f",
"fixtures/time_only.dkc": "99e915810d595f1092700b728f5e5081d78efe83f5343e76325b1bcc2c33ccf2", "fixtures/time_only.dkc": "99e915810d595f1092700b728f5e5081d78efe83f5343e76325b1bcc2c33ccf2",
"fixtures/time_only.inspect.json": "a4d45f945d6ba6616c01e120ac1133785e5279fea7dcab706b5feee287be8884", "fixtures/time_only.inspect.json": "a4d45f945d6ba6616c01e120ac1133785e5279fea7dcab706b5feee287be8884",
"fixtures/time_only.json": "b26e92ce9fd1e91f0141ca609bb2bfb46aec1185ed2eabf26ffd4ca7df3edd5c", "fixtures/time_only.json": "c7920af7a8afd5873e95363d1b2411715355263dcb6f87c11d3b4102f200fc1b",
"fixtures/time_only.plaintext": "53b8ee821fb7b678e89d4f93da1812339f6cc1ab83aac6ed1432db99df784be5", "fixtures/time_only.plaintext": "53b8ee821fb7b678e89d4f93da1812339f6cc1ab83aac6ed1432db99df784be5",
"fixtures/time_only_extensions.dkc": "0446c9b73e267adcb24e5cc89afba2544a386ec9a050016e06517a4a57aa2085", "fixtures/time_only_extensions.dkc": "0446c9b73e267adcb24e5cc89afba2544a386ec9a050016e06517a4a57aa2085",
"fixtures/time_only_extensions.inspect.json": "6f957b028da8a4a495b5e951ced0b91e0678128dac4e962b02d024b9439a0ba1", "fixtures/time_only_extensions.inspect.json": "6f957b028da8a4a495b5e951ced0b91e0678128dac4e962b02d024b9439a0ba1",
"fixtures/time_only_extensions.json": "ec60ac193847a083d41835c7f1d198d721adf864df6b33527c7837bd19c6efac", "fixtures/time_only_extensions.json": "29eea35b3a3e157c6af442358058d71e5e947ad1cc7bd29b72a86c3c4d2f677b",
"fixtures/time_only_extensions.plaintext": "1129768e195e2f1e50b7a6f926b6eebef120212c29b5642c8a662c503b2a9131", "fixtures/time_only_extensions.plaintext": "1129768e195e2f1e50b7a6f926b6eebef120212c29b5642c8a662c503b2a9131",
"vectors/cbor.json": "3001074166fae65e4ebad48c0e126823102e21bc9ca51e89ebc1c30ed6f52b30", "vectors/cbor.json": "b209674a9967657f9ea33ca0cc9d63e185c0007f192bfc6af182d7e97923d646",
"vectors/dk1.json": "62b6af3aa9145cf6a35e2351de008625d1c14405cec4aeb2926d4097e4dd10b3", "vectors/dk1.json": "d403ff60a5e1ecb9d21950ff4111e496462b367a08b536e3167952e245acb478",
"vectors/ed25519_strict.json": "ad436026fe5503fcccd0b2ffb213f2fd29092aa76f932c99662314302a036d8e", "vectors/ed25519_strict.json": "daa4022006b0d8c1b6728c74b1abdc5c700979d5e9b5ea7e3966dae45c81c687",
"vectors/head_schema.json": "fb9b8c1b9a8c481ee1253efe70d70e80c78e0431721413ec806a0ce20ce740c9", "vectors/head_schema.json": "995a81cf9497a13fae8e22d04f405d4bc7daf5c48023085677ecd0cd8984adcb",
"vectors/inspect_differential.json": "e994f1865b197eca6d04c10257af757134ec967566bb55909501a9a20e489275", "vectors/inspect_differential.json": "97d9f0f47fb30d16373c52242e5ffa364256ff728177e5dce2fa9d532ba116d7",
"vectors/locator.json": "a6320549f06f9100e26ea2b7be87e9f8ea45ec582409656f1fbeaf31ad6c28a3", "vectors/locator.json": "38f72731dd74db59253950c820316eed19281b9c63a23817d501dea3fbbd6ba9",
"vectors/mutations.json": "f823323312fa3204c487d8fef1e7ecd13ef22b7f30783171a1723a306dc31257", "vectors/mutations.json": "76d8d572ce5743ff56242d45d507124a1309d5871a701095c0e2cbcadd3bdfee",
"vectors/note.json": "c82ab92ba73e7721e897b2fd6259bbf33fbe4927eb2be409e5d7dbd00c495c0b", "vectors/note.json": "a0e44b493d5d7c7548d727b79122dad0151c1598b0db6a358844e8b193635223",
"vectors/padding.json": "502de972f6015e32be1dfa84957bf0df203dfcb3c6662d4eedbdd594a9d51573", "vectors/padding.json": "3555875043cc2961af43fbdb0b26eb198ce7822547d6d909b8e327511c732ed5",
"vectors/path_fold.json": "c7e329e12052c0c23f9ce4cec6cfbfd1c6025e9a4f3d357d121a56d2aba16765", "vectors/path_fold.json": "bd5db6c03d4ed4920c5da084ec0b8cfc584f6ace387b123c589c17449cb43896",
"vectors/paths.json": "485ffcef29f826da01d90ef7789b6791f1f8709958be72653e3bdffabd0c690b", "vectors/paths.json": "50bdc57d6650143478e5f58421a6adf7511deacc35e3fc1d49d6b0f37d792fb9",
"vectors/profile_quicknet.json": "6e6d0087d332f5fa27ccf8961b5ae225d123b137754deba2b6815c5a17f958c8", "vectors/profile_quicknet.json": "623d920e712e0b4eafdf85d4e3d363d81c33427c484964c4e12e5f695982b28f",
"vectors/quicknet_rounds.json": "8fbcdfea66ec31ffec38934c3d595e19d274682c20fe42dfe36d98350e2dd744", "vectors/quicknet_rounds.json": "beb38f35cda20be4b5dc17efeccd3ec82d676624a2b1f4030d2a317b618ce038",
"vectors/resolved_ip.json": "7b7752d94a79d9255d951f85ded9aff799ea211e51a5f503d6d56328e28e3b1b", "vectors/resolved_ip.json": "01c676cbdb815a3b0b0a2416f392a4b855f238f9378f3bf7efeae4a25ce50cdb",
"vectors/security.json": "df141a266eb56e8d68521fce58fe8a7f45522273d01137e66f8d4bb07a80cb80", "vectors/security.json": "7eb7dbce804c62ca8cc3f080ea192b2a7b717b5d4716d2d061dd06855d0818e6",
"vectors/security_cms.json": "cc0e192995b66a643530905e6e85f35bb74976e9fbdbbd3bafc1629f365d8950", "vectors/security_cms.json": "139d9bf130f3932aa73cfe68f8d7ce7f728b2467b857732ff5404dd4b4e242d4",
"vectors/tlock_ibe.json": "271a15461d3c7840cc29500ec95dd27360868645d933ecfd2c449ad6c3423866", "vectors/tlock_ibe.json": "37c07ec4f1806dfdbbcc5fe2b1c53a92695c6ba8702a6e9c1e7010d58ae936d9",
"vectors/wordkey.json": "88c1d13e08240192cbba117de96a61f725262b898ebdfddb298e52b11bfd536f" "vectors/tlock_steps.json": "d43ee8b71661803d21988266bf3fe00f3a36b41c74ebc1675b383f1323a87af1",
"vectors/wordkey.json": "c5241f306de01b1ae3437b8dfec7b2b117d1f305ebecae71c36d0957ff987e53"
} }
} }

@ -1,6 +1,6 @@
{ {
"description": "time_only capsule with an empty payload", "description": "time_only capsule with an empty payload",
"spec": "0.13", "spec": "0.14",
"format": 1, "format": 1,
"file": "empty_payload.dkc", "file": "empty_payload.dkc",
"sha256": "871e9bf05b52bbae17f3adfbbf97b46e7f0e53aa8f57bcaa506e43f36f53a9d4", "sha256": "871e9bf05b52bbae17f3adfbbf97b46e7f0e53aa8f57bcaa506e43f36f53a9d4",

@ -1,6 +1,6 @@
{ {
"description": "format 2 time_only capsule with an empty content: L = 0, P = 256", "description": "format 2 time_only capsule with an empty content: L = 0, P = 256",
"spec": "0.13", "spec": "0.14",
"format": 2, "format": 2,
"file": "format2_empty_payload.dkc", "file": "format2_empty_payload.dkc",
"sha256": "7aea2b5aa48b1a46053716f733d50fab9cd0b80b1be67631bcc06c5bb765dc21", "sha256": "7aea2b5aa48b1a46053716f733d50fab9cd0b80b1be67631bcc06c5bb765dc21",

@ -1,6 +1,6 @@
{ {
"description": "portable X25519 .dkk of format2_time_and_key_portable.dkc", "description": "portable X25519 .dkk of format2_time_and_key_portable.dkc",
"spec": "0.13", "spec": "0.14",
"file": "format2_time_and_key_portable.dkk", "file": "format2_time_and_key_portable.dkk",
"sha256": "095b7bc516a22bf0c2366f0af3cd48bfe857a2354d6e2a9b285278b95e450fe0", "sha256": "095b7bc516a22bf0c2366f0af3cd48bfe857a2354d6e2a9b285278b95e450fe0",
"credential_id": "e3c7be83cbf1fbd6b115c96411b3bd01", "credential_id": "e3c7be83cbf1fbd6b115c96411b3bd01",

@ -1,6 +1,6 @@
{ {
"description": "format 2 time_and_key capsule with one credential, a portable .dkk, and 15 dummies", "description": "format 2 time_and_key capsule with one credential, a portable .dkk, and 15 dummies",
"spec": "0.13", "spec": "0.14",
"format": 2, "format": 2,
"file": "format2_time_and_key_portable.dkc", "file": "format2_time_and_key_portable.dkc",
"sha256": "600892659fe4890223e895876275f656995d170fda42b07fb2bec0ca51ce4b43", "sha256": "600892659fe4890223e895876275f656995d170fda42b07fb2bec0ca51ce4b43",

@ -1,6 +1,6 @@
{ {
"description": "portable X25519 .dkk of format2_time_and_key_recipients.dkc", "description": "portable X25519 .dkk of format2_time_and_key_recipients.dkc",
"spec": "0.13", "spec": "0.14",
"file": "format2_time_and_key_recipients.dkk", "file": "format2_time_and_key_recipients.dkk",
"sha256": "2ad99b1556086ec311d7f0b3bd3aaba05e75f45c4fa22490b0d5e8bb0b1a222e", "sha256": "2ad99b1556086ec311d7f0b3bd3aaba05e75f45c4fa22490b0d5e8bb0b1a222e",
"credential_id": "93cedf68421710e83908ec683b104436", "credential_id": "93cedf68421710e83908ec683b104436",

@ -1,6 +1,6 @@
{ {
"description": "format 2 time_and_key capsule for three known X25519 recipients and a portable .dkk, and 12 dummies", "description": "format 2 time_and_key capsule for three known X25519 recipients and a portable .dkk, and 12 dummies",
"spec": "0.13", "spec": "0.14",
"format": 2, "format": 2,
"file": "format2_time_and_key_recipients.dkc", "file": "format2_time_and_key_recipients.dkc",
"sha256": "1a44fd8708c92e2e0a10cfcb1d864a71331ea9af25d97e1a42e969dc898959e3", "sha256": "1a44fd8708c92e2e0a10cfcb1d864a71331ea9af25d97e1a42e969dc898959e3",

@ -1,6 +1,6 @@
{ {
"description": "format 2 time_and_key capsule for sixteen known X25519 recipients, without dummies", "description": "format 2 time_and_key capsule for sixteen known X25519 recipients, without dummies",
"spec": "0.13", "spec": "0.14",
"format": 2, "format": 2,
"file": "format2_time_and_key_sixteen.dkc", "file": "format2_time_and_key_sixteen.dkc",
"sha256": "7aaac5c18f216bf53df326ecc817179640a53408cf25dfd50488910a762dc381", "sha256": "7aaac5c18f216bf53df326ecc817179640a53408cf25dfd50488910a762dc381",

@ -1,6 +1,6 @@
{ {
"description": "format 2 time_only capsule, padding code 2 (reforzado): L = 78000, P = 79872, two STREAM chunks", "description": "format 2 time_only capsule, padding code 2 (reforzado): L = 78000, P = 79872, two STREAM chunks",
"spec": "0.13", "spec": "0.14",
"format": 2, "format": 2,
"file": "format2_time_only.dkc", "file": "format2_time_only.dkc",
"sha256": "f5a40ac6b8a08a0c12db6114c2bca23522d6a77b512b509a217fb15f367813c4", "sha256": "f5a40ac6b8a08a0c12db6114c2bca23522d6a77b512b509a217fb15f367813c4",

@ -1,6 +1,6 @@
{ {
"description": "format 2 time_only capsule with the content of format2_time_only and padding code 1 (bloque256): L = 78000, P = 78080", "description": "format 2 time_only capsule with the content of format2_time_only and padding code 1 (bloque256): L = 78000, P = 78080",
"spec": "0.13", "spec": "0.14",
"format": 2, "format": 2,
"file": "format2_time_only_bloque256.dkc", "file": "format2_time_only_bloque256.dkc",
"sha256": "aae769c30d04920801d8b293d30864fbe223c9c9353ec2b4907a1ee1996e39f9", "sha256": "aae769c30d04920801d8b293d30864fbe223c9c9353ec2b4907a1ee1996e39f9",

@ -1,6 +1,6 @@
{ {
"description": "format 2 time_only capsule with a noncritical PUBLIC_HEADER extension and a noncritical CONTROL_CBOR extension", "description": "format 2 time_only capsule with a noncritical PUBLIC_HEADER extension and a noncritical CONTROL_CBOR extension",
"spec": "0.13", "spec": "0.14",
"format": 2, "format": 2,
"file": "format2_time_only_extensions.dkc", "file": "format2_time_only_extensions.dkc",
"sha256": "fb406100d5703a2e888983b3175ed34a09a34469cc722256e5cf535dd728fbe9", "sha256": "fb406100d5703a2e888983b3175ed34a09a34469cc722256e5cf535dd728fbe9",

@ -1,6 +1,6 @@
{ {
"description": "format 3 time_only capsule with a security area of 1024 bytes, as a later version may write it, holding the empty security", "description": "format 3 time_only capsule with a security area of 1024 bytes, as a later version may write it, holding the empty security",
"spec": "0.13", "spec": "0.14",
"format": 3, "format": 3,
"file": "format3_area_1024.dkc", "file": "format3_area_1024.dkc",
"sha256": "41ea2eed0293e4fef7f4a307b7f16aaf1339f5bf6f4ded7a6a9ae1aebeb0133c", "sha256": "41ea2eed0293e4fef7f4a307b7f16aaf1339f5bf6f4ded7a6a9ae1aebeb0133c",

@ -1,6 +1,6 @@
{ {
"description": "format 3 time_only capsule with padding code 1 (bloque256) and one file of 20000 bytes", "description": "format 3 time_only capsule with padding code 1 (bloque256) and one file of 20000 bytes",
"spec": "0.13", "spec": "0.14",
"format": 3, "format": 3,
"file": "format3_bloque256.dkc", "file": "format3_bloque256.dkc",
"sha256": "ff18444f434164ba8e7b26d38c76c7855dc6b0593b2fc8b4e9a95dbf9252d55d", "sha256": "ff18444f434164ba8e7b26d38c76c7855dc6b0593b2fc8b4e9a95dbf9252d55d",

@ -1,6 +1,6 @@
{ {
"description": "format 3 time_only capsule with a comment of two lines, the second one with a TAB, a declared author and no files", "description": "format 3 time_only capsule with a comment of two lines, the second one with a TAB, a declared author and no files",
"spec": "0.13", "spec": "0.14",
"format": 3, "format": 3,
"file": "format3_comment_only.dkc", "file": "format3_comment_only.dkc",
"sha256": "7f98a89413f08655bbbab28b96585dfa6173c1705dd81a900deba2100d19f2ef", "sha256": "7f98a89413f08655bbbab28b96585dfa6173c1705dd81a900deba2100d19f2ef",

@ -1,6 +1,6 @@
{ {
"description": "format 3 time_only capsule with a single file, nota.txt, and the public note «Cartas del viaje a Lisboa» in the noncritical array of PUBLIC_HEADER (spec v0.11, §24.1)", "description": "format 3 time_only capsule with a single file, nota.txt, and the public note «Cartas del viaje a Lisboa» in the noncritical array of PUBLIC_HEADER (spec v0.11, §24.1)",
"spec": "0.13", "spec": "0.14",
"format": 3, "format": 3,
"file": "format3_note.dkc", "file": "format3_note.dkc",
"sha256": "da1bee54231252a0fd98439e24588125c5521f6e5a2c6641b499e6b22192c0eb", "sha256": "da1bee54231252a0fd98439e24588125c5521f6e5a2c6641b499e6b22192c0eb",

@ -1,6 +1,6 @@
{ {
"description": "format 3 time_only capsule with an author-signature of alg 4294967295, as in format3_signature_unsupported, and a seal of seal_type 4294967295, reserved for tests, with a random token of 32 bytes: verdicts F1 and S1", "description": "format 3 time_only capsule with an author-signature of alg 4294967295, as in format3_signature_unsupported, and a seal of seal_type 4294967295, reserved for tests, with a random token of 32 bytes: verdicts F1 and S1",
"spec": "0.13", "spec": "0.14",
"format": 3, "format": 3,
"file": "format3_seal_unsupported.dkc", "file": "format3_seal_unsupported.dkc",
"sha256": "ae3219fbdbd1de4cef6fade1a3fb3f6e5d5e2e8af54d9516b05f0a48136913ad", "sha256": "ae3219fbdbd1de4cef6fade1a3fb3f6e5d5e2e8af54d9516b05f0a48136913ad",

@ -1,6 +1,6 @@
{ {
"description": "format 3 time_only capsule with a single file, nota.txt, signed with alg 1 by the test key of format3_signed and sealed with seal_type 2 by a test time-stamping authority before the round time: verdicts F4 and S4, with SEAL_SUBJECT and the token in the record", "description": "format 3 time_only capsule with a single file, nota.txt, signed with alg 1 by the test key of format3_signed and sealed with seal_type 2 by a test time-stamping authority before the round time: verdicts F4 and S4, with SEAL_SUBJECT and the token in the record",
"spec": "0.13", "spec": "0.14",
"format": 3, "format": 3,
"file": "format3_sealed.dkc", "file": "format3_sealed.dkc",
"sha256": "dde5a072d8783227d28279d06d3d226a1fb967c766da626f889d1c6fd76ac9c7", "sha256": "dde5a072d8783227d28279d06d3d226a1fb967c766da626f889d1c6fd76ac9c7",

@ -1,6 +1,6 @@
{ {
"description": "format 3 time_only capsule whose security is of version 2: verdict X", "description": "format 3 time_only capsule whose security is of version 2: verdict X",
"spec": "0.13", "spec": "0.14",
"format": 3, "format": 3,
"file": "format3_security_v2.dkc", "file": "format3_security_v2.dkc",
"sha256": "3d02b39ace010d74604554e378d22fe5ce00cecd998c0f797d657b17620b8912", "sha256": "3d02b39ace010d74604554e378d22fe5ce00cecd998c0f797d657b17620b8912",

@ -1,6 +1,6 @@
{ {
"description": "format 3 time_only capsule with an author-signature of alg 4294967295, a random key of 32 bytes and a random signature of 64: verdicts F1 and S0", "description": "format 3 time_only capsule with an author-signature of alg 4294967295, a random key of 32 bytes and a random signature of 64: verdicts F1 and S0",
"spec": "0.13", "spec": "0.14",
"format": 3, "format": 3,
"file": "format3_signature_unsupported.dkc", "file": "format3_signature_unsupported.dkc",
"sha256": "e8e3106d8d73bb7b845062e0fe42af21df7d7cd8f63c335cab8dedb3e690df31", "sha256": "e8e3106d8d73bb7b845062e0fe42af21df7d7cd8f63c335cab8dedb3e690df31",

@ -1,6 +1,6 @@
{ {
"description": "format 3 time_only capsule with a single file, nota.txt, signed with alg 1 by a test key whose seed the record gives: verdict F4, and the commitments and the message of the signature", "description": "format 3 time_only capsule with a single file, nota.txt, signed with alg 1 by a test key whose seed the record gives: verdict F4, and the commitments and the message of the signature",
"spec": "0.13", "spec": "0.14",
"format": 3, "format": 3,
"file": "format3_signed.dkc", "file": "format3_signed.dkc",
"sha256": "3c7d3c9e24c02853a0c7761b93bea1120b27fce396468d8d0f68e53aeb668c5e", "sha256": "3c7d3c9e24c02853a0c7761b93bea1120b27fce396468d8d0f68e53aeb668c5e",

@ -1,6 +1,6 @@
{ {
"description": "format 3 time_only capsule with a single file, nota.txt, signed with alg 2 by two test certificates, an ECDSA P-256 one and an RSA 2048 one, each sealed by a test time-stamping authority before the round time: verdict F6, with the certificates, the commitments, SIGNERS and the result of each signer in the record", "description": "format 3 time_only capsule with a single file, nota.txt, signed with alg 2 by two test certificates, an ECDSA P-256 one and an RSA 2048 one, each sealed by a test time-stamping authority before the round time: verdict F6, with the certificates, the commitments, SIGNERS and the result of each signer in the record",
"spec": "0.13", "spec": "0.14",
"format": 3, "format": 3,
"file": "format3_signed_cms.dkc", "file": "format3_signed_cms.dkc",
"sha256": "d658f8d5ac2c5550c07b8f8fd6883b2f6dc02ceafc47d436ea02d8950b2548d2", "sha256": "d658f8d5ac2c5550c07b8f8fd6883b2f6dc02ceafc47d436ea02d8950b2548d2",

@ -1,6 +1,6 @@
{ {
"description": "format 3 time_only capsule with a single file, nota.txt, with its mtime", "description": "format 3 time_only capsule with a single file, nota.txt, with its mtime",
"spec": "0.13", "spec": "0.14",
"format": 3, "format": 3,
"file": "format3_single.dkc", "file": "format3_single.dkc",
"sha256": "9f68664af8733255084be9036a100b75d27bd16106bf0acff94ce469dd1d1743", "sha256": "9f68664af8733255084be9036a100b75d27bd16106bf0acff94ce469dd1d1743",

@ -1,6 +1,6 @@
{ {
"description": "portable X25519 .dkk of format3_time_and_key_portable.dkc", "description": "portable X25519 .dkk of format3_time_and_key_portable.dkc",
"spec": "0.13", "spec": "0.14",
"file": "format3_time_and_key_portable.dkk", "file": "format3_time_and_key_portable.dkk",
"sha256": "54cc64d849395234b3e093e47f432b72781ccc13f455c9ef394e3554ab566751", "sha256": "54cc64d849395234b3e093e47f432b72781ccc13f455c9ef394e3554ab566751",
"credential_id": "bdb483fba42daf0b409f44d23033f362", "credential_id": "bdb483fba42daf0b409f44d23033f362",

@ -1,6 +1,6 @@
{ {
"description": "format 3 time_and_key capsule with one credential, a portable .dkk, and 15 dummies", "description": "format 3 time_and_key capsule with one credential, a portable .dkk, and 15 dummies",
"spec": "0.13", "spec": "0.14",
"format": 3, "format": 3,
"file": "format3_time_and_key_portable.dkc", "file": "format3_time_and_key_portable.dkc",
"sha256": "680d29962e575689a31543df28433dae7737abd9a793e9cae92ef40920d09636", "sha256": "680d29962e575689a31543df28433dae7737abd9a793e9cae92ef40920d09636",

@ -1,6 +1,6 @@
{ {
"description": "format 3 time_only capsule with five files in three folders, one of them over two STREAM chunks and one without mtime, a comment of two lines and a declared author", "description": "format 3 time_only capsule with five files in three folders, one of them over two STREAM chunks and one without mtime, a comment of two lines and a declared author",
"spec": "0.13", "spec": "0.14",
"format": 3, "format": 3,
"file": "format3_tree.dkc", "file": "format3_tree.dkc",
"sha256": "217f378faaf795f6a9c416b564fb8931bb2e896918aee870120fd14f9a5da7d1", "sha256": "217f378faaf795f6a9c416b564fb8931bb2e896918aee870120fd14f9a5da7d1",

@ -1,6 +1,6 @@
{ {
"description": "format 3 time_only capsule with a single file, nota.txt, as format3_signed, without a signature: the area of 32 KiB of spec v0.11 holds the empty security, and P is the one of format3_signed", "description": "format 3 time_only capsule with a single file, nota.txt, as format3_signed, without a signature: the area of 32 KiB of spec v0.11 holds the empty security, and P is the one of format3_signed",
"spec": "0.13", "spec": "0.14",
"format": 3, "format": 3,
"file": "format3_unsigned.dkc", "file": "format3_unsigned.dkc",
"sha256": "317ab722ae3812a25ddd78b4c98c586363e5587c8d3634c881ce7c421af19168", "sha256": "317ab722ae3812a25ddd78b4c98c586363e5587c8d3634c881ce7c421af19168",

@ -1,6 +1,6 @@
{ {
"description": "portable X25519 .dkk of time_and_key_portable.dkc", "description": "portable X25519 .dkk of time_and_key_portable.dkc",
"spec": "0.13", "spec": "0.14",
"file": "time_and_key_portable.dkk", "file": "time_and_key_portable.dkk",
"sha256": "e528fa2c832c91119f0684bb9d6fb3c4c2d0d55183482890e7c4fe92f668426a", "sha256": "e528fa2c832c91119f0684bb9d6fb3c4c2d0d55183482890e7c4fe92f668426a",
"credential_id": "3955e944a3c60cfa1fd6485e9693c77d", "credential_id": "3955e944a3c60cfa1fd6485e9693c77d",

@ -1,6 +1,6 @@
{ {
"description": "time_and_key capsule whose only recipient is a portable .dkk", "description": "time_and_key capsule whose only recipient is a portable .dkk",
"spec": "0.13", "spec": "0.14",
"format": 1, "format": 1,
"file": "time_and_key_portable.dkc", "file": "time_and_key_portable.dkc",
"sha256": "2e97878078bae6358037a9c264f379a3cbe839f767d69836b0343f35657b2972", "sha256": "2e97878078bae6358037a9c264f379a3cbe839f767d69836b0343f35657b2972",

@ -1,6 +1,6 @@
{ {
"description": "portable X25519 .dkk of time_and_key_portable.dkc with a noncritical extension: the credential of time_and_key_portable.dkk re-issued with org.example.delivery", "description": "portable X25519 .dkk of time_and_key_portable.dkc with a noncritical extension: the credential of time_and_key_portable.dkk re-issued with org.example.delivery",
"spec": "0.13", "spec": "0.14",
"file": "time_and_key_portable_extension.dkk", "file": "time_and_key_portable_extension.dkk",
"sha256": "0bf463a7c65627b7dda2234d728df89ec5b835816a2a37b91497d8fecc5ea548", "sha256": "0bf463a7c65627b7dda2234d728df89ec5b835816a2a37b91497d8fecc5ea548",
"credential_id": "3955e944a3c60cfa1fd6485e9693c77d", "credential_id": "3955e944a3c60cfa1fd6485e9693c77d",

@ -1,6 +1,6 @@
{ {
"description": "portable X25519 .dkk of time_and_key_recipients.dkc", "description": "portable X25519 .dkk of time_and_key_recipients.dkc",
"spec": "0.13", "spec": "0.14",
"file": "time_and_key_recipients.dkk", "file": "time_and_key_recipients.dkk",
"sha256": "19f6c47150c3194712d454f43c7392b7344e6b4e7b074d83e9ca5f563a8e072f", "sha256": "19f6c47150c3194712d454f43c7392b7344e6b4e7b074d83e9ca5f563a8e072f",
"credential_id": "b89292aedf6d05d584cec9a871ce8735", "credential_id": "b89292aedf6d05d584cec9a871ce8735",

@ -1,6 +1,6 @@
{ {
"description": "time_and_key capsule for two known X25519 recipients and a portable .dkk", "description": "time_and_key capsule for two known X25519 recipients and a portable .dkk",
"spec": "0.13", "spec": "0.14",
"format": 1, "format": 1,
"file": "time_and_key_recipients.dkc", "file": "time_and_key_recipients.dkc",
"sha256": "69ac110380f5d768b5b6afaa157a50ed17d8ceccfbd4604ffa5b6da38539b635", "sha256": "69ac110380f5d768b5b6afaa157a50ed17d8ceccfbd4604ffa5b6da38539b635",

@ -1,6 +1,6 @@
{ {
"description": "time_only capsule, two STREAM chunks, no extensions", "description": "time_only capsule, two STREAM chunks, no extensions",
"spec": "0.13", "spec": "0.14",
"format": 1, "format": 1,
"file": "time_only.dkc", "file": "time_only.dkc",
"sha256": "99e915810d595f1092700b728f5e5081d78efe83f5343e76325b1bcc2c33ccf2", "sha256": "99e915810d595f1092700b728f5e5081d78efe83f5343e76325b1bcc2c33ccf2",

@ -1,6 +1,6 @@
{ {
"description": "time_only capsule with a noncritical PUBLIC_HEADER extension and a noncritical CONTROL_CBOR extension", "description": "time_only capsule with a noncritical PUBLIC_HEADER extension and a noncritical CONTROL_CBOR extension",
"spec": "0.13", "spec": "0.14",
"format": 1, "format": 1,
"file": "time_only_extensions.dkc", "file": "time_only_extensions.dkc",
"sha256": "0446c9b73e267adcb24e5cc89afba2544a386ec9a050016e06517a4a57aa2085", "sha256": "0446c9b73e267adcb24e5cc89afba2544a386ec9a050016e06517a4a57aa2085",

@ -1,5 +1,5 @@
{ {
"spec": "0.13", "spec": "0.14",
"description": "CBOR profile of spec §58 and the schemas of spec/datekeys.cddl, generated by the reference implementation. accept and reject are walked as one data item of the profile with the limits of walk; schemas are decoded with the decoder of their schema. See testdata/README.md.", "description": "CBOR profile of spec §58 and the schemas of spec/datekeys.cddl, generated by the reference implementation. accept and reject are walked as one data item of the profile with the limits of walk; schemas are decoded with the decoder of their schema. See testdata/README.md.",
"walk": { "walk": {
"max_depth": 3, "max_depth": 3,

@ -1,5 +1,5 @@
{ {
"spec": "0.13", "spec": "0.14",
"description": "Canonical dk1_ strings and rejected encodings (spec §18, §19, §66), generated by the reference implementation.", "description": "Canonical dk1_ strings and rejected encodings (spec §18, §19, §66), generated by the reference implementation.",
"vectors": [ "vectors": [
{ {

@ -1,5 +1,5 @@
{ {
"spec": "0.13", "spec": "0.14",
"description": "Ed25519 signatures and the result of the strict profile of the author signature (spec v0.11, §29.9), after the cases of «Taming the many EdDSAs»; stdlib is the result of crypto/ed25519 of Go, for the record. Generated by the reference implementation. See testdata/README.md.", "description": "Ed25519 signatures and the result of the strict profile of the author signature (spec v0.11, §29.9), after the cases of «Taming the many EdDSAs»; stdlib is the result of crypto/ed25519 of Go, for the record. Generated by the reference implementation. See testdata/README.md.",
"vectors": [ "vectors": [
{ {

@ -1,5 +1,5 @@
{ {
"spec": "0.13", "spec": "0.14",
"description": "HEAD_CBOR of format 3 (spec §29.4 to §29.6) and the result of decoding it with no extension known, generated by the reference implementation: layer 2 (type tag and version), layer 3 (the CDDL with R1 and R8), then layer 4 in key order (spec §69.1). See testdata/README.md.", "description": "HEAD_CBOR of format 3 (spec §29.4 to §29.6) and the result of decoding it with no extension known, generated by the reference implementation: layer 2 (type tag and version), layer 3 (the CDDL with R1 and R8), then layer 4 in key order (spec §69.1). See testdata/README.md.",
"heads": [ "heads": [
{ {

@ -1,5 +1,5 @@
{ {
"spec": "0.13", "spec": "0.14",
"description": "Differential corpus of the pre-unlock checks (spec §63 steps 1 to 8): deterministic mutations of the official .dkc fixtures with the verdict of the reference implementation. See testdata/README.md.", "description": "Differential corpus of the pre-unlock checks (spec §63 steps 1 to 8): deterministic mutations of the official .dkc fixtures with the verdict of the reference implementation. See testdata/README.md.",
"format": "Each mutation is bases[base].file (in testdata/fixtures) with its edits applied. An edit is [at, delete, insert]: the delete bytes at offset at of the base are replaced by the bytes of the hex string insert. The edits of one mutation refer to offsets of the unmodified base, are sorted by offset and do not overlap. result is the verdict of steps 1 to 8 of spec §63 (capsule.Inspect, the Quicknet profile pinned, no extension known, no network, no secret): ok, or the normative error code, with step the step that failed. kind names the generator of the mutation and is informative.", "format": "Each mutation is bases[base].file (in testdata/fixtures) with its edits applied. An edit is [at, delete, insert]: the delete bytes at offset at of the base are replaced by the bytes of the hex string insert. The edits of one mutation refer to offsets of the unmodified base, are sorted by offset and do not overlap. result is the verdict of steps 1 to 8 of spec §63 (capsule.Inspect, the Quicknet profile pinned, no extension known, no network, no secret): ok, or the normative error code, with step the step that failed. kind names the generator of the mutation and is informative.",
"seed": 20260925, "seed": 20260925,

@ -1,6 +1,6 @@
{ {
"description": "The extension datekeys.capsule of a .dkk and what it points to (spec v0.12, 44.1): an envelope of age with its header apart from its rest, the rest hidden in a host file, the locator sealed with tlock for round 1000, and the data of the extension. On the same envelope, what a reader rejects and what it uses (64): addresses, a locator with rejected and usable addresses, resources of the rest, data of the extension and plaintexts of the locator. Frozen. See testdata/README.md.", "description": "The extension datekeys.capsule of a .dkk and what it points to (spec v0.12, 44.1): an envelope of age with its header apart from its rest, the rest hidden in a host file, the locator sealed with tlock for round 1000, and the data of the extension. On the same envelope, what a reader rejects and what it uses (64): addresses, a locator with rejected and usable addresses, resources of the rest, data of the extension and plaintexts of the locator. Frozen. See testdata/README.md.",
"spec": "0.13", "spec": "0.14",
"round": 1000, "round": 1000,
"datekey": "dk1_eyJ2ZXJzaW9uIjoxLCJuZXR3b3JrIjoiZGF0ZWtleXM6cXVpY2tuZXQ6djEiLCJyb3VuZCI6MTAwMH0", "datekey": "dk1_eyJ2ZXJzaW9uIjoxLCJuZXR3b3JrIjoiZGF0ZWtleXM6cXVpY2tuZXQ6djEiLCJyb3VuZCI6MTAwMH0",
"note": "Cartas del viaje a Lisboa", "note": "Cartas del viaje a Lisboa",

@ -1,5 +1,5 @@
{ {
"spec": "0.13", "spec": "0.14",
"description": "Mutation corpus of spec §64 and further cases of capsule.TestMutationCorpus, generated by the reference implementation: each case is a .dkc and what the reader is given, with the normative error and the step of spec §63 at which capsule.Open fails. See testdata/README.md.", "description": "Mutation corpus of spec §64 and further cases of capsule.TestMutationCorpus, generated by the reference implementation: each case is a .dkc and what the reader is given, with the normative error and the step of spec §63 at which capsule.Open fails. See testdata/README.md.",
"cases": [ "cases": [
{ {

@ -1,5 +1,5 @@
{ {
"spec": "0.13", "spec": "0.14",
"description": "The data of the public note, datekeys.note version 1 in the noncritical array of PUBLIC_HEADER (spec §24.1): the text in UTF-8, from 1 to 1024 bytes, that meets the rules of the declared author of §29.6. See testdata/README.md.", "description": "The data of the public note, datekeys.note version 1 in the noncritical array of PUBLIC_HEADER (spec §24.1): the text in UTF-8, from 1 to 1024 bytes, that meets the rules of the declared author of §29.6. See testdata/README.md.",
"notes": [ "notes": [
{ {

@ -1,5 +1,5 @@
{ {
"spec": "0.13", "spec": "0.14",
"description": "Padding rules of the payload of a format 2 capsule (spec §29.1): for each content length L, P with code 1 (bloque256) and code 2 (reforzado), and the length of PAYLOAD_AGE for each. e, s and last_bits are informative. Generated by the reference implementation. See testdata/README.md.", "description": "Padding rules of the payload of a format 2 capsule (spec §29.1): for each content length L, P with code 1 (bloque256) and code 2 (reforzado), and the length of PAYLOAD_AGE for each. e, s and last_bits are informative. Generated by the reference implementation. See testdata/README.md.",
"l_max": 8936830510563328, "l_max": 8936830510563328,
"vectors": [ "vectors": [

@ -1,5 +1,5 @@
{ {
"spec": "0.13", "spec": "0.14",
"description": "The key of R7 (spec §29.5) of segments, with the Unicode 18.0.0 tables of §29.5.1, generated by the reference implementation: nfd is NFD(segment) and key is NFD(fold(NFD(s'))), s' the segment without ZWNJ, ZWJ, VS15 and VS16. See testdata/README.md.", "description": "The key of R7 (spec §29.5) of segments, with the Unicode 18.0.0 tables of §29.5.1, generated by the reference implementation: nfd is NFD(segment) and key is NFD(fold(NFD(s'))), s' the segment without ZWNJ, ZWJ, VS15 and VS16. See testdata/README.md.",
"unicode_version": "18.0.0", "unicode_version": "18.0.0",
"tables_digest": "07cf5d54aea1cd13a3ecef14a06976cc49a3cdad755cf9bc10395178b93aeb07", "tables_digest": "07cf5d54aea1cd13a3ecef14a06976cc49a3cdad755cf9bc10395178b93aeb07",

@ -1,5 +1,5 @@
{ {
"spec": "0.13", "spec": "0.14",
"description": "Paths of a format 3 head (spec §29.5) with the Unicode 18.0.0 and best-fit tables of §29.5.1, generated by the reference implementation. paths: one path and the rules of one entry, R2 to R6c and R10; trees: the paths of a head, of 0 bytes each, and the result of decoding it. See testdata/README.md.", "description": "Paths of a format 3 head (spec §29.5) with the Unicode 18.0.0 and best-fit tables of §29.5.1, generated by the reference implementation. paths: one path and the rules of one entry, R2 to R6c and R10; trees: the paths of a head, of 0 bytes each, and the result of decoding it. See testdata/README.md.",
"unicode_version": "18.0.0", "unicode_version": "18.0.0",
"tables_digest": "07cf5d54aea1cd13a3ecef14a06976cc49a3cdad755cf9bc10395178b93aeb07", "tables_digest": "07cf5d54aea1cd13a3ecef14a06976cc49a3cdad755cf9bc10395178b93aeb07",

@ -1,5 +1,5 @@
{ {
"spec": "0.13", "spec": "0.14",
"description": "Quicknet Provider Profile V1: exact Deterministic CBOR and profile_hash (spec §11, §12, §75 item 2), generated by the reference implementation.", "description": "Quicknet Provider Profile V1: exact Deterministic CBOR and profile_hash (spec §11, §12, §75 item 2), generated by the reference implementation.",
"profile_id": "datekeys:quicknet:v1", "profile_id": "datekeys:quicknet:v1",
"provider": "drand", "provider": "drand",

@ -1,5 +1,5 @@
{ {
"spec": "0.13", "spec": "0.14",
"profile": "datekeys:quicknet:v1", "profile": "datekeys:quicknet:v1",
"description": "Quicknet date to round resolution (spec §15, §16, §65), generated by the reference implementation.", "description": "Quicknet date to round resolution (spec §15, §16, §65), generated by the reference implementation.",
"vectors": [ "vectors": [

@ -1,5 +1,5 @@
{ {
"spec": "0.13", "spec": "0.14",
"description": "The IP address that the name of an https address of a locator resolves to, and whether a reader may connect (spec v0.13, 44.1): a public address, or an address of NAT64 (RFC 6052) of 64:ff9b::/96 or of the NAT64 prefix of the network, whose IPv4 address inside is public. See testdata/README.md.", "description": "The IP address that the name of an https address of a locator resolves to, and whether a reader may connect (spec v0.13, 44.1): a public address, or an address of NAT64 (RFC 6052) of 64:ff9b::/96 or of the NAT64 prefix of the network, whose IPv4 address inside is public. See testdata/README.md.",
"cases": [ "cases": [
{ {

@ -1,5 +1,5 @@
{ {
"spec": "0.13", "spec": "0.14",
"description": "SECURITY_CBOR of format 3, exactly its SECURITY_LEN bytes, the verdicts of the signature and of the seal in the context of the file, and their lines (spec §29.3, §29.7, §29.9). See testdata/README.md.", "description": "SECURITY_CBOR of format 3, exactly its SECURITY_LEN bytes, the verdicts of the signature and of the seal in the context of the file, and their lines (spec §29.3, §29.7, §29.9). See testdata/README.md.",
"context": { "context": {
"control_commit": "0101010101010101010101010101010101010101010101010101010101010101", "control_commit": "0101010101010101010101010101010101010101010101010101010101010101",

@ -1,6 +1,6 @@
{ {
"description": "SECURITY_CBOR with an author signature of alg 2 or a time seal of seal_type 2, the context of its capsule, and the verdicts, the result of each signer and the lines of spec v0.12 29.7, 29.10 and 29.11. Certificates and tokens are made once with test keys and the file is frozen. See testdata/README.md.", "description": "SECURITY_CBOR with an author signature of alg 2 or a time seal of seal_type 2, the context of its capsule, and the verdicts, the result of each signer and the lines of spec v0.12 29.7, 29.10 and 29.11. Certificates and tokens are made once with test keys and the file is frozen. See testdata/README.md.",
"spec": "0.13", "spec": "0.14",
"cases": [ "cases": [
{ {
"name": "alg 2: two signers, each sealed before the round time: F6", "name": "alg 2: two signers, each sealed before the round time: F6",

@ -1,5 +1,5 @@
{ {
"spec": "0.13", "spec": "0.14",
"description": "H2 of the IBE-CCA of tlock (spec §63 step 11): SHA-256 of \"IBE-H2\" and the 576 bytes of an element of GT, c1 before c0 at every level of the tower and each coordinate of Fp in 48 bytes big-endian (the order of kilic/bls12-381), truncated to 16 bytes. Generated by the reference implementation with drand/kyber-bls12381, the pairing of tlock.", "description": "H2 of the IBE-CCA of tlock (spec §63 step 11): SHA-256 of \"IBE-H2\" and the 576 bytes of an element of GT, c1 before c0 at every level of the tower and each coordinate of Fp in 48 bytes big-endian (the order of kilic/bls12-381), truncated to 16 bytes. Generated by the reference implementation with drand/kyber-bls12381, the pairing of tlock.",
"vectors": [ "vectors": [
{ {

@ -0,0 +1,164 @@
{
"spec": "0.14",
"description": "Steps 10 and 11 of spec §63 for Quicknet, value by value, over published releases. Step 10: M = SHA-256(uint64_be(round)), H(M) the hash to G1 of RFC 9380 with the suite BLS12381G1_XMD:SHA-256_SSWU_RO_ and the DST dst, and e(H(M), public_key) = e(signature, G2). Step 11: a stanza body U || V || W built with the sigma and the file key of the vector; H2 = SHA-256(\"IBE-H2\" || e(signature, U))[:16], sigma = V XOR H2, H4 = SHA-256(\"IBE-H4\" || sigma)[:16], file_key = W XOR H4, and r = H3(sigma, file_key): h3_base = SHA-256(\"IBE-H3\" || sigma || file_key), then for i = 1, 2, ... d = SHA-256(uint16_le(i) || h3_base), its first byte shifted one bit to the right, until it is below the order of the group; r·G2 = U. Generated by the reference implementation and checked against drand, kyber, tlock and agewrap. See testdata/README.md.",
"profile": "datekeys:quicknet:v1",
"scheme": "bls-unchained-g1-rfc9380",
"chain_hash": "52db9ba70e0cc0f6eaf7803dd07447a1f5477735fd3f661792ba94600c84e971",
"public_key": "83cf0f2896adee7eb8b5f01fcad3912212c437e0073e911fb90022d3e760183c8c4b450b6a0a6c3ac6a5776a2d1064510d1fec758c921cc22b0e17e63aaf4bcb5ed66304de9cf809bd274ca73bab4af5a6e9c76a4bc09e76eae8991ef5ece45a",
"dst": "BLS_SIG_BLS12381G1_XMD:SHA-256_SSWU_RO_NUL_",
"tags": {
"h2": "4942452d4832",
"h3": "4942452d4833",
"h4": "4942452d4834"
},
"vectors": [
{
"name": "round 1000, stanza 0",
"round": 1000,
"signature": "b44679b9a59af2ec876b1a6b1ad52ea9b1615fc3982b19576350f93447cb1125e342b73a8dd2bacbe47e4b6b63ed5e39",
"message": "f652498d092acd949bad74e40683bf3824fb817980504a0c7e6722cfc5a9c0a3",
"hash_to_g1": "8f5a32d53837b00fbc0ee31ce9966435a41c5188a80ce9934d3c80588b6ad6f643ebda1b83ef89e44da9ced6205cdecf",
"body": "a73eb63b9a766ebbd23e06daa313760b001502ab48de4976c98c1697ebd51907c2ab92306e4d04ee9f42bff92775ba6606f08479fbd58a3fb786c94a27bf924c67975f419d5b67b96080b4a3da776eddc762ce07af0a5b5a0965f64a9902f4d3f62867846361583f06a8978ae6876e0eb799ebe3cf0b0bf967921fc5e6eb85d9",
"u": "a73eb63b9a766ebbd23e06daa313760b001502ab48de4976c98c1697ebd51907c2ab92306e4d04ee9f42bff92775ba6606f08479fbd58a3fb786c94a27bf924c67975f419d5b67b96080b4a3da776eddc762ce07af0a5b5a0965f64a9902f4d3",
"v": "f62867846361583f06a8978ae6876e0e",
"w": "b799ebe3cf0b0bf967921fc5e6eb85d9",
"pairing": "13dc0e183d402040f68cb518c39c5fcfc61852058d0d58f962ec5649d3da484f62f8562cb4fa6b576d2882bac78ce474100a3086d82617f2b9ba844f6e2569e5b0c3c81ca94aa9ecda8909baabf16bfd4d95602b0ad3263aaaeb14748d41e9e30c811671230b41b54e5cce08f3d3ef671a411850c165dad83824fb91380554f5dd9ea3005738c83e264d58b3b28c275a0409076922ff12b9b1421d70c958c22a29da81a7df5f93a7d5f32d187e82a1f34ed60c01e9bb0685c0f773cb324b0e8118c5a8cee62b795b8fa7d5e820aa08003462a5521d70beabebb7f74022163286256eaeab18148d7caf9a0057fe37e6de0f10c412dd62f013e62a21971bae6d3957fd326aaa809348da278e812637343a20c942263da247497748aa5c39b945bd112fe3afbf5508117b48b1017931e9dfa97e3a9eaffef3add91ed62ec2814eb9063ffb64943e0b302efb12e3ff680d99199e068714b0c0d6d295a6019a6e325def3cd58c7c20c2196ba7fe28d67b9bf385764d81c63c02f6333d4fc5dbf5e1171913e06b904367571b8d2811f7288c18be3831d907ebc7f03ab6014282bcc362f1a3b0d12bbfc9cd9ba1d255254d64a216151c040975fd726c51fe191b3c675fc6ebc79b9a1f123e15059955761732f66cbb13c45868881fbbe08b21cf677551120e80ef555a5db93283f5b99714e997028eb1380e1a3db0bdc55d269f736e2b9f584c2661e460d3a6ce2db9a1aa902a02b16d5b9f634e96c5d615d3e1be0c232e13723d6f9b93686b1b9bee950ed45e729b3bd6d448badc0816fb8b9360bf28",
"h2": "c3d489f4c7c6a6962801cad91047eb95",
"sigma": "35fcee70a4a7fea92ea95d53f6c0859b",
"h4": "bd093650d9bd27e682b48bc3ba52a0aa",
"file_key": "0a90ddb316b62c1fe52694065cb92573",
"h3_base": "c8b1566b6f0ed7b6cfea5eebaa1a7291f77f50c80dfd8269e9b4f253fff23fe0",
"h3_tries": [
{
"i": 1,
"digest": "41fd905b124c321e66a781f9eec59842d08689c872f4eaada61c921f8b6e6a8e",
"shifted": "20fd905b124c321e66a781f9eec59842d08689c872f4eaada61c921f8b6e6a8e",
"accepted": true
}
],
"r": "20fd905b124c321e66a781f9eec59842d08689c872f4eaada61c921f8b6e6a8e"
},
{
"name": "round 1001, stanza 0",
"round": 1001,
"signature": "b33bf3667cbd5a82de3a24b4e0e9fe5513cc1a0e840368c6e31f5fcfa79bea03f73896b25883abf2853d10337fb8fa41",
"message": "ce43c3353a7ad7aac3408cad0bf921b6a7dda89be75d9cb2b3b5a152cefc8afd",
"hash_to_g1": "8dafa08d032514b04972cd9bca0c40226294bc9dc8b02d10ed4b3913554571e04f20d7eb05b74cddf72a9992995ac5bb",
"body": "ad4937a39b57f8c494817575bf3cac373ed629b3580d374953f08df5c59e00f76abbe58ec09704b544464975a843255307d45413ad277661ac6d361afa687bd40f2745fb9c4498882fbb91269350ab975fc1a1a83d2c5f7d127786779c01e55ee512d80ed32c46da0c915a5459244507444e2b3f156d72748fa2c3ee40120dee",
"u": "ad4937a39b57f8c494817575bf3cac373ed629b3580d374953f08df5c59e00f76abbe58ec09704b544464975a843255307d45413ad277661ac6d361afa687bd40f2745fb9c4498882fbb91269350ab975fc1a1a83d2c5f7d127786779c01e55e",
"v": "e512d80ed32c46da0c915a5459244507",
"w": "444e2b3f156d72748fa2c3ee40120dee",
"pairing": "06bf5fa844026aff0c454df2da4f46f769b6db78c68bdfdafacc1aee0d9d57b40603c0a043478a4785c635587896068701fcbc9ef9f489e53c2f30709136404cbb04c9b0ba0b74e26708f53735209f6f5cfa76fefff64a2db62726745db1693711a09a514fc2925ac383494d6882edb9d2c5143f9f2e8b2b25dfcaf1ac03ca6e9e0bfa989f3e1ebbe0a63345bfe1b9e40657b0fdb63c0646e2fef7f48e73861a364fbc944380af8e989e897a0037e54a1766086a1ea7c9457f47ff7521ac175d0e80ac41a06b949e12ac4c131354371f34318d9559bbdbdb8a9b7bd415b4b64542f240d4d3b69f350614fce76cbeb83b09457cc90c73da60247b929ca72602ba0e3c47653f6e798ffdac42f85039f2d43b817647536f369cea55812d08aa1ca80b9854d9b951ded8c1fa0053377711320de0ca459a84983ce49d68446a5d1c757afeffc896b146c2198b3a171854910d04fa8559d6018affc7c4e35760dc1ac4d90c83821e383ecdaa7ee3eda64e3ac4fa43648e7e821caddcbcabf3e34f5ea30e962c6aa7e6de1e72b3362311c5506607b180a79920c14961b9f8c850227bca1c0b59acffc7a79bf48bfde53fde6031185598646a15c7eb55df63e7fe8f930c6be0e8d6ee695608114f511c83a3c98b2e376cedc16b41c6c94acfb7180287d4007e4eeaf3bb6cd8bf67014302f47626346526358b3acec4cd9f7b083cdeed60c632c8007d0e4d88e252e6a3b8a955d216d6991a2893a56117cdebee0c78d7364f54f45313d472de5dd1e426b3483100107614137b08c38b7f139ab8adb05e33",
"h2": "d1c48e9d72ef4e29581947627078779e",
"sigma": "34d65693a1c308f354881d36295c3299",
"h4": "b05c539a1ce0d4b2f881e2a899bd648b",
"file_key": "f41278a5098da6c677232146d9af6965",
"h3_base": "f89b77b992969b10442252a826f0380716867ee3f2270cd6705b4ffbe474c727",
"h3_tries": [
{
"i": 1,
"digest": "85e7c45f27c75fa2571403fc7cd8222e0dfbdddd7842f85e814854c507abdfc6",
"shifted": "42e7c45f27c75fa2571403fc7cd8222e0dfbdddd7842f85e814854c507abdfc6",
"accepted": true
}
],
"r": "42e7c45f27c75fa2571403fc7cd8222e0dfbdddd7842f85e814854c507abdfc6"
},
{
"name": "round 1004, stanza 0",
"round": 1004,
"signature": "a40658b820c0f8c10207524179a2031ba9537688a0d04e4851b58026be9a341fee3b96fb48ffad28483d84b40a5864aa",
"message": "dfb0ecda8fd28db758bd0c580c0bb9397b56225bd50f076bac68460e68d0ea00",
"hash_to_g1": "895a4b04764f8964e42a056c23d7b34808895603f605ee0f749f8be419420b53a0ba5e01caab02e8afd7ff28c6cd771f",
"body": "97b8304c3e87868e549a6293d19d65481bdbcf7cf67b9d5e3d798ade332deb499648fe2f23931ab55b0911ccdc8839560f5a72325eedc7302420bd87bcafd7f27f2eadbc90523a295e5ab476b357ca91b9a8b5e45a4dac972f20b37e97e8945d96ce47d18a7e845031e28207606a7ea78a4f271ed5ed8d3ed9420fe99200396a",
"u": "97b8304c3e87868e549a6293d19d65481bdbcf7cf67b9d5e3d798ade332deb499648fe2f23931ab55b0911ccdc8839560f5a72325eedc7302420bd87bcafd7f27f2eadbc90523a295e5ab476b357ca91b9a8b5e45a4dac972f20b37e97e8945d",
"v": "96ce47d18a7e845031e28207606a7ea7",
"w": "8a4f271ed5ed8d3ed9420fe99200396a",
"pairing": "0b57e9394946ebc2e4ec7478308fe77ab5b509f00727d46dec4d8635bb7934b4c485f3408c974d45468c2363a768ee18172c3f56f94c6bea5f8658cfc79bc3cafdf3dc418134f4cea86e14b1c73ca85456cb56ac4438862d5093447e97afd795169452925b396bb07823cd1d4a5b9a7b58355170a713a0a14a3ff568a27f57743890c26387ef0f15c49057d8cc74857e0874d72f661e9cecd3b97443aaf64e0703ed453ff9ffb659070d81a40fd0c92ed1221d5d0767e0bb6e6d72c3979fe57619cc78dbd491b3629b21668beab4bdcf787ab581c62211f17db4a61d2ff5946178d1d29448c7bce8a664220bb2fd928d1926ddc1fa2d65f47a60bee3f1375a49cad2a5d0c5406f51ccf6d18e537b820da2112350f6a97b2fc76111b7ec8c0ae11484bd6d622de8b58cbb79ad193d285a49333040cdcf4aabd532cf5465248d4234b41a72614aabfe23479926e6b6635d003901ecd863d063befa706baba0b7aba385e7396b78a20f8e7738c7ec14e340b80e8cfeb5509e8bb47807a82fea6b6215a3f4ce9786623a283a4b07d5aa07fcf9636122a6dee64db8b4280c24e2e909bc791cc9d11adf6cacd82823fdf43873171d52f3d9bc035d3f9bb63eaaaa27e3109b7324f2828e6dc2ce78324bff9a92b9c569ab51ed714e70afd1687d5188f60e1ab87bd7db3ffedec49b52dd0a09909be3cc96156b82d0ab49adfd64c24faf9cd574d9c585829f3fd608c7df754a58045f1545128a0030459cc766fbaf636ce19be4d4537ac181cd9bd2da65cb93257b72984bcf0c74b19247d15c680fd278",
"h2": "ed9e2e9ca7679f40d9d5461808d3902d",
"sigma": "7b50694d2d191b10e837c41f68b9ee8a",
"h4": "8aa64ea323262cff566c987b5467ae3a",
"file_key": "00e969bdf6cba1c18f2e9792c6679750",
"h3_base": "cbf54def509294ab547c383ea065b02d2bec599d6a41f41b3083dad3ff7b2459",
"h3_tries": [
{
"i": 1,
"digest": "060304f06ac573eee1c4ed5b125d6f8ae7c9f154c60156c4e37de84ebc9846cb",
"shifted": "030304f06ac573eee1c4ed5b125d6f8ae7c9f154c60156c4e37de84ebc9846cb",
"accepted": true
}
],
"r": "030304f06ac573eee1c4ed5b125d6f8ae7c9f154c60156c4e37de84ebc9846cb"
},
{
"name": "round 2000, stanza 0",
"round": 2000,
"signature": "b6cb8f482a0b15d45936a4c4ea08e98a087e71787caee3f4d07a8a9843b1bc5423c6b3c22f446488b3137eaca799c77e",
"message": "597962656abdc948a536fcd5ba8405e6bd95b9763f4a4da0727e8c98689d52c2",
"hash_to_g1": "906dc77479bc9962a8ed67fd00ad6af2a6c8d109926fdd6b897fe77526b2531b544b5e8703de23748b6ae6172b9986f5",
"body": "ab73f3818b2170ec27e8c6ad89232453199c2ceb781e920fb8058947ade9a12daf99775f384f575daae76fb76c1bb40e00754fd1515534b2f1c315108a568bb7405a5829eba26e3a1ac08178e73ac13bca55a0ef7eeb8980d0a4424b84ac47ff04cbb545b21b4ebcc651055043dd6f7b216b730fe903e9c7824eadef6522c2d9",
"u": "ab73f3818b2170ec27e8c6ad89232453199c2ceb781e920fb8058947ade9a12daf99775f384f575daae76fb76c1bb40e00754fd1515534b2f1c315108a568bb7405a5829eba26e3a1ac08178e73ac13bca55a0ef7eeb8980d0a4424b84ac47ff",
"v": "04cbb545b21b4ebcc651055043dd6f7b",
"w": "216b730fe903e9c7824eadef6522c2d9",
"pairing": "07999e22e3e3e73a814ff2ff0329f87749396dc9b6a2e6f0520b01df4f73935cce76c3197164eb129f03b72675d05d8318f73d35d748b4fadc36cb7bff193e44bc30a795377a5faaae2649fc89df82539b177defcd3122e1ef461f869e22ab80165c6c07fbc3ed5752921287c8dc5177cbbf19c14b84fce0393d4cd2bd9dc8f569964e88d82cca5df637019bf6b3f9230ca4d83f519082c62919b1d5138326cd97af77bf54a8257c677f1162c603f181f0f74dbc5c4558ade7adf44d6689213804028a36cb0597d58a1a777bb187479ae7e69214f632a53fdb93c9580bf71d1cf91076830ca73bf548417e9729a53ad400a89f83721daa9e2a1b963b9cd2b9a6c68bd17b61039d08f4ff9962deef188b597cbf5855dcefc6e4192d4ad4984a2a05929fc3c0043f53f63bca31ae676883ca550ac47c06dad52a95366ccec9f03a2eb6c4fdb15df0238a991f4245a740b00b1762bb3c76709333e758be369616ea68929eadc0eee12b1f074707db5153d2b07fa99db5bff8f6ba04f318c9f4abf6175c1d5471c150ffd8e1cd83ed6e26c3eaa821aa4c4724dbfd644b0df28a80134c0fc2334e34c2b591a79b531b116abf1363314b98b21a669ca179bb7065336df05315a8885f32db74d56884c01ab37ecd0dfcde9b4d23a3481bd487d6e5f523089f89ed52d7e50a48a591306eea76b353ea2c63f14826b8a785ce9a7cafddd5b5d6d6a89773c2b24a178b6e6d3f1f2002d7c409b2c7312df81c21af3ba95ec8646e64ac240a43e6e8245f3ec2532a10ea917c0dac568cb468bad84562acf72c",
"h2": "0b214ea01f127a78f8af587331314ce0",
"sigma": "0feafbe5ad0934c43efe5d2372ec239b",
"h4": "5097513c5c6ad5a8e614205284b46f9a",
"file_key": "71fc2233b5693c6f645a8dbde196ad43",
"h3_base": "2a1ca2b9377eae364c9874c19450c74919f88bd0e4d05153fcadc373db2d3989",
"h3_tries": [
{
"i": 1,
"digest": "59d0a91dbc2ea95a7ded3610fd282f2c0286459e49fe275bce5185501df3a106",
"shifted": "2cd0a91dbc2ea95a7ded3610fd282f2c0286459e49fe275bce5185501df3a106",
"accepted": true
}
],
"r": "2cd0a91dbc2ea95a7ded3610fd282f2c0286459e49fe275bce5185501df3a106"
},
{
"name": "round 1000, stanza 111: H3 accepts its try 4",
"round": 1000,
"signature": "b44679b9a59af2ec876b1a6b1ad52ea9b1615fc3982b19576350f93447cb1125e342b73a8dd2bacbe47e4b6b63ed5e39",
"message": "f652498d092acd949bad74e40683bf3824fb817980504a0c7e6722cfc5a9c0a3",
"hash_to_g1": "8f5a32d53837b00fbc0ee31ce9966435a41c5188a80ce9934d3c80588b6ad6f643ebda1b83ef89e44da9ced6205cdecf",
"body": "b326f73120b5a037953e1b58da50d242e8766a4ade2ac5113685210dfe09d63a2ae1e02e8f1dab5214c68d9fd739e6450ccf379e9e47323e993ac94d91af16d4b38157af7bd098ece86f9d2ceb06b93da6d295e1b18a6eba255a95ed50c869d5f6c14db7259bc069fe1b69cb2d562349e6407fe52ab31aa27b7cc4c859564e33",
"u": "b326f73120b5a037953e1b58da50d242e8766a4ade2ac5113685210dfe09d63a2ae1e02e8f1dab5214c68d9fd739e6450ccf379e9e47323e993ac94d91af16d4b38157af7bd098ece86f9d2ceb06b93da6d295e1b18a6eba255a95ed50c869d5",
"v": "f6c14db7259bc069fe1b69cb2d562349",
"w": "e6407fe52ab31aa27b7cc4c859564e33",
"pairing": "00585d6ec0a2617f28a00b0455e9ea364ec343489aa7f67f046ba13fc40a800d032c89a0ca5cc33761a02c2de95383650ecf9bbbc77ce2322cd225e6775e7a8e39ad0ed6e3bca1213ff44e52bce0a629e5c69cdd380e0448969b253d12e2baa8131b9e81906e44795535bbf276371d6db833ff9e0c96b76ed960e18c9c8a2b9032880bfebc681f0802d0f00b4768317c0246c202f18c369b5fe659353ee0dd803aed4fd66c98b6402ed811ca348741efff0f88ed32fdd65070bda0a63b30dfcd0c24962dad0b5587f8fc39630d37aea45f50ef458c000884b9b51ee2599496aa61b7b916ed873c6c7f11ef1db2a41cb003df3d757e4f61e5c13beb19d0fd9ebbcb15559e6252bbc5d0faae267dc7f5b25f5f2b4e3295bc4d17b308553e28599911d75b66f3f1d5d6a2795cf9bf3f154654d8bd8e64bea438cecaddee75093cf5efc7579ac55e0b5a76ae767264df544a0fdd0e95b9310d24d7bbb3a4df3bc3ae3d251d3970e483c5d4b10870409c7620531cb9d41670835f2306ac0acdd7524312eeb7b9d83de7c623724eba86ea0a7b10bbc6efecf440681271c5c3d980a975637dd26c99f632e003a9f54045bcb1df0abca2ce0afe6bb1cd383fc34efb72ae0afa3db33ac715a371e3fdfe1e28385e775b5e19e1a49ff265ce2238483c342803dd1ae3f72ecd82f17aa1207fa1f32f2c9f89c38488a381d987e90810753462d7003210c6f66b8ff590055b143b553c0825f4bac496509f88698485173da385b2230f44275eb55a3da686e12680fcb175062007100161ed9bf6de51976739c3",
"h2": "2271ed3feb6223f3f21e7fcecb89f30b",
"sigma": "d4b0a088cef9e39a0c051605e6dfd042",
"h4": "085c839d518ebc5636d8642df86b6f2b",
"file_key": "ee1cfc787b3da6f44da4a0e5a13d2118",
"h3_base": "a5dd9d066f9fdd547d25616b65c9ea76e5da38392ca02853a20ebb2c7d01fc11",
"h3_tries": [
{
"i": 1,
"digest": "f647f4537bc552e6d82a22abbef3397f1adfbe51933df3fda8b60e9d927fd9a1",
"shifted": "7b47f4537bc552e6d82a22abbef3397f1adfbe51933df3fda8b60e9d927fd9a1",
"accepted": false
},
{
"i": 2,
"digest": "f20b12601c3bae738eea421aba70ccfb7df494791c004bf5f028972258c1d15a",
"shifted": "790b12601c3bae738eea421aba70ccfb7df494791c004bf5f028972258c1d15a",
"accepted": false
},
{
"i": 3,
"digest": "f45606605279cfaffabaadda379d52a5ae0aa5453447244b702b1588e7be4200",
"shifted": "7a5606605279cfaffabaadda379d52a5ae0aa5453447244b702b1588e7be4200",
"accepted": false
},
{
"i": 4,
"digest": "a495752b48f0bcd717b4e3846ed0501b4085621321ca846b2710d805d0790699",
"shifted": "5295752b48f0bcd717b4e3846ed0501b4085621321ca846b2710d805d0790699",
"accepted": true
}
],
"r": "5295752b48f0bcd717b4e3846ed0501b4085621321ca846b2710d805d0790699"
}
]
}

@ -1,5 +1,5 @@
{ {
"spec": "0.13", "spec": "0.14",
"description": "The key of words (spec §38.1): the words of a text, after NFD, without U+0300 to U+036F, in simple lower case of Unicode 18.0.0 and split by the spaces of the list; what a writer refuses; and the identity, PBKDF2-HMAC-SHA256 of 600000 rounds, for a chain hash, a round and a capsule_id. See testdata/README.md.", "description": "The key of words (spec §38.1): the words of a text, after NFD, without U+0300 to U+036F, in simple lower case of Unicode 18.0.0 and split by the spaces of the list; what a writer refuses; and the identity, PBKDF2-HMAC-SHA256 of 600000 rounds, for a chain hash, a round and a capsule_id. See testdata/README.md.",
"normalize": [ "normalize": [
{ {

Loading…
Cancel
Save

Powered by TurnKey Linux.