v0.16: SpecVersion 0.16, the annex of the draft, and the tests in 76

SpecVersion is 0.16, and so is the spec field of every file of testdata,
the frozen security_cms.json and locator.json included. annex/recovery.md
is §79 of the draft v0.16, with the key of words in 79.7. The draft lists
the two new fixtures in 67, says in 79 what recovery_check.sh opens, and
names in 76 the tests that now exist. The CHANGELOG has its section.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
main
dev 3 hours ago
parent 7ef9e61c60
commit 4f7885495b

@ -3,6 +3,43 @@
All notable changes to this module are documented here. The project follows
semantic versioning; `v0.x` versions make no API stability promise.
## Unreleased — specification v0.16
Implements the draft of the DateKeys Protocol Specification v0.16, of 7
October 2026, on the branch `v0.16`: the review of v0.15 by Astra, with the
recommendation of each decision. It changes no format; it changes the
verdict of a seal without accuracy and the reading of drand's JSON.
`SpecVersion` is 0.16, and so is the `spec` field of every file of
`testdata`, also of the frozen `security_cms.json` and `locator.json`.
- **A seal without accuracy** (§29.7, §29.11). `cms.Token` gains
`HasAccuracy`, `Policy` and `BTSP`. A valid seal is S4 only with accuracy
and t plus the accuracy before the round time; otherwise S5, whose text
gives its reason, `capsule.SealReason`: sealed after or too close, no
accuracy under the BTSP policy of ETSI EN 319 421, or no accuracy.
`Detail.SealReason` and `SignerLine.Reason` carry it, and the line of a
signer of F6 whose seal does not prove it says «sin acreditar que fuera
antes de la fecha de apertura» and the reason. `EncryptFiles` returns the
verdicts of the area it wrote in `Result.Security`, so that a writer warns
of a seal without accuracy (§62.1 rule 19). `security_cms.json` is made
again: 143 cases with `seal_reason`.
- **drand's JSON, strict** (§47.1). `provider.ParseDrandJSON`, the one
reader of it, for a release in hand and for the answers of the relays:
no object repeats a name, names compared exactly once their escapes are
decoded, no lone surrogate, and round a number without sign, fraction or
exponent from 1 to 2^53 - 1. `encoding/json` kept the last of two repeated
names and matched `ROUND` to `round`. `release.json` gains 25 cases.
- **The key of words in the annex** (§79, 79.7). `scripts/recovery` opens
with `-words FILE`, with the normalization without tables of the annex or,
with `-unicodedata FILE`, the full one from `UnicodeData.txt` of Unicode
18.0.0, checked by its SHA-256. The fixture `format3_time_and_key_words`
opens with the text of the vector of the annex, kept in `words_text`.
- **A full last chunk** (79.5). The fixture `format3_full_chunk`, whose
`PAYLOAD_AGE` is one full STREAM chunk; `scripts/recovery_check.sh` opens
it, and the one with words.
- **The annex.** `annex/recovery.md` is §79 of the draft v0.16, with the
key of words in 79.7.
## Unreleased — specification v0.15
Implements the DateKeys Protocol Specification v0.15, which its author

