From ae334343bfa2433bd82b679c8119596dbd4840a4 Mon Sep 17 00:00:00 2001 From: dev Date: Thu, 1 Oct 2026 22:46:12 +0200 Subject: [PATCH] Spec v0.11 approved: the text of the review, SpecVersion 0.11 and its SHA-256 The author approved the text and the six open decisions on 1 October 2026. The spec says now what the review left open: the form of the CMS signature and of the TSTInfo field by field, the ESSCertIDv2 with SHA-256 written, the padding of the locator at its boundaries, base32 CIDs, the addresses read without decoding, the issuer shown by the rules of the holder, and the area decided after the signatures. SpecVersion is 0.11, the records of fixtures and vectors say so, and decrypt shows an mtime later than a valid seal as an inconsistency, which 29.7 asks as a SHOULD. Co-Authored-By: Claude Sonnet 5.5 --- CHANGELOG.md | 16 ++++++++---- capsule/format3.go | 25 +++++++++++++++++++ cmd/datekeys/author_test.go | 15 +++++++++++ cmd/datekeys/present.go | 11 ++++++++ spec/DateKeys_Protocol_Specification_v0.11.md | 25 ++++++++++++++----- spec/README.md | 19 ++++++++------ testdata/fixtures/empty_payload.json | 2 +- testdata/fixtures/format2_empty_payload.json | 2 +- .../format2_time_and_key_portable.dkk.json | 2 +- .../format2_time_and_key_portable.json | 2 +- .../format2_time_and_key_recipients.dkk.json | 2 +- .../format2_time_and_key_recipients.json | 2 +- .../format2_time_and_key_sixteen.json | 2 +- testdata/fixtures/format2_time_only.json | 2 +- .../fixtures/format2_time_only_bloque256.json | 2 +- .../format2_time_only_extensions.json | 2 +- testdata/fixtures/format3_area_1024.json | 2 +- testdata/fixtures/format3_bloque256.json | 2 +- testdata/fixtures/format3_comment_only.json | 2 +- .../fixtures/format3_seal_unsupported.json | 2 +- testdata/fixtures/format3_sealed.json | 2 +- testdata/fixtures/format3_security_v2.json | 2 +- .../format3_signature_unsupported.json | 2 +- testdata/fixtures/format3_signed.json | 2 +- testdata/fixtures/format3_signed_cms.json | 2 +- testdata/fixtures/format3_single.json | 2 +- .../format3_time_and_key_portable.dkk.json | 2 +- .../format3_time_and_key_portable.json | 2 +- testdata/fixtures/format3_tree.json | 2 +- .../fixtures/time_and_key_portable.dkk.json | 2 +- testdata/fixtures/time_and_key_portable.json | 2 +- .../time_and_key_portable_extension.dkk.json | 2 +- .../fixtures/time_and_key_recipients.dkk.json | 2 +- .../fixtures/time_and_key_recipients.json | 2 +- testdata/fixtures/time_only.json | 2 +- testdata/fixtures/time_only_extensions.json | 2 +- testdata/vectors/cbor.json | 2 +- testdata/vectors/dk1.json | 2 +- testdata/vectors/ed25519_strict.json | 2 +- testdata/vectors/head_schema.json | 2 +- testdata/vectors/inspect_differential.json | 2 +- testdata/vectors/locator.json | 2 +- testdata/vectors/mutations.json | 2 +- testdata/vectors/padding.json | 2 +- testdata/vectors/path_fold.json | 2 +- testdata/vectors/paths.json | 2 +- testdata/vectors/profile_quicknet.json | 2 +- testdata/vectors/quicknet_rounds.json | 2 +- testdata/vectors/security.json | 2 +- testdata/vectors/security_cms.json | 2 +- testdata/vectors/tlock_ibe.json | 2 +- version.go | 6 ++--- 52 files changed, 140 insertions(+), 67 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5013713..6ebdf29 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,12 +3,12 @@ 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.11 (draft) +## Unreleased — specification v0.11 -Implements, on the branch `v0.11`, what the draft of the specification v0.11 -adds to format 3, without changing any format: a reader of v0.10 opens these -capsules. The text of the specification has not been approved yet, so the -module still reports `SpecVersion` 0.10. +Moves the module to the DateKeys Protocol Specification v0.11, approved by its +author on 1 October 2026 and tagged `spec-v0.11`, which adds to format 3 what +the v0.10 reserved, without changing any format: a reader of v0.10 opens these +capsules. `SpecVersion` is 0.11. - **Area of 32 KiB.** `capsule.AreaLen` is 32768, and `LargeAreaLen`, 65536, which `EncryptOptions.LargeArea` lets the writer use, after the signatures @@ -37,6 +37,12 @@ module still reports `SpecVersion` 0.10. - **Test data.** `format3_signed` and the vectors of its signature, and the fixtures `format3_signature_unsupported` and `format3_seal_unsupported` remade with `alg` 4294967295. +- **Review.** Three independent reviews, of the CMS reader, of the signing + logic and writer, and of the locator and the CLI, fixed the form of the + signature and of the TSTInfo field by field, the area decided after the + signatures, the text of an issuer on screen and the rules of the addresses; + spec §76 item 8 records them. Under a valid seal, `decrypt` shows an mtime + later than the seal as an inconsistency (§29.7). - **CLI.** `author keygen` and `author public`, `encrypt -sign`, `-note` and `-large-area`, and `decrypt -expect-author`. Passphrases come from a file or from the standard input. diff --git a/capsule/format3.go b/capsule/format3.go index ea6466f..de5f1e3 100644 --- a/capsule/format3.go +++ b/capsule/format3.go @@ -226,6 +226,31 @@ type SignerLine struct { Before bool } +// SealedAt returns the earliest instant that a valid seal gives, the seal of +// key 3 or that of a required signer of an alg 2 signature, and false when +// there is none (spec v0.11, §29.7). A reader shows an mtime later than it as +// an inconsistency: whoever made the capsule claims a file that is newer than +// the proof that it existed. +func (v Verdicts) SealedAt() (time.Time, bool) { + var best time.Time + take := func(t time.Time) { + if !t.IsZero() && (best.IsZero() || t.Before(best)) { + best = t + } + } + if v.Detail != nil { + if v.Seal == VerdictSealed || v.Seal == VerdictSealedLate { + take(v.Detail.SealTime) + } + for _, s := range v.Detail.Signers { + if s.Result == "valid" { + take(s.SealTime) + } + } + } + return best, !best.IsZero() +} + // Lines are the verdicts as the official SDK shows them, in order: X alone, // or the signature and then the seal, when it shows something. func (v Verdicts) Lines() []string { diff --git a/cmd/datekeys/author_test.go b/cmd/datekeys/author_test.go index eba6132..3ffcd1b 100644 --- a/cmd/datekeys/author_test.go +++ b/cmd/datekeys/author_test.go @@ -126,3 +126,18 @@ func TestPublicNoteCLI(t *testing.T) { t.Errorf("decrypt: %v\n%s", err, shown) } } + +// Spec v0.11 §29.7: under a valid seal, an mtime later than the seal is shown +// as an inconsistency. format3_sealed has a file dated 2026, sealed in 2023. +func TestMTimeAfterSeal(t *testing.T) { + out := filepath.Join(t.TempDir(), "out") + shown, _, err := cli(t, later, "decrypt", "-in", filepath.Join(fixtures, "format3_sealed.dkc"), "-out", out, "-relay", relay(t)) + if err != nil || !strings.Contains(shown, "aviso: la fecha de modificación de un fichero es posterior al sello (2023-08-23T15:09:27Z)") { + t.Errorf("%v\n%s", err, shown) + } + clean := filepath.Join(t.TempDir(), "out") + shown, _, err = cli(t, later, "decrypt", "-in", filepath.Join(fixtures, "format3_single.dkc"), "-out", clean, "-relay", relay(t)) + if err != nil || strings.Contains(shown, "no es coherente") { + t.Errorf("an unsealed capsule: %v\n%s", err, shown) + } +} diff --git a/cmd/datekeys/present.go b/cmd/datekeys/present.go index 9f97cb9..95ba4c6 100644 --- a/cmd/datekeys/present.go +++ b/cmd/datekeys/present.go @@ -5,6 +5,7 @@ import ( "io" "os" "strings" + "time" "g.activething.com/go/DateKeys/capsule" "g.activething.com/go/DateKeys/extension" @@ -107,6 +108,16 @@ func present(w io.Writer, o *capsule.Opened, dir string, width int) { fmt.Fprintln(w, line) } h := o.Head + // Spec v0.11 §29.7: under a valid seal, a modification time later than the + // instant of the seal is shown as an inconsistency. + if t, ok := o.Verdicts.SealedAt(); ok { + for _, f := range h.Files { + if f.HasMTime && time.Unix(int64(f.MTime), 0).After(t) { + fmt.Fprintf(w, " aviso: la fecha de modificación de un fichero es posterior al sello (%s): no es coherente.\n", t.UTC().Format(time.RFC3339)) + break + } + } + } if o.Inspection != nil && o.Inspection.Header != nil { if note, ok := o.Inspection.Header.PublicNote(); ok { fmt.Fprintln(w, "┌ "+noteTitle) diff --git a/spec/DateKeys_Protocol_Specification_v0.11.md b/spec/DateKeys_Protocol_Specification_v0.11.md index 781b095..7c3b287 100644 --- a/spec/DateKeys_Protocol_Specification_v0.11.md +++ b/spec/DateKeys_Protocol_Specification_v0.11.md @@ -3,7 +3,7 @@ ### Borrador normativo v0.11 **Estado:** Draft / pre-estándar -**Fecha:** 1 octubre 2026 (borrador en curso, sin aprobar) +**Fecha:** 1 octubre 2026, aprobado por su autor ese día **Proyecto:** DateKeys **Implementación de referencia prevista:** Go **Proveedor temporal V1:** drand Quicknet @@ -1327,7 +1327,7 @@ X es una sola línea, en lugar de la de la firma y la del sello. Un lector de la El SDK oficial MUST usar los textos de esta tabla. Otra implementación MUST usar esos textos o una traducción que no afirme más que ellos. -En los textos, ‹etiqueta› es la que la persona dio a una clave guardada (§29.12); ‹titulares›, el nombre del titular de cada certificado de los firmantes exigidos, tomado de su `subject` (`commonName`, o `givenName` y `surname`) sin su `serialNumber`, si cumple las reglas del autor declarado de §29.6, y si no, el SHA-256 del certificado en hexadecimal; ‹TSA›, el del titular del certificado de la autoridad de sellado, con las mismas reglas; y ‹t›, el instante del sello en UTC. Con F6, el lector MUST mostrar además una línea por firmante, con su titular, el emisor que dice su certificado y el instante de su sello, y decir si ese instante, más su precisión, es anterior a la fecha de apertura. Un `SignerInfo` cuyo certificado no está entre los exigidos se muestra aparte, con su resultado, y no cuenta (§29.10). +En los textos, ‹etiqueta› es la que la persona dio a una clave guardada (§29.12); ‹titulares›, el nombre del titular de cada certificado de los firmantes exigidos, tomado de su `subject` (`commonName`, o `givenName` y `surname`) sin su `serialNumber`, si cumple las reglas del autor declarado de §29.6, y si no, el SHA-256 del certificado en hexadecimal; ‹TSA›, el del titular del certificado de la autoridad de sellado, con las mismas reglas; y ‹t›, el instante del sello en UTC. Con F6, el lector MUST mostrar además una línea por firmante, con su titular, el emisor que dice su certificado y el instante de su sello, y decir si ese instante, más su precisión, es anterior a la fecha de apertura. Un `SignerInfo` cuyo certificado no está entre los exigidos se muestra aparte, con su resultado, y no cuenta (§29.10). El emisor que dice el certificado, en la línea de cada firmante, sigue las mismas reglas que el titular: si incumple las del autor declarado, se muestra el SHA-256 de su nombre en hexadecimal. Un lector MUST NOT decir que una cápsula se firmó antes de la fecha salvo por un sello válido con t + precisión < round_time, y entonces MUST decir que no comprueba quién emitió el sello: quien puede abrirla puede rehacer el área (§7.9). Con un sello válido, una mtime posterior a t SHOULD mostrarse como incoherencia. @@ -1427,6 +1427,14 @@ author-signature: 3. Cada `SignerInfo` identifica con su `sid`, por `issuerAndSerialNumber` o por `subjectKeyIdentifier`, exactamente un certificado de `certificates`, y ningún certificado tiene dos `SignerInfo`. Los certificados que ningún `SignerInfo` identifica no deciden nada: un validador externo puede usarlos como intermedios. En `crls` solo van respuestas OCSP (`OtherRevocationInfoFormat` con id-ri-ocsp-response, RFC 5940). 4. Cada `SignerInfo` lleva `signedAttrs` con exactamente un `content-type` (id-data), un `message-digest` y un `signing-certificate-v2` (RFC 5035) cuyo primer `ESSCertIDv2` da el hash de su certificado; y como mucho un atributo no firmado `signature-time-stamp` (id-aa-signatureTimeStampToken, 1.2.840.113549.1.9.16.2.14), con un solo valor. Los demás atributos, firmados o no, no deciden nada. +Sobre esa forma, un lector MUST aplicar además: + +- el `ContentInfo` y cada `SignerInfo` son SEQUENCE; la `version` de un `SignerInfo` es 1 con `issuerAndSerialNumber` y 3 con `subjectKeyIdentifier` (RFC 5652, §5.3); +- un atributo tiene al menos un valor, y un atributo de un tipo que esta sección pide una sola vez se cuenta por atributo y no por valor: dos atributos `content-type`, uno de ellos con un conjunto de valores vacío, incumplen la forma; +- un `signing-certificate` (RFC 2634) junto al `signing-certificate-v2` no decide nada: cuenta el v2; +- un `ESSCertIDv2` con el `hashAlgorithm` SHA-256 escrito de forma explícita se acepta, aunque sea su valor por defecto y DER no lo escriba, porque algunas aplicaciones de firma lo escriben; su hash MUST ser uno de la tabla de abajo, y SHA-1 incumple la forma; +- los parámetros de RSASSA-PSS van en el orden de sus etiquetas, sin repetir ninguno y sin escribir el `trailerField` que vale 1 por defecto: de otro modo, la firma no es verificable. + **Algoritmos.** Una tabla cerrada; el hash de la firma es el de `digestAlgorithm`: | Algoritmo | OID | @@ -1481,7 +1489,7 @@ seal: **Perfil del token**, en los dos sitios. Un lector comprueba, en este orden, y el resultado es el del primer fallo: -1. **Forma (S2):** DER de X.690; un `SignedData` con `eContentType` id-ct-TSTInfo (1.2.840.113549.1.9.16.1.4), su `eContent` y un solo `SignerInfo`; en él, `signedAttrs` con `content-type` id-ct-TSTInfo, `message-digest` y un `signing-certificate` (ESSCertID, cuyo SHA-1 solo identifica) o `signing-certificate-v2` que identifica el certificado de la TSA en `certificates`; y un `TSTInfo` de versión 1. +1. **Forma (S2):** DER de X.690; un `SignedData` con `eContentType` id-ct-TSTInfo (1.2.840.113549.1.9.16.1.4), su `eContent` y un solo `SignerInfo`; en él, `signedAttrs` con `content-type` id-ct-TSTInfo, `message-digest` y un `signing-certificate` (ESSCertID, cuyo SHA-1 solo identifica) o `signing-certificate-v2` que identifica el certificado de la TSA en `certificates`; y un `TSTInfo` de versión 1, en DER aunque vaya dentro de una cadena de bytes: `genTime` en UTC con la letra Z y una fracción sin cero final, `accuracy` con segundos de 0 en adelante y milisegundos y microsegundos de 1 a 999, `ordering` solo si es TRUE, los campos en su orden y ninguno después del último. 2. **Algoritmos (S1):** los de la tabla de §29.10, incluido el de `messageImprint`, que con `seal_type` 2 es SHA-256. 3. **Verificación (S3):** el `message-digest` es el hash del `eContent`, la firma de la TSA verifica, `messageImprint` es el hash de lo sellado, y el certificado de la TSA es válido en `genTime`. @@ -2050,7 +2058,7 @@ La extensión `datekeys.capsule`, versión 1, registrada para el array no críti 1 → desplazamiento (entero, opcional: 0 si falta) ``` - El plaintext mide exactamente 4096 bytes, o el menor múltiplo de 4096 en el que quepa: la clave 6 completa lo que falte, así que su longitud no delata cuántas direcciones hay ni de qué tipo. + El plaintext mide exactamente 4096 bytes, o el menor múltiplo de 4096 en el que quepa: la clave 6 completa lo que falte, así que su longitud no delata cuántas direcciones hay ni de qué tipo. Si ninguna longitud de la clave 6 completa un múltiplo exactamente, porque la longitud CBOR de su cadena de bytes cambia de tamaño en ese punto, se usa el múltiplo siguiente: una base de 4070 bytes sin la clave 6 da 8192. `locator.json` da los casos en torno a esos límites. **El sobre.** Quien crea la cápsula cifra el `.dkc` con `age` para la pública de `I_SOBRE`, una identity nueva de un CSPRNG, y parte ese fichero `age` en dos: la cabecera, hasta el salto de línea de su MAC incluido, que va en el localizador; y el resto, el nonce y los chunks de STREAM, que es lo único que se guarda fuera. El resto no lleva ninguna marca: sus bytes no se distinguen del azar, así que quien lo encuentra no sabe que es un fichero `age` ni una cápsula. Nadie, tampoco quien tiene la llave, lee el localizador antes de la fecha. En la fecha, el mismo release que abre la cápsula lo descifra, y el lector une la cabecera y el resto y descifra el `.dkc` con `I_SOBRE`. @@ -2059,7 +2067,7 @@ La extensión `datekeys.capsule`, versión 1, registrada para el array no críti - Es ocultación, no esteganografía: quien analice el huésped puede ver que lleva bytes de más, pero no qué son ni de qué cápsula. - Solo sirve un almacenamiento que conserva el fichero byte a byte, como un disco en la nube, IPFS o un servidor propio. Una red social o una aplicación de mensajería recomprimen las imágenes y los vídeos, o quitan lo que sobra, y el resto se pierde. -**Direcciones.** Cada URI es ASCII, de RFC 3986, con el esquema `https` o `ipfs` (un CID v1), sin userinfo. Un lector: +**Direcciones.** Cada URI es ASCII, de RFC 3986, con el esquema `https` o `ipfs` (un CID v1 en base32, que empieza por «b»), sin userinfo. Un lector lee la autoridad tal como está escrita, sin decodificar nada, y MUST rechazar la dirección si la autoridad lleva `%`, `@` o una barra invertida, si el puerto no es un número de 1 a 65535, si el host de un `https` no son letras, dígitos y guiones separados por puntos, o una dirección IP, que no sea de loopback, privada ni de enlace local, y si un nombre cuyo último segmento es numérico o empieza por `0x` no es una dirección IPv4 en notación decimal con puntos. Un nombre con letras que no son ASCII se escribe en su forma punycode. El host que muestra a la persona es ese texto, no el que daría una decodificación. Un lector: - MUST NOT descargar sin que la persona lo pida, y MUST mostrar antes el host o el CID: la descarga revela a quien controla la dirección cuándo y desde dónde se usa la llave, y en IPFS la ven la pasarela y los pares; - MUST pedir solo los bytes del resto, con un rango de HTTP si el servidor lo admite; si no, MUST dejar de leer al llegar al desplazamiento más `resto_size`; @@ -2736,7 +2744,7 @@ SHOULD: En formato 3, además, MUST: -13. **Área.** Escribir `AREA_LEN` = 32768 y `SECURITY_CBOR` en todas las cápsulas, lleve o no firma o sello, sin que dependa de lo que el escritor sepa hacer (§29.2). La única excepción es la ampliación expresa: si las firmas y sus evidencias no caben y quien crea la cápsula elige ampliar, `AREA_LEN` = 65536. MUST NOT ampliar por su cuenta ni descartar nada en silencio, y si no cabe en 65536, MUST rechazar la cápsula. Sin firma ni sello, `SECURITY_CBOR` va vacío: `{0: "datekeys-security", 1: 1}` (§29.3). Solo un generador de vectores de prueba MAY escribir otra área u otro `SECURITY_CBOR`, como los de `format3_area_1024`, `format3_security_v2`, `format3_signature_unsupported` y `format3_seal_unsupported` (§67). +13. **Área.** Escribir `AREA_LEN` = 32768 y `SECURITY_CBOR` en todas las cápsulas, lleve o no firma o sello, sin que dependa de lo que el escritor sepa hacer (§29.2). La única excepción es la ampliación expresa: si las firmas y sus evidencias no caben y quien crea la cápsula elige ampliar, `AREA_LEN` = 65536. MUST NOT ampliar por su cuenta ni descartar nada en silencio, y si no cabe en 65536, MUST rechazar la cápsula. El escritor decide el área después de hacer las firmas y los sellos, con lo que ocupan, y quien firmó no firma de nuevo por eso. Sin firma ni sello, `SECURITY_CBOR` va vacío: `{0: "datekeys-security", 1: 1}` (§29.3). Solo un generador de vectores de prueba MAY escribir otra área u otro `SECURITY_CBOR`, como los de `format3_area_1024`, `format3_security_v2`, `format3_signature_unsupported` y `format3_seal_unsupported` (§67). 14. **Head.** Escribir el head de versión 1 (§29.4): con una sal de un CSPRNG, nueva para cada cápsula; con al menos un fichero o un comentario; con las entradas en el orden de R8, con sus tamaños, su maquetación y el SHA-256 de los bytes que escribe; y de como mucho 16 MiB. 15. **Rutas y texto.** Rechazar una ruta o un texto que incumpla §29.5 o §29.6, con un mensaje que nombre la regla y el carácter, en lugar de corregirlo sin avisar. Guardar las rutas tal como llegan, rechazar un UTF-16 mal formado y no conservar carpetas vacías. El SDK oficial SHOULD excluir por defecto `.DS_Store`, `Thumbs.db`, `desktop.ini`, `._*` y `__MACOSX/`, y dejar ver y editar la lista antes de cifrar. 16. **mtime.** Si incluye la mtime de un fichero, tomarla de su fuente, al cargarlo: ⌊lastModified / 1000⌋ en un navegador, o `ModTime().Unix()` en Go; y omitirla si no la conoce o si cae fuera de 0 a 253402300799, sin recortarla. El SDK oficial SHOULD incluirla por defecto, con una opción para quitarla. @@ -4030,6 +4038,11 @@ La v0.11 define la firma de autor y el sello de tiempo del área `security`, que - Motivo: una aplicación que lista cápsulas y llaves solo puede distinguirlas hoy por `capsule_id`, y una llave suelta no dice de qué cápsula es ni dónde está. - Caso: una `.dkk` de la v0.10 lleva `capsule_id` y `capsule_digest`, nada legible para una persona. Y en IPFS un `.dkc` es público: un rastreador indexaría `capsule_id`, la nota y la fecha, y quien tiene la `.dkk` encontraría la cápsula antes de la fecha; por eso se guarda un sobre. - Pruebas previstas: la nota cambiada y la nota inválida, y los casos de `datekeys.capsule` (§64). +8. **Aclaraciones de la revisión adversarial** (§29.7, §29.10, §29.11, §44.1, §62.1 regla 13). + - Cambio: la forma de la firma CMS y del `TSTInfo` queda fijada campo a campo (versión del `SignerInfo` según su `sid`, atributos contados por atributo, `signing-certificate` junto al v2, `ESSCertIDv2` con SHA-256 explícito, parámetros de PSS, `accuracy` sin negativos, `genTime` en UTC con Z); el emisor de un certificado se muestra con las reglas del titular; las direcciones del localizador se leen sin decodificar y se rechazan los hosts que no son letras, dígitos y guiones y las IP que no son públicas; el relleno del localizador pasa al múltiplo siguiente cuando ninguna longitud encaja; y el área se decide después de firmar. + - Motivo: tres revisiones independientes, del lector CMS, de la lógica de firma y del escritor y del localizador, encontraron estas ambigüedades y fallos, todos con un caso que los reproduce. + - Caso: un sello con una `accuracy` negativa daba S4 a una cápsula sellada después de la fecha; un certificado con un nombre de emisor que lleva ESC y U+202E ponía líneas falsas en los veredictos; `https://%D0%B0pple.com/` se mostraba como un host con una «а» cirílica. + - Pruebas previstas: `security_cms.json` y `locator.json`, y los fixtures `format3_signed_cms` y `format3_sealed` (§64, §67). Con un lector de la v0.11 cambian de veredicto cinco vectores de la v0.10 que usaban `alg` 1 y `seal_type` 2 como no soportados: en `security.json`, «a signature of alg 1» y «a signature and a seal» pasan de F1 a F2, y «a seal of seal_type 2», de S1 a S2; y los fixtures `format3_signature_unsupported` y `format3_seal_unsupported`, de F1 a F2. Los casos no soportados se rehacen con `alg` y `seal_type` 4294967295 (§29.3), y los actuales quedan como casos de F2 y S2. Ningún otro objeto cambia de veredicto ni de código. Los vectores de la firma, del sello, de la nota y de la extensión de cápsula, y los de `control_commit`, `signers_digest`, `AUTHOR_MESSAGE` y `SEAL_SUBJECT` sobre `format3_single`, se añadirán a `testdata` con el paso 6 del plan de la firma. --- diff --git a/spec/README.md b/spec/README.md index db81367..863e178 100644 --- a/spec/README.md +++ b/spec/README.md @@ -23,19 +23,22 @@ §76 records each change with its reproducible case. - `DateKeys_Protocol_Specification_v0.10.md`: frozen copy of the normative draft v0.10 (30 September 2026), approved by its author on that date and - tagged `spec-v0.10`; this module implements it. SHA-256: + tagged `spec-v0.10`. SHA-256: `7f26419a444aa3e89a3aa8afbbba9d952af69e048aee1e93cd70732c2d1d99d1`. It adds capsule format 3, which stores several files with their paths, sizes, hashes and dates, encrypted, and reserves the `security` area for an author signature and a timestamp seal that later versions will define without changing the format. Its §76 records each change with its reproducible case. -- `DateKeys_Protocol_Specification_v0.11.md`: the draft v0.11, work in - progress and not approved. It defines the author signature of format 3, - with an Ed25519 key of one's own or with X.509 certificates (CMS, one or - several signers, a CAdES-T timestamp each), the RFC 3161 seal, a fixed - area of 32 KiB, the key of words, the public note and the capsule - extension of the .dkk. Its §76 records each change with its case. -- `datekeys.cddl`: the CBOR schemas of the v0.10 draft, the three control +- `DateKeys_Protocol_Specification_v0.11.md`: frozen copy of the normative + draft v0.11 (1 October 2026), approved by its author on that date and + tagged `spec-v0.11`; this module implements it. SHA-256: + `25cf1039d16666199c662e88e838a1d2ef0507be68e17fecd9aeee5d85a5bb6e`. + It defines the author signature of format 3, with an Ed25519 key of one's + own or with X.509 certificates (CMS, one or several signers, a CAdES-T + timestamp each), the RFC 3161 seal, a fixed area of 32 KiB, the key of + words, the public note and the capsule extension of the .dkk. Its §76 + records each change with its reproducible case. +- `datekeys.cddl`: the CBOR schemas of the v0.11 draft, the three control versions and the security and head objects of format 3 included, with the encoding rules CDDL cannot express. Those of v0.9 and v0.8.2 are at the tags `spec-v0.9` and `spec-v0.8.2`. diff --git a/testdata/fixtures/empty_payload.json b/testdata/fixtures/empty_payload.json index 3899f77..5635a6a 100644 --- a/testdata/fixtures/empty_payload.json +++ b/testdata/fixtures/empty_payload.json @@ -1,6 +1,6 @@ { "description": "time_only capsule with an empty payload", - "spec": "0.10", + "spec": "0.11", "format": 1, "file": "empty_payload.dkc", "sha256": "871e9bf05b52bbae17f3adfbbf97b46e7f0e53aa8f57bcaa506e43f36f53a9d4", diff --git a/testdata/fixtures/format2_empty_payload.json b/testdata/fixtures/format2_empty_payload.json index 8fdf39f..e8fdf9b 100644 --- a/testdata/fixtures/format2_empty_payload.json +++ b/testdata/fixtures/format2_empty_payload.json @@ -1,6 +1,6 @@ { "description": "format 2 time_only capsule with an empty content: L = 0, P = 256", - "spec": "0.10", + "spec": "0.11", "format": 2, "file": "format2_empty_payload.dkc", "sha256": "7aea2b5aa48b1a46053716f733d50fab9cd0b80b1be67631bcc06c5bb765dc21", diff --git a/testdata/fixtures/format2_time_and_key_portable.dkk.json b/testdata/fixtures/format2_time_and_key_portable.dkk.json index 79fcb68..174c9a6 100644 --- a/testdata/fixtures/format2_time_and_key_portable.dkk.json +++ b/testdata/fixtures/format2_time_and_key_portable.dkk.json @@ -1,6 +1,6 @@ { "description": "portable X25519 .dkk of format2_time_and_key_portable.dkc", - "spec": "0.10", + "spec": "0.11", "file": "format2_time_and_key_portable.dkk", "sha256": "095b7bc516a22bf0c2366f0af3cd48bfe857a2354d6e2a9b285278b95e450fe0", "credential_id": "e3c7be83cbf1fbd6b115c96411b3bd01", diff --git a/testdata/fixtures/format2_time_and_key_portable.json b/testdata/fixtures/format2_time_and_key_portable.json index 48599df..48e9301 100644 --- a/testdata/fixtures/format2_time_and_key_portable.json +++ b/testdata/fixtures/format2_time_and_key_portable.json @@ -1,6 +1,6 @@ { "description": "format 2 time_and_key capsule with one credential, a portable .dkk, and 15 dummies", - "spec": "0.10", + "spec": "0.11", "format": 2, "file": "format2_time_and_key_portable.dkc", "sha256": "600892659fe4890223e895876275f656995d170fda42b07fb2bec0ca51ce4b43", diff --git a/testdata/fixtures/format2_time_and_key_recipients.dkk.json b/testdata/fixtures/format2_time_and_key_recipients.dkk.json index 5cd0a66..077f928 100644 --- a/testdata/fixtures/format2_time_and_key_recipients.dkk.json +++ b/testdata/fixtures/format2_time_and_key_recipients.dkk.json @@ -1,6 +1,6 @@ { "description": "portable X25519 .dkk of format2_time_and_key_recipients.dkc", - "spec": "0.10", + "spec": "0.11", "file": "format2_time_and_key_recipients.dkk", "sha256": "2ad99b1556086ec311d7f0b3bd3aaba05e75f45c4fa22490b0d5e8bb0b1a222e", "credential_id": "93cedf68421710e83908ec683b104436", diff --git a/testdata/fixtures/format2_time_and_key_recipients.json b/testdata/fixtures/format2_time_and_key_recipients.json index d453028..9cf68cf 100644 --- a/testdata/fixtures/format2_time_and_key_recipients.json +++ b/testdata/fixtures/format2_time_and_key_recipients.json @@ -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.10", + "spec": "0.11", "format": 2, "file": "format2_time_and_key_recipients.dkc", "sha256": "1a44fd8708c92e2e0a10cfcb1d864a71331ea9af25d97e1a42e969dc898959e3", diff --git a/testdata/fixtures/format2_time_and_key_sixteen.json b/testdata/fixtures/format2_time_and_key_sixteen.json index 4cbd5c5..f68f0e8 100644 --- a/testdata/fixtures/format2_time_and_key_sixteen.json +++ b/testdata/fixtures/format2_time_and_key_sixteen.json @@ -1,6 +1,6 @@ { "description": "format 2 time_and_key capsule for sixteen known X25519 recipients, without dummies", - "spec": "0.10", + "spec": "0.11", "format": 2, "file": "format2_time_and_key_sixteen.dkc", "sha256": "7aaac5c18f216bf53df326ecc817179640a53408cf25dfd50488910a762dc381", diff --git a/testdata/fixtures/format2_time_only.json b/testdata/fixtures/format2_time_only.json index b653845..b512421 100644 --- a/testdata/fixtures/format2_time_only.json +++ b/testdata/fixtures/format2_time_only.json @@ -1,6 +1,6 @@ { "description": "format 2 time_only capsule, padding code 2 (reforzado): L = 78000, P = 79872, two STREAM chunks", - "spec": "0.10", + "spec": "0.11", "format": 2, "file": "format2_time_only.dkc", "sha256": "f5a40ac6b8a08a0c12db6114c2bca23522d6a77b512b509a217fb15f367813c4", diff --git a/testdata/fixtures/format2_time_only_bloque256.json b/testdata/fixtures/format2_time_only_bloque256.json index e8ffc84..e33a559 100644 --- a/testdata/fixtures/format2_time_only_bloque256.json +++ b/testdata/fixtures/format2_time_only_bloque256.json @@ -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.10", + "spec": "0.11", "format": 2, "file": "format2_time_only_bloque256.dkc", "sha256": "aae769c30d04920801d8b293d30864fbe223c9c9353ec2b4907a1ee1996e39f9", diff --git a/testdata/fixtures/format2_time_only_extensions.json b/testdata/fixtures/format2_time_only_extensions.json index 2bba812..5ed3d23 100644 --- a/testdata/fixtures/format2_time_only_extensions.json +++ b/testdata/fixtures/format2_time_only_extensions.json @@ -1,6 +1,6 @@ { "description": "format 2 time_only capsule with a noncritical PUBLIC_HEADER extension and a noncritical CONTROL_CBOR extension", - "spec": "0.10", + "spec": "0.11", "format": 2, "file": "format2_time_only_extensions.dkc", "sha256": "fb406100d5703a2e888983b3175ed34a09a34469cc722256e5cf535dd728fbe9", diff --git a/testdata/fixtures/format3_area_1024.json b/testdata/fixtures/format3_area_1024.json index 54a0756..b3a0fd8 100644 --- a/testdata/fixtures/format3_area_1024.json +++ b/testdata/fixtures/format3_area_1024.json @@ -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.10", + "spec": "0.11", "format": 3, "file": "format3_area_1024.dkc", "sha256": "41ea2eed0293e4fef7f4a307b7f16aaf1339f5bf6f4ded7a6a9ae1aebeb0133c", diff --git a/testdata/fixtures/format3_bloque256.json b/testdata/fixtures/format3_bloque256.json index 4dc1d3b..71902ca 100644 --- a/testdata/fixtures/format3_bloque256.json +++ b/testdata/fixtures/format3_bloque256.json @@ -1,6 +1,6 @@ { "description": "format 3 time_only capsule with padding code 1 (bloque256) and one file of 20000 bytes", - "spec": "0.10", + "spec": "0.11", "format": 3, "file": "format3_bloque256.dkc", "sha256": "ff18444f434164ba8e7b26d38c76c7855dc6b0593b2fc8b4e9a95dbf9252d55d", diff --git a/testdata/fixtures/format3_comment_only.json b/testdata/fixtures/format3_comment_only.json index a67fa75..455aa3e 100644 --- a/testdata/fixtures/format3_comment_only.json +++ b/testdata/fixtures/format3_comment_only.json @@ -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.10", + "spec": "0.11", "format": 3, "file": "format3_comment_only.dkc", "sha256": "7f98a89413f08655bbbab28b96585dfa6173c1705dd81a900deba2100d19f2ef", diff --git a/testdata/fixtures/format3_seal_unsupported.json b/testdata/fixtures/format3_seal_unsupported.json index 0ace98c..a82f20c 100644 --- a/testdata/fixtures/format3_seal_unsupported.json +++ b/testdata/fixtures/format3_seal_unsupported.json @@ -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 1 with a random token of 32 bytes: verdicts F1 and S1", - "spec": "0.10", + "spec": "0.11", "format": 3, "file": "format3_seal_unsupported.dkc", "sha256": "cd3f68e430c8d41df92a364d65fe29b4aed8ec50e5129595735ede6a8d7df88b", diff --git a/testdata/fixtures/format3_sealed.json b/testdata/fixtures/format3_sealed.json index 50a3d5f..4b61906 100644 --- a/testdata/fixtures/format3_sealed.json +++ b/testdata/fixtures/format3_sealed.json @@ -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.10", + "spec": "0.11", "format": 3, "file": "format3_sealed.dkc", "sha256": "dde5a072d8783227d28279d06d3d226a1fb967c766da626f889d1c6fd76ac9c7", diff --git a/testdata/fixtures/format3_security_v2.json b/testdata/fixtures/format3_security_v2.json index 2ad6a5e..15700b5 100644 --- a/testdata/fixtures/format3_security_v2.json +++ b/testdata/fixtures/format3_security_v2.json @@ -1,6 +1,6 @@ { "description": "format 3 time_only capsule whose security is of version 2: verdict X", - "spec": "0.10", + "spec": "0.11", "format": 3, "file": "format3_security_v2.dkc", "sha256": "3d02b39ace010d74604554e378d22fe5ce00cecd998c0f797d657b17620b8912", diff --git a/testdata/fixtures/format3_signature_unsupported.json b/testdata/fixtures/format3_signature_unsupported.json index 3d457d5..0b7aaae 100644 --- a/testdata/fixtures/format3_signature_unsupported.json +++ b/testdata/fixtures/format3_signature_unsupported.json @@ -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.10", + "spec": "0.11", "format": 3, "file": "format3_signature_unsupported.dkc", "sha256": "e8e3106d8d73bb7b845062e0fe42af21df7d7cd8f63c335cab8dedb3e690df31", diff --git a/testdata/fixtures/format3_signed.json b/testdata/fixtures/format3_signed.json index 3041726..b24064c 100644 --- a/testdata/fixtures/format3_signed.json +++ b/testdata/fixtures/format3_signed.json @@ -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.10", + "spec": "0.11", "format": 3, "file": "format3_signed.dkc", "sha256": "3c7d3c9e24c02853a0c7761b93bea1120b27fce396468d8d0f68e53aeb668c5e", diff --git a/testdata/fixtures/format3_signed_cms.json b/testdata/fixtures/format3_signed_cms.json index 085d773..2d4813e 100644 --- a/testdata/fixtures/format3_signed_cms.json +++ b/testdata/fixtures/format3_signed_cms.json @@ -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.10", + "spec": "0.11", "format": 3, "file": "format3_signed_cms.dkc", "sha256": "d658f8d5ac2c5550c07b8f8fd6883b2f6dc02ceafc47d436ea02d8950b2548d2", diff --git a/testdata/fixtures/format3_single.json b/testdata/fixtures/format3_single.json index 3b45683..002ad2a 100644 --- a/testdata/fixtures/format3_single.json +++ b/testdata/fixtures/format3_single.json @@ -1,6 +1,6 @@ { "description": "format 3 time_only capsule with a single file, nota.txt, with its mtime", - "spec": "0.10", + "spec": "0.11", "format": 3, "file": "format3_single.dkc", "sha256": "9f68664af8733255084be9036a100b75d27bd16106bf0acff94ce469dd1d1743", diff --git a/testdata/fixtures/format3_time_and_key_portable.dkk.json b/testdata/fixtures/format3_time_and_key_portable.dkk.json index 9ded6e4..0882b2b 100644 --- a/testdata/fixtures/format3_time_and_key_portable.dkk.json +++ b/testdata/fixtures/format3_time_and_key_portable.dkk.json @@ -1,6 +1,6 @@ { "description": "portable X25519 .dkk of format3_time_and_key_portable.dkc", - "spec": "0.10", + "spec": "0.11", "file": "format3_time_and_key_portable.dkk", "sha256": "54cc64d849395234b3e093e47f432b72781ccc13f455c9ef394e3554ab566751", "credential_id": "bdb483fba42daf0b409f44d23033f362", diff --git a/testdata/fixtures/format3_time_and_key_portable.json b/testdata/fixtures/format3_time_and_key_portable.json index c577e8b..b17e49e 100644 --- a/testdata/fixtures/format3_time_and_key_portable.json +++ b/testdata/fixtures/format3_time_and_key_portable.json @@ -1,6 +1,6 @@ { "description": "format 3 time_and_key capsule with one credential, a portable .dkk, and 15 dummies", - "spec": "0.10", + "spec": "0.11", "format": 3, "file": "format3_time_and_key_portable.dkc", "sha256": "680d29962e575689a31543df28433dae7737abd9a793e9cae92ef40920d09636", diff --git a/testdata/fixtures/format3_tree.json b/testdata/fixtures/format3_tree.json index 34d418e..19145d1 100644 --- a/testdata/fixtures/format3_tree.json +++ b/testdata/fixtures/format3_tree.json @@ -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.10", + "spec": "0.11", "format": 3, "file": "format3_tree.dkc", "sha256": "217f378faaf795f6a9c416b564fb8931bb2e896918aee870120fd14f9a5da7d1", diff --git a/testdata/fixtures/time_and_key_portable.dkk.json b/testdata/fixtures/time_and_key_portable.dkk.json index 4a2ff4d..32c7264 100644 --- a/testdata/fixtures/time_and_key_portable.dkk.json +++ b/testdata/fixtures/time_and_key_portable.dkk.json @@ -1,6 +1,6 @@ { "description": "portable X25519 .dkk of time_and_key_portable.dkc", - "spec": "0.10", + "spec": "0.11", "file": "time_and_key_portable.dkk", "sha256": "e528fa2c832c91119f0684bb9d6fb3c4c2d0d55183482890e7c4fe92f668426a", "credential_id": "3955e944a3c60cfa1fd6485e9693c77d", diff --git a/testdata/fixtures/time_and_key_portable.json b/testdata/fixtures/time_and_key_portable.json index d57efe6..535b9e9 100644 --- a/testdata/fixtures/time_and_key_portable.json +++ b/testdata/fixtures/time_and_key_portable.json @@ -1,6 +1,6 @@ { "description": "time_and_key capsule whose only recipient is a portable .dkk", - "spec": "0.10", + "spec": "0.11", "format": 1, "file": "time_and_key_portable.dkc", "sha256": "2e97878078bae6358037a9c264f379a3cbe839f767d69836b0343f35657b2972", diff --git a/testdata/fixtures/time_and_key_portable_extension.dkk.json b/testdata/fixtures/time_and_key_portable_extension.dkk.json index 1ed6121..904069d 100644 --- a/testdata/fixtures/time_and_key_portable_extension.dkk.json +++ b/testdata/fixtures/time_and_key_portable_extension.dkk.json @@ -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.10", + "spec": "0.11", "file": "time_and_key_portable_extension.dkk", "sha256": "0bf463a7c65627b7dda2234d728df89ec5b835816a2a37b91497d8fecc5ea548", "credential_id": "3955e944a3c60cfa1fd6485e9693c77d", diff --git a/testdata/fixtures/time_and_key_recipients.dkk.json b/testdata/fixtures/time_and_key_recipients.dkk.json index 4fd9722..8d63d98 100644 --- a/testdata/fixtures/time_and_key_recipients.dkk.json +++ b/testdata/fixtures/time_and_key_recipients.dkk.json @@ -1,6 +1,6 @@ { "description": "portable X25519 .dkk of time_and_key_recipients.dkc", - "spec": "0.10", + "spec": "0.11", "file": "time_and_key_recipients.dkk", "sha256": "19f6c47150c3194712d454f43c7392b7344e6b4e7b074d83e9ca5f563a8e072f", "credential_id": "b89292aedf6d05d584cec9a871ce8735", diff --git a/testdata/fixtures/time_and_key_recipients.json b/testdata/fixtures/time_and_key_recipients.json index 1ea76ed..5d83caa 100644 --- a/testdata/fixtures/time_and_key_recipients.json +++ b/testdata/fixtures/time_and_key_recipients.json @@ -1,6 +1,6 @@ { "description": "time_and_key capsule for two known X25519 recipients and a portable .dkk", - "spec": "0.10", + "spec": "0.11", "format": 1, "file": "time_and_key_recipients.dkc", "sha256": "69ac110380f5d768b5b6afaa157a50ed17d8ceccfbd4604ffa5b6da38539b635", diff --git a/testdata/fixtures/time_only.json b/testdata/fixtures/time_only.json index dc11d03..ac9576d 100644 --- a/testdata/fixtures/time_only.json +++ b/testdata/fixtures/time_only.json @@ -1,6 +1,6 @@ { "description": "time_only capsule, two STREAM chunks, no extensions", - "spec": "0.10", + "spec": "0.11", "format": 1, "file": "time_only.dkc", "sha256": "99e915810d595f1092700b728f5e5081d78efe83f5343e76325b1bcc2c33ccf2", diff --git a/testdata/fixtures/time_only_extensions.json b/testdata/fixtures/time_only_extensions.json index 10fddeb..65e2fd9 100644 --- a/testdata/fixtures/time_only_extensions.json +++ b/testdata/fixtures/time_only_extensions.json @@ -1,6 +1,6 @@ { "description": "time_only capsule with a noncritical PUBLIC_HEADER extension and a noncritical CONTROL_CBOR extension", - "spec": "0.10", + "spec": "0.11", "format": 1, "file": "time_only_extensions.dkc", "sha256": "0446c9b73e267adcb24e5cc89afba2544a386ec9a050016e06517a4a57aa2085", diff --git a/testdata/vectors/cbor.json b/testdata/vectors/cbor.json index 4202ede..fafd867 100644 --- a/testdata/vectors/cbor.json +++ b/testdata/vectors/cbor.json @@ -1,5 +1,5 @@ { - "spec": "0.10", + "spec": "0.11", "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, diff --git a/testdata/vectors/dk1.json b/testdata/vectors/dk1.json index e5ba4fc..f9e4d3e 100644 --- a/testdata/vectors/dk1.json +++ b/testdata/vectors/dk1.json @@ -1,5 +1,5 @@ { - "spec": "0.10", + "spec": "0.11", "description": "Canonical dk1_ strings and rejected encodings (spec §18, §19, §66), generated by the reference implementation.", "vectors": [ { diff --git a/testdata/vectors/ed25519_strict.json b/testdata/vectors/ed25519_strict.json index bb5227c..027ba46 100644 --- a/testdata/vectors/ed25519_strict.json +++ b/testdata/vectors/ed25519_strict.json @@ -1,5 +1,5 @@ { - "spec": "0.10", + "spec": "0.11", "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": [ { diff --git a/testdata/vectors/head_schema.json b/testdata/vectors/head_schema.json index cc79b19..ea79eef 100644 --- a/testdata/vectors/head_schema.json +++ b/testdata/vectors/head_schema.json @@ -1,5 +1,5 @@ { - "spec": "0.10", + "spec": "0.11", "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": [ { diff --git a/testdata/vectors/inspect_differential.json b/testdata/vectors/inspect_differential.json index a6f8ecc..dbd21d3 100644 --- a/testdata/vectors/inspect_differential.json +++ b/testdata/vectors/inspect_differential.json @@ -1,5 +1,5 @@ { - "spec": "0.10", + "spec": "0.11", "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, diff --git a/testdata/vectors/locator.json b/testdata/vectors/locator.json index f124ade..a2b72aa 100644 --- a/testdata/vectors/locator.json +++ b/testdata/vectors/locator.json @@ -1,6 +1,6 @@ { "description": "The extension datekeys.capsule of a .dkk and what it points to (spec v0.11, 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. Frozen. See testdata/README.md.", - "spec": "0.10", + "spec": "0.11", "round": 1000, "datekey": "dk1_eyJ2ZXJzaW9uIjoxLCJuZXR3b3JrIjoiZGF0ZWtleXM6cXVpY2tuZXQ6djEiLCJyb3VuZCI6MTAwMH0", "note": "Cartas del viaje a Lisboa", diff --git a/testdata/vectors/mutations.json b/testdata/vectors/mutations.json index a106cea..7bc7e37 100644 --- a/testdata/vectors/mutations.json +++ b/testdata/vectors/mutations.json @@ -1,5 +1,5 @@ { - "spec": "0.10", + "spec": "0.11", "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": [ { diff --git a/testdata/vectors/padding.json b/testdata/vectors/padding.json index a982752..1fee966 100644 --- a/testdata/vectors/padding.json +++ b/testdata/vectors/padding.json @@ -1,5 +1,5 @@ { - "spec": "0.10", + "spec": "0.11", "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": [ diff --git a/testdata/vectors/path_fold.json b/testdata/vectors/path_fold.json index 21c043d..cd4ccea 100644 --- a/testdata/vectors/path_fold.json +++ b/testdata/vectors/path_fold.json @@ -1,5 +1,5 @@ { - "spec": "0.10", + "spec": "0.11", "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", diff --git a/testdata/vectors/paths.json b/testdata/vectors/paths.json index e9125ec..e8d4318 100644 --- a/testdata/vectors/paths.json +++ b/testdata/vectors/paths.json @@ -1,5 +1,5 @@ { - "spec": "0.10", + "spec": "0.11", "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", diff --git a/testdata/vectors/profile_quicknet.json b/testdata/vectors/profile_quicknet.json index ff60352..de68fdf 100644 --- a/testdata/vectors/profile_quicknet.json +++ b/testdata/vectors/profile_quicknet.json @@ -1,5 +1,5 @@ { - "spec": "0.10", + "spec": "0.11", "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", diff --git a/testdata/vectors/quicknet_rounds.json b/testdata/vectors/quicknet_rounds.json index 84d73f1..20c2ddc 100644 --- a/testdata/vectors/quicknet_rounds.json +++ b/testdata/vectors/quicknet_rounds.json @@ -1,5 +1,5 @@ { - "spec": "0.10", + "spec": "0.11", "profile": "datekeys:quicknet:v1", "description": "Quicknet date to round resolution (spec §15, §16, §65), generated by the reference implementation.", "vectors": [ diff --git a/testdata/vectors/security.json b/testdata/vectors/security.json index 4f0f92b..640137d 100644 --- a/testdata/vectors/security.json +++ b/testdata/vectors/security.json @@ -1,5 +1,5 @@ { - "spec": "0.10", + "spec": "0.11", "description": "SECURITY_CBOR of format 3, exactly its SECURITY_LEN bytes, and the verdicts of the signature and of the seal (spec §29.3, §29.7), generated by the reference implementation, which implements no alg and no seal_type. See testdata/README.md.", "vectors": [ { diff --git a/testdata/vectors/security_cms.json b/testdata/vectors/security_cms.json index 227b339..74f8958 100644 --- a/testdata/vectors/security_cms.json +++ b/testdata/vectors/security_cms.json @@ -1,6 +1,6 @@ { "description": "SECURITY_CBOR with an author signature of alg 2 or a time seal of seal_type 2, its context and the verdicts of spec v0.11 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.10", + "spec": "0.11", "cases": [ { "name": "alg 2: two signers, each sealed before the round time", diff --git a/testdata/vectors/tlock_ibe.json b/testdata/vectors/tlock_ibe.json index a0aa127..dc16e05 100644 --- a/testdata/vectors/tlock_ibe.json +++ b/testdata/vectors/tlock_ibe.json @@ -1,5 +1,5 @@ { - "spec": "0.10", + "spec": "0.11", "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": [ { diff --git a/version.go b/version.go index 0427c3f..7ef6dc2 100644 --- a/version.go +++ b/version.go @@ -6,11 +6,11 @@ import ( ) // SpecVersion is the version of the DateKeys Protocol Specification that this -// module implements: spec/DateKeys_Protocol_Specification_v0.10.md, tagged -// spec-v0.10 in its repository. It is neither the version of the module (see +// 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 // Version) nor the versions inside the objects: the capsule format, 1 to 3, // and the schema versions (spec §22, §70). -const SpecVersion = "0.10" +const SpecVersion = "0.11" // modulePath is the path of this module: the import path of its root // package, whatever the module is called.