@ -1,6 +1,6 @@
# Cómo abrir una cápsula DateKeys sin software de DateKeys
Este texto acompaña a una cápsula del tiempo de DateKeys, un fichero `.dkc`: dice cómo abrirla, llegada su fecha, sin ningún software de DateKeys, por si ya no existe. Es el anexo informativo §79 de la especificación del protocolo DateKeys v0.15, cuyo texto tiene el SHA-256 45105e693be4187af4dd30f4d254402612587b6427c746f5d29f07a541c1e3f3. Es el mismo para toda cápsula: no lleva ningún dato de esta. Su licencia es CC BY-ND 4.0, Atribución-SinDerivadas 4.0 Internacional (https://creativecommons.org/licenses/by-nd/4.0/deed.es): se puede copiar y compartir sin cambios, citando su origen.
Este texto acompaña a una cápsula del tiempo de DateKeys, un fichero `.dkc`: dice cómo abrirla, llegada su fecha, sin ningún software de DateKeys, por si ya no existe. Es el anexo informativo §79 de la especificación del protocolo DateKeys v0.16, cuyo texto tiene el SHA-256 c13b598fa688f6cd74b7223f34896c30ff091e05df11dad8a02f1ea6bcbb6fa7. Es el mismo para toda cápsula: no lleva ningún dato de esta. Su licencia es CC BY-ND 4.0, Atribución-SinDerivadas 4.0 Internacional (https://creativecommons.org/licenses/by-nd/4.0/deed.es): se puede copiar y compartir sin cambios, citando su origen.
## 79. Anexo informativo: recuperación sin software DateKeys
@ -13,11 +13,12 @@ Hace falta:
- el `.dkc`;
- el release de su ronda, de cualquier fuente: un relay de drand, un archivo de releases, un servicio de caché (§50) o cualquier copia. No hace falta confiar en quien lo da: se verifica con la clave pública de 79.1 (79.3);
- en `time_and_key`, una credencial: la `.dkk`, la identity `age` de un recipient o las palabras de una llave de palabras (§38.1);
- una librería de BLS12-381 con pairing y con el hash a G1 de RFC 9380, SHA-256, HMAC-SHA256, HKDF-SHA256 (RFC 5869), ChaCha20-Poly1305 (RFC 8439), un decodificador de CBOR y la herramienta `age` (§77) o una librería compatible.
- una librería de BLS12-381 con pairing y con el hash a G1 de RFC 9380, SHA-256, HMAC-SHA256, HKDF-SHA256 (RFC 5869), ChaCha20-Poly1305 (RFC 8439), un decodificador de CBOR y la herramienta `age` (§77) o una librería compatible;
- con una llave de palabras, PBKDF2-HMAC-SHA256 (RFC 8018) y, si las palabras llevan otras letras que las de 79.7, `UnicodeData.txt` de Unicode 18.0.0.
No sirven las herramientas de drand: `tle` pide el release a la red y no acepta uno dado, y `age` no acepta una file key, que es lo que da el stanza tlock (79.4). Por eso este anexo describe esos dos pasos enteros (79.4 y 79.5).
La implementación de referencia lo sigue en `scripts/recovery`, un programa que no importa ningún paquete de DateKeys, tlock ni drand: solo la librería estándar de Go, `golang.org/x/crypto`, `filippo.io/age` y la librería BLS12-381 `drand/kyber-bls12381`. `scripts/recovery_check.sh` abre con él una cápsula `time_only` y otra `time_and_key` de los fixtures oficiales.
La implementación de referencia lo sigue en `scripts/recovery`, un programa que no importa ningún paquete de DateKeys, tlock ni drand: solo la librería estándar de Go, `golang.org/x/crypto`, `filippo.io/age` y la librería BLS12-381 `drand/kyber-bls12381`, con las interfaces de `drand/kyber`. `scripts/recovery_check.sh` abre con él una cápsula `time_only`, otra `time_and_key` con su `.dkk`, otra con una llave de palabras y otra cuyo `PAYLOAD_AGE` acaba en un bloque completo, de los fixtures oficiales. Las palabras se le dan en un fichero de texto, y `UnicodeData.txt`, si hace falta, en otro.
### 79.1 Parámetros de Quicknet
@ -108,7 +109,7 @@ Es la especificación `age` v1 de C2SP (§77), resumida. Un fichero `age` es una
```text
age-encryption.org/v1
-> <tipo> <argumentos…>
<cuerpo del stanza en Base64 sin relleno, líneas de 64 caracteres, la última más corta>
<cuerpo del stanza en Base64 sin relleno, líneas de 64 caracteres, la última más corta, quizá vacía>
--- <MAC en Base64 sin relleno, 43 caracteres>
<payload>
```
@ -117,20 +118,48 @@ Con la file key FK, de 16 bytes:
1. La cabecera: clave_mac = HKDF-SHA256(ikm = FK, salt = vacío, info = `header`), 32 bytes. El MAC es HMAC-SHA256(clave_mac, la cabecera desde `age-encryption.org/v1` hasta `---` inclusive, sin el espacio que lo sigue). Si no coincide con el de la línea `---`, la file key o la cabecera son otras.
2. El payload empieza tras el salto de línea del MAC por un nonce de 16 bytes. clave = HKDF-SHA256(ikm = FK, salt = nonce, info = `payload`), 32 bytes.
3. Lo demás son bloques de ChaCha20-Poly1305 de 65 536 bytes de texto, 65 552 cifrados, el último más corto. El nonce de 12 bytes del bloque n, desde 0, es n en 11 bytes big-endian seguido de 0x01 en el último bloque y de 0x00 en los demás. No hay datos asociados. El último bloque solo puede estar vacío si es el único, y nada sigue al último bloque.
3. Lo demás son bloques de ChaCha20-Poly1305 de 65 536 bytes de texto, 65 552 cifrados; el último puede ser más corto, o estar completo: un plaintext de 65 536 bytes es un solo bloque, completo y marcado como último. El nonce de 12 bytes del bloque n, desde 0, es n en 11 bytes big-endian seguido de 0x01 en el último bloque y de 0x00 en los demás. No hay datos asociados. El último bloque solo puede estar vacío si es el único, y nada sigue al último bloque.
### 79.6 Las capas siguientes
El plaintext de `SEALED_CONTROL` es:
- en `time_only`, `CONTROL_CBOR`;
- en `time_and_key`, otro fichero `age`, `INNER_ACCESS_AGE`, con stanzas X25519, uno por credencial y señuelos hasta 16 en los formatos 2 y 3. Se abre con `age -d -i clave.txt`, con la identity de la credencial en `clave.txt`. La de una `.dkk` es su `access_material`. La `.dkk` empieza por 12 bytes, `DKK1`, `01`, `00`, `00 00` y `BODY_LEN` en 4 bytes big-endian (§40), y le sigue un mapa CBOR cuya clave 5 es ese `access_material`, 32 bytes (§41), y cuya clave 3 es el `capsule_id` de su cápsula. Una llave de palabras da la identity con §38.1.
- en `time_and_key`, otro fichero `age`, `INNER_ACCESS_AGE`, con stanzas X25519, uno por credencial y señuelos hasta 16 en los formatos 2 y 3. Se abre con `age -d -i clave.txt`, con la identity de la credencial en `clave.txt`. La de una `.dkk` es su `access_material`. La `.dkk` empieza por 12 bytes, `DKK1`, `01`, `00`, `00 00` y `BODY_LEN` en 4 bytes big-endian (§40), y le sigue un mapa CBOR cuya clave 5 es ese `access_material`, 32 bytes (§41), y cuya clave 3 es el `capsule_id` de su cápsula. Una llave de palabras da la identity con 79.7.
`CONTROL_CBOR` es un mapa CBOR (§31). Su clave 3 es `I_PAYLOAD`, otra identity X25519 de 32 bytes, y en los formatos 2 y 3 su clave 6 es L, una cadena de 8 bytes con un entero big-endian, no un entero CBOR. Con `I_PAYLOAD`, `age -d -i payload.txt` abre `PAYLOAD_AGE`.
Una identity X25519 de 32 bytes se escribe para `age` en Bech32 (BIP 173, §77), no Bech32m: el prefijo `age-secret-key-`, los 32 bytes reagrupados de 8 en 5 bits con ceros al final, que dan 52 caracteres, y la suma de comprobación de BIP 173, calculada con el prefijo en minúsculas. Después, todo en mayúsculas: `AGE-SECRET-KEY-1…`.
### 79.7 El contenido
### 79.7 La llave de palabras
Unas palabras dan la identity X25519 de una credencial (§38.1):
```text
P = las palabras normalizadas, en UTF-8, separadas por un espacio (0x20)
S = "DateKeys llave de palabras v2|" || chain_hash || "|" || ronda || "|" || capsule_id
id = PBKDF2-HMAC-SHA256(P, S, 600000 iteraciones, 32 bytes) ; RFC 8018
```
En S, `chain_hash` es el de 79.1 y `capsule_id` el de 79.2, en hexadecimal en minúsculas, y la ronda, la de la DateKey en decimal, sin ceros a la izquierda. `id` es la identity, que se escribe para `age` como dice 79.6.
**Normalización sin tablas.** Si el texto solo lleva caracteres ASCII imprimibles (U+0021 a U+007E), los espacios U+0009 a U+000D y U+0020, las letras á, é, í, ó, ú, ü y ñ y sus mayúsculas, y marcas de U+0300 a U+036F, que es lo que da cualquier palabra de las listas de DateKeys, las palabras normalizadas salen así:
1. se quitan las marcas de U+0300 a U+036F;
2. á y Á pasan a a; é y É, a e; í e Í, a i; ó y Ó, a o; ú, ü, Ú y Ü, a u; ñ y Ñ, a n;
3. A a Z pasan a a a z;
4. se parte el texto por los espacios, sin palabras vacías.
El resto se queda: la puntuación y las cifras cuentan, y «perro,» no es «perro».
**Normalización completa.** Para cualquier otro texto, en este orden: la NFD de UAX #15, con la descomposición canónica de cada punto de código (el campo 5 de `UnicodeData.txt`, sin las que llevan una etiqueta entre `<` y `>`, aplicada hasta el final), la de las sílabas Hangul, que se calcula, y la reordenación canónica por la clase de combinación (campo 3); se quitan los puntos de código de U+0300 a U+036F; cada punto de código pasa a su minúscula simple (campo 13), si la tiene; y se parte por los espacios U+0009 a U+000D, U+0020, U+0085, U+00A0, U+1680, U+2000 a U+200A, U+2028, U+2029, U+202F, U+205F y U+3000, sin palabras vacías. Sirve cualquier copia de `UnicodeData.txt` de Unicode 18.0.0 cuyo SHA-256 sea `0736451de439ae7baf1425136617da495e09ee5afbe6e394374db7009ea08950`; unicode.org la publica en `https://www.unicode.org/Public/18.0.0/ucd/UnicodeData.txt`. Otra versión de Unicode puede dar otras palabras: una que asigne un punto de código nuevo, o que cambie una descomposición o una minúscula.
Vectores, con el chain hash de Quicknet, la ronda 1000 y `capsule_id` = `000102030405060708090a0b0c0d0e0f`:
- «perro luna casa verde tren mar» da `id` = `fceec4d8ca8de86c85a1f26ed49f82a2b38431bd0ce36db995ae7dfd49b96e41`;
- el texto «Ñandú», dos espacios, «PINGÜINO», un tabulador (U+0009) y «camión árbol Éter ola» da «nandu pinguino camion arbol eter ola» e `id` = `273295d29370126a3be50b743132718d3cd9137fb3bb4cb20aa23163d2e19bb7`, lo mismo que ese texto con las tildes, la diéresis y la tilde de la eñe escritas como marcas sueltas detrás de su letra (U+0301, U+0308 y U+0303).
### 79.8 El contenido
El plaintext de `PAYLOAD_AGE` es:
@ -153,6 +182,6 @@ La clave 5 del head es la lista de ficheros (§29.4). Cada uno es un mapa:
Sus bytes van de start a end, sin incluir end, contados desde el origen. Las claves 3 y 4 del head son el comentario y el autor declarado: textos del creador que no prueban nada (§29.7). Una ruta que saldría de la carpeta de destino no se escribe.
### 79.8 Lo que el anexo no comprueba
### 79.9 Lo que el anexo no comprueba
Este anexo comprueba lo que decide que el resultado es el correcto: la firma del release, r·G2 == U, los MAC de cada fichero `age` y el SHA-256 de cada fichero. No comprueba, entre otras cosas, la codificación canónica de cada objeto, `header_binding` (§26), los 16 stanzas de `INNER_ACCESS_AGE` (§39), los ceros del relleno (§29.1) ni las reglas de las rutas (§29.5). Una cápsula que el lector de §63 rechazaría puede abrirse siguiendo este anexo; su contenido es el que sellaron las MAC de `age`, pero no tiene la garantía de un lector conforme.

@ -44,7 +44,7 @@ func TestRecoveryAnnex(t *testing.T) {
if RecoveryAnnex != want {
t.Fatalf("annex/recovery.md is not §79 of the specification %s: write it again with DATEKEYS_WRITE_ANNEX=1 go test -run TestRecoveryAnnex .", SpecVersion)
}
for _, s := range []string{"## 79. Anexo informativo: recuperación sin software DateKeys", "### 79.8 Lo que el anexo no comprueba", "DateKeys v" + SpecVersion + ","} {
for _, s := range []string{"## 79. Anexo informativo: recuperación sin software DateKeys", "### 79.7 La llave de palabras", "### 79.9 Lo que el anexo no comprueba", "DateKeys v" + SpecVersion + ","} {
if !strings.Contains(RecoveryAnnex, s) {
t.Errorf("the annex lacks %q", s)
}

@ -17,13 +17,13 @@ import (
// testdata/vectors/security_cms.json is frozen: each case is evaluated again,
// with its context, and must give its verdicts, the result of each signer,
// the authority and the time of a valid seal, and its lines, byte for byte
// (spec v0.12 §29.7, §29.10, §29.11).
// (spec v0.16 §29.7, §29.10, §29.11).
func TestCMSVectors(t *testing.T) {
var f testkit.CMSVectorFile
if err := testkit.ReadJSON(filepath.Join("..", "testdata", "vectors", "security_cms.json"), &f); err != nil {
t.Fatal(err)
}
if f.Spec != datekeys.SpecVersion || !strings.Contains(f.Description, "v0.12") || len(f.Cases) < 100 {
if f.Spec != datekeys.SpecVersion || !strings.Contains(f.Description, "v0.16") || len(f.Cases) < 140 {
t.Fatalf("spec %q, %d cases: %s", f.Spec, len(f.Cases), f.Description)
}
seen := map[string]bool{}

@ -372,7 +372,7 @@ func securityCMSVectors() (any, error) {
g.file = testkit.CMSVectorFile{
Spec: cmsVectorSpec,
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. " +
"and the verdicts, the result of each signer and the lines of spec v0.16 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.",
}
g.signatureCases()

@ -3518,9 +3518,10 @@ Los de formato 3 cubren, como mínimo:
- el área de 32 KiB sin firma;
- una firma de `alg` 1 (F4, o F3 con su clave guardada);
- esa firma con un sello de `seal_type` 2 (S4), y un fichero cuya mtime es posterior al sello, que se muestra como incoherencia;
- una firma de `alg` 2 de dos firmantes, con ECDSA P-256 y con RSA de 2048 bits, cada uno con su sello CAdES-T (F6).
- una firma de `alg` 2 de dos firmantes, con ECDSA P-256 y con RSA de 2048 bits, cada uno con su sello CAdES-T (F6);
- desde la v0.16, una cápsula `time_and_key` cuya única credencial es una llave de palabras, la del segundo vector de 79.7, y una cuyo `PAYLOAD_AGE` acaba en un bloque completo de 65 536 bytes de texto (79.5).
Son `format3_single.dkc`, `format3_tree.dkc`, `format3_comment_only.dkc`, `format3_bloque256.dkc`, `format3_time_and_key_portable.dkc` con su `.dkk`, `format3_area_1024.dkc`, `format3_security_v2.dkc`, `format3_signature_unsupported.dkc`, `format3_seal_unsupported.dkc`, `format3_unsigned.dkc`, `format3_signed.dkc`, `format3_sealed.dkc` y `format3_signed_cms.dkc`. Los vectores de rutas y del head van en `testdata/vectors/paths.json`, `head_schema.json` y `path_fold.json`; los de `security`, en `security.json` y `security_cms.json`; los de Ed25519 estricto, en `ed25519_strict.json`; los de la nota, en `note.json`; y los de `datekeys.capsule`, en `locator.json`.
Son `format3_single.dkc`, `format3_tree.dkc`, `format3_comment_only.dkc`, `format3_bloque256.dkc`, `format3_time_and_key_portable.dkc` con su `.dkk`, `format3_area_1024.dkc`, `format3_security_v2.dkc`, `format3_signature_unsupported.dkc`, `format3_seal_unsupported.dkc`, `format3_unsigned.dkc`, `format3_signed.dkc`, `format3_sealed.dkc`, `format3_signed_cms.dkc`, `format3_time_and_key_words.dkc`, con el texto de sus palabras en su registro, y `format3_full_chunk.dkc`. Los vectores de rutas y del head van en `testdata/vectors/paths.json`, `head_schema.json` y `path_fold.json`; los de `security`, en `security.json` y `security_cms.json`; los de Ed25519 estricto, en `ed25519_strict.json`; los de la nota, en `note.json`; y los de `datekeys.capsule`, en `locator.json`.
Los vectores de rutas y del head cubren, como mínimo: U+00A0 y U+3000 al principio y al final de un segmento, con el veredicto que dan las tablas, que para U+3000 es el rechazo por R6c; best-fit; alias 8.3, «~1» incluido; Cn; `["b/..", "a"]`; U+206A a U+206F, las etiquetas y otros ignorables fuera de la lista blanca; «.» seguido de ZWJ y un segmento hecho solo de ZWJ; 127 veces «ΐ»; U+F03A; «.datekeys-x» en el primer nivel y en otro; el orden de U+FF5E y U+1F600; «ab» con y sin ZWNJ; «¿», «§» y «♥», que se aceptan; VS16 tras un emoji que lo admite, que se acepta, y tras «a», que no; ZWJ al principio, al final y dos seguidos; y la bandera arcoíris, que se acepta, y la de Escocia, que no. Los de `head_schema.json` cubren además un comentario con etiquetas y con selectores de variante sueltos. Los de `security.json` cubren: el mapa exterior con la clave 2 que no es una cadena de bytes, con una clave 4 o con un byte de más dentro de `SECURITY_LEN` (X); `alg` 0 o una clave vacía dentro de la clave 2 (F1, con el sello intacto); y un `seal` que incumple su schema con un `seal_type` desconocido (S2).
@ -4481,18 +4482,18 @@ La v0.16 corrige lo que encontró la revisión de Astra de la v0.15, el 7 de oct
- Cambio: S4 exige que el token lleve `accuracy` y que t + precisión < round_time; sin `accuracy`, un sello válido es S5. S5 pasa a «No acredita que se sellara antes de la fecha de apertura: ‹motivo›.», con tres motivos, uno de ellos para un token de la política BTSP de ETSI, que exige `accuracy`. En F6, la línea de un firmante cuyo sello no la lleva no dice «antes de la fecha de apertura». El escritor avisa de un sello sin `accuracy`.
- Motivo: con «0 si no viene», un sello sin `accuracy` acreditaba anterioridad con una precisión que nadie había declarado. RFC 3161 (§2.4.2) deja entonces la precisión a la política de la TSA, que el lector no conoce, y ningún margen fijo vale para toda TSA. El texto de S5, «Sellado después de la fecha de apertura», era además falso para un sello anterior a round_time cuya precisión llegaba a ella (revisión de Astra, punto 1).
- Caso: «seal: before the round time: S4» de `security_cms.json`, un token sin `accuracy` sellado el 30 de septiembre de 2026 en una cápsula de 2030, daba S4 con una precisión de 0; ahora da S5, «el sello no dice su precisión». `format3_sealed` lleva una `accuracy` de 1 s y no cambia.
- Pruebas previstas: `security_cms.json`, con los casos sin `accuracy` en S5 y casos nuevos: un token sin `accuracy` de la política BTSP, uno con una `accuracy` de 0 segundos y un firmante de `alg` 2 cuyo sello no la lleva.
- Pruebas: `security_cms.json`, hecho de nuevo, 143 casos: los sellos de los casos que prueban otra cosa llevan una `accuracy` de 1 s, y hay casos nuevos sin `accuracy`, años antes de la fecha y después, de la política BTSP con ella y sin ella, con una `accuracy` de 0 segundos y vacía, y de un firmante de `alg` 2 cuyo sello no la lleva, también BTSP, cada uno con su `seal_reason`; `capsule.TestEvaluateSeal` y `TestEncryptFilesCMSAndSeal`, que comprueba que el escritor devuelve el veredicto S5 de un sello sin `accuracy` para avisar de él.
- Descartado: un margen fijo para el sello sin `accuracy`, y una tabla de políticas con su precisión, que queda como trabajo futuro (§74).
2. **La llave de palabras en el anexo** (§79, 79.6, 79.7).
- Cambio: el anexo trae la derivación de §38.1 y su normalización: una receta sin tablas, exacta para el texto que dan las listas de DateKeys (ASCII, á, é, í, ó, ú, ü, ñ y sus mayúsculas, y las marcas de U+0300 a U+036F), y para cualquier otro texto, la normalización completa con `UnicodeData.txt` de Unicode 18.0.0, que nombra por su SHA-256; y dos vectores. Lo que hace falta incluye PBKDF2-HMAC-SHA256.
- Motivo: el anexo remitía a §38.1, que no contiene, y §38.1 a las tablas de §29.5.1: sin software de DateKeys no se podía abrir una cápsula de una llave de palabras (revisión de Astra, punto 2).
- Caso: el texto «Ñandú», dos espacios, «PINGÜINO», un tabulador y «camión árbol Éter ola» da `id` = `273295d29370126a3be50b743132718d3cd9137fb3bb4cb20aa23163d2e19bb7` en la cápsula del vector de §38.1, lo mismo que «nandu pinguino camion arbol eter ola» y que el texto con sus marcas sueltas.
- Pruebas previstas: `scripts/recovery` con las palabras, también sobre el texto del vector, y su comprobación sobre un fixture con una llave de palabras; `wordkey.json`, con el vector nuevo.
- Pruebas: `scripts/recovery` abre con `-words` y, si hace falta, `-unicodedata`; `TestAnnexWordVectors` comprueba los dos vectores, `TestNormalizeVectors`, que las dos normalizaciones dan las palabras de cada caso de `wordkey.json`, y `TestRecoverWithWords`, el fixture nuevo `format3_time_and_key_words`, que `scripts/recovery_check.sh` abre también; `wordkey.json` gana el texto del vector, también con sus marcas sueltas, y su llave.
3. **El último bloque de `age`** (79.5).
- Cambio: «el último más corto» pasa a «el último puede ser más corto, o estar completo»: un plaintext de 65 536 bytes es un solo bloque completo, marcado como último. La última línea del cuerpo de un stanza puede estar vacía.
- Motivo: lo dice la especificación `age` de C2SP (§77). Quien siguiera el anexo rechazaría un fichero `age` cuyo plaintext mide un múltiplo de 65 536 bytes (revisión de Astra, punto 3). `scripts/recovery` ya lo hacía bien.
- Caso: ningún fixture oficial tiene un `PAYLOAD_AGE` que acabe en un bloque completo, así que `scripts/recovery_check.sh` no lo comprobaba.
- Pruebas previstas: un fixture nuevo cuyo `PAYLOAD_AGE` acaba en un bloque completo, abierto por `scripts/recovery_check.sh`.
- Pruebas: `format3_full_chunk`, cuyo BODY y cuya P miden 65 536 bytes, abierto por `scripts/recovery_check.sh` y por `TestRecoverFixtures`.
4. **Las evidencias de la firma con certificado** (§29.10, §62.1 reglas 21 y 22).
- Cambio: la regla 21 deja de recomendar podar la cadena a un certificado por firmante: el escritor SHOULD guardar las cadenas de los firmantes y de las autoridades de sellado sin sus raíces, y las respuestas OCSP; si no caben, MUST decir qué deja fuera y SHOULD ofrecer exportarlo. La regla 22 pide lo mismo para la cadena de la autoridad de un sello de la clave 3. §29.10 promete solo lo que la cápsula conserva.
- Motivo: un validador de largo plazo necesita los certificados intermedios y la revocación del momento de la firma, y años después quizá no pueda pedirlos. Podar la cadena los perdía en silencio, y §29.10 prometía la respuesta OCSP aunque no cupiera (revisión de Astra, punto 4).
@ -4502,7 +4503,7 @@ La v0.16 corrige lo que encontró la revisión de Astra de la v0.15, el 7 de oct
- Cambio: ningún objeto del JSON repite un nombre; los nombres se comparan exactos, tras decodificar sus escapes; un sustituto suelto hace el JSON mal formado; y `round` es un número sin signo, sin fracción ni exponente, de 1 a 2⁵³ − 1. Lo demás es `ERR_RELEASE_INVALID`.
- Motivo: «`round` es un número entero» dejaba la lectura a cada librería de JSON. Las tres implementaciones leen como `encoding/json` de Go, que se queda con el último de dos nombres repetidos y no distingue mayúsculas, y otro lector con `JSON.parse` o con el `json` de Python distingue mayúsculas: la misma entrada daba dos rondas (revisión de Astra, punto 5).
- Caso: `{"round":1000,"ROUND":1001,"signature":…}`, con la firma de la ronda 1000, da `ERR_ROUND_MISMATCH` con `time_only.dkc` en las tres implementaciones, que leen la ronda 1001, y abre la cápsula con un lector que distingue mayúsculas; y `{"round":1000,"round":1001,…}` da la ronda 1001 en las tres, y la 1000 en un lector que se queda con el primero.
- Pruebas previstas: `release.json`, con los casos nuevos de §64.
- Pruebas: `release.json`, con 25 casos nuevos del JSON de drand (§64), y `provider.TestStrictJSON`, con los bordes de la gramática de RFC 8259 y UTF-8 inválido. `provider/drand` lee las respuestas de los relays con el mismo lector.
6. **Erratas** (§1, §74, §77, §79).
- Cambio: §1 junta en una línea la Release API, la Release Cache y el objeto release; la lista de provisionales de §74 acaba en punto; §77 añade ETSI EN 319 421 y 319 422; §79 nombra las interfaces de `drand/kyber`, que `scripts/recovery` también importa; y la cabecera ya no dice «prevista» de la implementación de referencia.
- Pruebas previstas: ninguna.
@ -4640,7 +4641,7 @@ Hace falta:
No sirven las herramientas de drand: `tle` pide el release a la red y no acepta uno dado, y `age` no acepta una file key, que es lo que da el stanza tlock (79.4). Por eso este anexo describe esos dos pasos enteros (79.4 y 79.5).
La implementación de referencia lo sigue en `scripts/recovery`, un programa que no importa ningún paquete de DateKeys, tlock ni drand: solo la librería estándar de Go, `golang.org/x/crypto`, `filippo.io/age` y la librería BLS12-381 `drand/kyber-bls12381`, con las interfaces de `drand/kyber`. `scripts/recovery_check.sh` abre con él una cápsula `time_only`, otra `time_and_key` y otra con una llave de palabras de los fixtures oficiales.
La implementación de referencia lo sigue en `scripts/recovery`, un programa que no importa ningún paquete de DateKeys, tlock ni drand: solo la librería estándar de Go, `golang.org/x/crypto`, `filippo.io/age` y la librería BLS12-381 `drand/kyber-bls12381`, con las interfaces de `drand/kyber`. `scripts/recovery_check.sh` abre con él una cápsula `time_only`, otra `time_and_key` con su `.dkk`, otra con una llave de palabras y otra cuyo `PAYLOAD_AGE` acaba en un bloque completo, de los fixtures oficiales. Las palabras se le dan en un fichero de texto, y `UnicodeData.txt`, si hace falta, en otro.
### 79.1 Parámetros de Quicknet

@ -67,7 +67,7 @@
the tlock IBE. Its §76 records each change with its case.
- `DateKeys_Protocol_Specification_v0.15.md`: frozen copy of the normative
draft v0.15 (7 October 2026), approved by its author on that date and
tagged `spec-v0.15`; this module implements it. SHA-256:
tagged `spec-v0.15`. SHA-256:
`45105e693be4187af4dd30f4d254402612587b6427c746f5d29f07a541c1e3f3`.
It covers the
long-term recovery of capsules: the release object, the release of a
@ -81,7 +81,7 @@
valid release in hand opens a capsule with a clock behind its round time.
Its §76 records each change with its case.
- `DateKeys_Protocol_Specification_v0.16.md`: the draft v0.16 (7 October
2026), not yet approved, on the branch `v0.16`. It fixes what Astra's
2026), not yet approved, on the branch `v0.16`; this module implements it. It fixes what Astra's
review of v0.15 found: a valid seal without `accuracy` no longer proves
that it came before the unlock date (S5, with its reason); the recovery
annex derives a key of words without DateKeys software, with a recipe

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

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

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

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

@ -1,6 +1,6 @@
{
"description": "portable X25519 .dkk of format2_time_and_key_recipients.dkc",
"spec": "0.15",
"spec": "0.16",
"file": "format2_time_and_key_recipients.dkk",
"sha256": "2ad99b1556086ec311d7f0b3bd3aaba05e75f45c4fa22490b0d5e8bb0b1a222e",
"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",
"spec": "0.15",
"spec": "0.16",
"format": 2,
"file": "format2_time_and_key_recipients.dkc",
"sha256": "1a44fd8708c92e2e0a10cfcb1d864a71331ea9af25d97e1a42e969dc898959e3",

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

@ -1,6 +1,6 @@
{
"description": "format 2 time_only capsule, padding code 2 (reforzado): L = 78000, P = 79872, two STREAM chunks",
"spec": "0.15",
"spec": "0.16",
"format": 2,
"file": "format2_time_only.dkc",
"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",
"spec": "0.15",
"spec": "0.16",
"format": 2,
"file": "format2_time_only_bloque256.dkc",
"sha256": "aae769c30d04920801d8b293d30864fbe223c9c9353ec2b4907a1ee1996e39f9",

@ -1,6 +1,6 @@
{
"description": "format 2 time_only capsule with a noncritical PUBLIC_HEADER extension and a noncritical CONTROL_CBOR extension",
"spec": "0.15",
"spec": "0.16",
"format": 2,
"file": "format2_time_only_extensions.dkc",
"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",
"spec": "0.15",
"spec": "0.16",
"format": 3,
"file": "format3_area_1024.dkc",
"sha256": "41ea2eed0293e4fef7f4a307b7f16aaf1339f5bf6f4ded7a6a9ae1aebeb0133c",

@ -1,6 +1,6 @@
{
"description": "format 3 time_only capsule with padding code 1 (bloque256) and one file of 20000 bytes",
"spec": "0.15",
"spec": "0.16",
"format": 3,
"file": "format3_bloque256.dkc",
"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",
"spec": "0.15",
"spec": "0.16",
"format": 3,
"file": "format3_comment_only.dkc",
"sha256": "7f98a89413f08655bbbab28b96585dfa6173c1705dd81a900deba2100d19f2ef",

@ -1,6 +1,6 @@
{
"description": "format 3 time_only capsule with padding code 1 (bloque256) and one file, whose BODY and P are 65536 bytes: PAYLOAD_AGE ends in a full STREAM chunk, which the annex of spec v0.16 (79.5) allows",
"spec": "0.15",
"spec": "0.16",
"format": 3,
"file": "format3_full_chunk.dkc",
"sha256": "af658967b0b2c79379e25edfe3a785095e9aa2686203e93e9f30dacf27a38684",

@ -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)",
"spec": "0.15",
"spec": "0.16",
"format": 3,
"file": "format3_note.dkc",
"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",
"spec": "0.15",
"spec": "0.16",
"format": 3,
"file": "format3_seal_unsupported.dkc",
"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",
"spec": "0.15",
"spec": "0.16",
"format": 3,
"file": "format3_sealed.dkc",
"sha256": "dde5a072d8783227d28279d06d3d226a1fb967c766da626f889d1c6fd76ac9c7",

@ -1,6 +1,6 @@
{
"description": "format 3 time_only capsule whose security is of version 2: verdict X",
"spec": "0.15",
"spec": "0.16",
"format": 3,
"file": "format3_security_v2.dkc",
"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",
"spec": "0.15",
"spec": "0.16",
"format": 3,
"file": "format3_signature_unsupported.dkc",
"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",
"spec": "0.15",
"spec": "0.16",
"format": 3,
"file": "format3_signed.dkc",
"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",
"spec": "0.15",
"spec": "0.16",
"format": 3,
"file": "format3_signed_cms.dkc",
"sha256": "d658f8d5ac2c5550c07b8f8fd6883b2f6dc02ceafc47d436ea02d8950b2548d2",

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

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

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

@ -1,6 +1,6 @@
{
"description": "format 3 time_and_key capsule with one credential, a key of words, and 15 dummies: the text of the vector of the annex of spec v0.16 (79.7), «Ñandú», two spaces, «PINGÜINO», a tab and «camión árbol Éter ola», whose words are «nandu pinguino camion arbol eter ola»",
"spec": "0.15",
"spec": "0.16",
"format": 3,
"file": "format3_time_and_key_words.dkc",
"sha256": "64a11824630b6134892087a4d4ad3ee6e27941513507ad17fc87a7a2b4421e33",

@ -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",
"spec": "0.15",
"spec": "0.16",
"format": 3,
"file": "format3_tree.dkc",
"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",
"spec": "0.15",
"spec": "0.16",
"format": 3,
"file": "format3_unsigned.dkc",
"sha256": "317ab722ae3812a25ddd78b4c98c586363e5587c8d3634c881ce7c421af19168",

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

@ -1,6 +1,6 @@
{
"description": "time_and_key capsule whose only recipient is a portable .dkk",
"spec": "0.15",
"spec": "0.16",
"format": 1,
"file": "time_and_key_portable.dkc",
"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",
"spec": "0.15",
"spec": "0.16",
"file": "time_and_key_portable_extension.dkk",
"sha256": "0bf463a7c65627b7dda2234d728df89ec5b835816a2a37b91497d8fecc5ea548",
"credential_id": "3955e944a3c60cfa1fd6485e9693c77d",

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

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

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

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

@ -1,5 +1,5 @@
{
"spec": "0.15",
"spec": "0.16",
"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": {
"max_depth": 3,

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

@ -1,5 +1,5 @@
{
"spec": "0.15",
"spec": "0.16",
"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": [
{

@ -1,5 +1,5 @@
{
"spec": "0.15",
"spec": "0.16",
"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": [
{

@ -1,5 +1,5 @@
{
"spec": "0.15",
"spec": "0.16",
"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.",
"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.",
"spec": "0.15",
"spec": "0.16",
"round": 1000,
"datekey": "dk1_eyJ2ZXJzaW9uIjoxLCJuZXR3b3JrIjoiZGF0ZWtleXM6cXVpY2tuZXQ6djEiLCJyb3VuZCI6MTAwMH0",
"note": "Cartas del viaje a Lisboa",

@ -1,5 +1,5 @@
{
"spec": "0.15",
"spec": "0.16",
"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": [
{

@ -1,5 +1,5 @@
{
"spec": "0.15",
"spec": "0.16",
"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": [
{

@ -1,5 +1,5 @@
{
"spec": "0.15",
"spec": "0.16",
"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,
"vectors": [

@ -1,5 +1,5 @@
{
"spec": "0.15",
"spec": "0.16",
"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",
"tables_digest": "07cf5d54aea1cd13a3ecef14a06976cc49a3cdad755cf9bc10395178b93aeb07",

@ -1,5 +1,5 @@
{
"spec": "0.15",
"spec": "0.16",
"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",
"tables_digest": "07cf5d54aea1cd13a3ecef14a06976cc49a3cdad755cf9bc10395178b93aeb07",

@ -1,5 +1,5 @@
{
"spec": "0.15",
"spec": "0.16",
"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",
"provider": "drand",

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

@ -1,5 +1,5 @@
{
"spec": "0.15",
"spec": "0.16",
"description": "The release object (spec v0.15, §47.1), and drand's JSON as the input of the caller, each checked against the pinned Quicknet profile and the round of a DateKey as step 10 of spec §63 checks a release that the caller supplies; and the lookups of a local release archive (spec v0.15, §50). See testdata/README.md.",
"profile": "datekeys:quicknet:v1",
"objects": [

@ -1,5 +1,5 @@
{
"spec": "0.15",
"spec": "0.16",
"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": [
{

@ -1,5 +1,5 @@
{
"spec": "0.15",
"spec": "0.16",
"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": {
"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.",
"spec": "0.15",
"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.16 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.16",
"cases": [
{
"name": "alg 2: two signers, each sealed before the round time: F6",

@ -1,5 +1,5 @@
{
"spec": "0.15",
"spec": "0.16",
"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": [
{

@ -1,5 +1,5 @@
{
"spec": "0.15",
"spec": "0.16",
"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",

@ -1,5 +1,5 @@
{
"spec": "0.15",
"spec": "0.16",
"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": [
{

@ -6,11 +6,11 @@ import (
)
// SpecVersion is the version of the DateKeys Protocol Specification that this
// module implements: spec/DateKeys_Protocol_Specification_v0.11.md, tagged
// spec-v0.11 in its repository. It is neither the version of the module (see
// module implements: spec/DateKeys_Protocol_Specification_v<SpecVersion>.md,
// tagged spec-v<SpecVersion> in its repository once its author approves it. It is neither the version of the module (see
// Version) nor the versions inside the objects: the capsule format, 1 to 3,
// and the schema versions (spec §22, §70).
const SpecVersion = "0.15"
const SpecVersion = "0.16"
// modulePath is the path of this module: the import path of its root
// package, whatever the module is called.

Loading…
Cancel
Save

Powered by TurnKey Linux.