diff --git a/HANDOFF.md b/HANDOFF.md index 898df4c..c0e2580 100644 --- a/HANDOFF.md +++ b/HANDOFF.md @@ -16,7 +16,7 @@ Sirve para retomar sin contexto previo, sea una persona o una sesión de Claude. | Repo | Rama y commit | Tags | Qué es | |---|---|---|---| | `datekeys-go` | `v0.16` y `main` en `b6ff17a`; `v0.15` en `70d907b` | `spec-v0.16` en `b6ff17a`, y los de las versiones anteriores | Spec v0.16 aprobada, implementación de referencia, `testdata` compartido. En `v0.15`, tras su tag: `c49c67c` las palabras al azar, `27a75ee` el alfabeto de cada lista y la fuerza de las palabras, `96d8992` arregla `TestGenerate`, `e671032` la lista inglesa de la EFF, `92e7154` los dados, `aefc8f6` lo que dice el SDK al sellar y `70d907b` la licencia CC BY-ND 4.0. En `v0.16`: el borrador (`a2b71c2`, `2c29625`), su implementación (`7e3b810` a `3fd0e93`) y el cierre (`b6ff17a`) | -| `App` (`datekeys-ts`) | `v0.10` en `c74a37e`; `main` en `7650418` | `v0.4.0` en `7650418`, `v0.3.0`, `v0.2.0`, `v0.1.0` | Librería TypeScript `0.5.0-dev`, de la spec 0.16, y páginas `/inspect` y `/create`, con las palabras al azar; la última publicada es la 0.4.0, de la spec 0.15 | +| `App` (`datekeys-ts`) | `v0.10` y `main` en `2c305cf` | `v0.5.0` en `2c305cf`, `v0.4.0`, `v0.3.0`, `v0.2.0`, `v0.1.0` | Librería TypeScript `0.5.0`, publicada el 7-10, de la spec 0.16, y páginas `/inspect` y `/create`, con las palabras al azar | | `datekeys-dart` | `v0.16` en `b53afdc`; `v0.15` en `e2296b0` | ninguno | Librería Dart completa, de la spec 0.16, con las palabras al azar; las ramas `v0.11` a `v0.15` se quedan atrás | | `docs` | `main` | — | Este repo | | `web` | `main` en `f2b8a38` | — | Landing de datekeys.com, sin remoto | @@ -25,7 +25,7 @@ Sirve para retomar sin contexto previo, sea una persona o una sesión de Claude. - **El fichero `.dkr` se descartó** antes de aprobar (7-10). El autor no lo había aprobado conscientemente, y no tiene sentido: al crear la cápsula no hay release que guardar, y cuando llega la ronda la cápsula ya se abre. El objeto release no tiene extensión propia; sale de un archivo o de un servicio de caché. El §76 lo registra. - **Las tres implementaciones** coinciden en todos los vectores compartidos de `datekeys-go/testdata` en `spec-v0.16` (`b6ff17a`), 150 ficheros, de donde TypeScript y Dart copian hoy `testdata`, `wordlists` y `annex`. Gates el 7-10 por la noche: - Go: `scripts/check.sh` entero en `4f78854`, en `3fd0e93` y en `b6ff17a`, con el anexo abriendo con palabras y con un último bloque completo; en la v0.15, `scripts/fuzz.sh 20s` en `fe50885` con sus 27 objetivos, sin fallos; - - TypeScript: `npm run verify` en `c74a37e`, con 8 273 pruebas; + - TypeScript: `npm run verify` en `c74a37e` y en `2c305cf`, la `0.5.0`, con 8 273 pruebas; - Dart: `tool/check.sh` en `b53afdc`, con 2 286 pruebas en la VM y 720 en Node. - **Palabras al azar (7-10, después de cerrar la v0.15):** es el SHOULD de §38.1 de ofrecer palabras generadas; no cambia ningún formato ni la derivación. - Go: `c49c67c` añade `wordkey.Generate`, `List` y `CheckList`, y `datekeys encrypt -new-words FICHERO [-dic es] [-word-count 7]`. `27a75ee` hace que `CheckList(lang, words)` compruebe cada palabra contra el alfabeto de su idioma, que da el código y no la lista (para `es`, de la `a` a la `z`, `á`, `é`, `í`, `ó`, `ú`, `ü` y `ñ`, en minúscula y NFC): una letra cirílica que parece latina, una mayúscula, una cifra o el retorno de carro de un fichero CRLF dejarían la cápsula sin abrir. También añade `Bits`, la fuerza de lo sorteado, que `encrypt` muestra (90 bits para 7 de 7 776). `scripts/check.sh` pasa entero en los dos. @@ -45,7 +45,7 @@ Sirve para retomar sin contexto previo, sea una persona o una sesión de Claude. - **El estado del perfil** (§71): `profile.Status`/`StatusOf` en Go, `profileStatusOf` en TypeScript, con la tabla de los perfiles fijados que trae cada versión, porque el registro firmado no existe: Quicknet, activo. Con un perfil que no esté activo no se escribe ninguna cápsula, y `decrypt`, `inspect` e `/inspect` avisan si el de una cápsula está comprometido. - Go `aefc8f6` y `6158be2`, TypeScript `728c3bb` y `e8b5d35`, Dart `8eed96f` y `e2296b0` (de un agente Opus revisado contra Go: el anexo es una constante generada, `lib/src/recovery_annex.g.dart`, que escribe `tool/recovery_annex_copy.dart` tras cada sincronización que cambie `annex/`). - **La licencia** (7-10, decisión del autor): el spec y su anexo son CC BY-ND 4.0, no CC BY 4.0, que no le gustaba. Se pueden copiar y compartir sin cambios, citando su origen; una versión modificada o una traducción necesita su permiso por escrito. El anexo lo dice en su cabecera (`70d907b`). Las listas de palabras conservan las suyas. -- **La revisión externa:** el paquete de [revision_externa/](revision_externa/NOTA_PARA_EL_AUTOR.md) está al día con la v0.15. Su nota dice qué decidió el autor y qué falta: elegir revisor, alcance y presupuesto, el NDA, los bundles y el envío. +- **La revisión externa:** el paquete de [revision_externa/](revision_externa/NOTA_PARA_EL_AUTOR.md) está al día con la v0.16. Su nota dice qué decidió el autor y qué falta: elegir revisor, alcance y presupuesto, el NDA, los bundles y el envío. --- @@ -60,7 +60,8 @@ La recuperación a largo plazo quedó hecha con la v0.15, las palabras al azar e - TypeScript (`f79d8e2`, `59d7607`, `c74a37e`) y Dart (`290d97e`, `0609e9e`, `b53afdc`), de dos agentes Opus revisados contra Go. TypeScript usa también el lector estricto para un release pegado en la página. Dart regeneró sus vectores propios desde un `git archive` de Go. - Un tropiezo: las herramientas de edición convierten un escape `\u0072` en el carácter. Los casos «escaped as» de `release.json` llevaban un `round` llano en `b570338`; lo vio el agente de TypeScript y se arregló en `3fd0e93`. Ver la memoria. - No hay paquete de recuperación (decisión 5): el anexo nombra `UnicodeData.txt` por su SHA-256. - - **Lo siguiente:** poner al día el paquete de la revisión externa, que sigue en la v0.15 y congela TypeScript en la `0.4.0`. Para congelar la v0.16 hace falta una versión publicada de TypeScript, quizá la `0.5.0`, con las palabras al azar y la v0.16: es decisión del autor. + - **TypeScript 0.5.0** (7-10, «sí» del autor): tag `v0.5.0` en `2c305cf`, `main` movido; la v0.16, las palabras al azar con dados y lo que dice el SDK al sellar. + - **El paquete de la revisión externa** está al día con la v0.16: congela `spec-v0.16` (`b6ff17a`), TypeScript `v0.5.0` y Dart `b53afdc`; gana Q13, sobre los cambios de la v0.16, y cierra K17. Ver su [nota](revision_externa/NOTA_PARA_EL_AUTOR.md). - Las reglas 21 y 22 de la v0.16 (guardar las cadenas y las respuestas OCSP, decir lo que queda fuera) no tienen código: ningún escritor de las librerías pide sellos ni firmas con certificado todavía. 1. **La revisión externa.** El paquete está listo; lo que falta es del autor. Al recibir el informe, se abre la versión siguiente con sus hallazgos, el párrafo de idioma y precedencia del final del §1, las etiquetas del §76 que hoy llaman independientes a revisiones de IA, y el registro de la revisión (§75, punto 10). Todo eso lo aprobó el autor el 6-10; ver [revision_externa/precedence_and_language.md](revision_externa/precedence_and_language.md). 2. **Un archivo o servicio de caché de releases** (§50). El protocolo ya lo admite y las librerías leen un archivo local, pero nadie aloja uno todavía. Es decisión del autor: dónde, quién lo mantiene y si DateKeys ofrece el suyo. diff --git a/README.md b/README.md index caa0fd2..c86a556 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ Para retomar el trabajo, lee [HANDOFF.md](HANDOFF.md): el estado de cada repo, l | Carpeta | Qué es | Remoto | |---|---|---| | `datekeys-go/` | Especificación del protocolo (`spec/`), CDDL, testdata compartido e implementación de referencia en Go: librería y CLI | `go/DateKeys` | -| `datekeys-ts/` | Implementación en TypeScript y páginas `/inspect` y `/create`; la carpeta sigue llamándose `App`. Versión `0.4.0` (tag `v0.4.0`), de la especificación 0.15; en desarrollo, la `0.5.0`, con las palabras al azar y la especificación 0.16 | `go/DateKeys-App` | +| `datekeys-ts/` | Implementación en TypeScript y páginas `/inspect` y `/create`; la carpeta sigue llamándose `App`. Versión `0.5.0` (tag `v0.5.0`), de la especificación 0.16, con las palabras al azar | `go/DateKeys-App` | | `datekeys-dart/` | Librería Dart para la app Flutter, según [PLAN_dart.md](PLAN_dart.md). Rama `v0.16`, de la especificación 0.16: todas las etapas hechas, de la 0 a la 7, las palabras al azar y los dados, con `testdata/`, `wordlists/` y `annex/` en `spec-v0.16` (`b6ff17a`) de `datekeys-go`. La app Flutter está archivada desde el 6-10 | `go/dateKeys-dart`, desde el 6-10 | | `web/` | Landing de datekeys.com, con `api/enquiry.php` | ninguno | | `docs/` | Este repositorio | `go/datekeys-doc`, desde el 6-10 | diff --git a/revision_externa/NOTA_PARA_EL_AUTOR.md b/revision_externa/NOTA_PARA_EL_AUTOR.md index 9e08e4c..d8428de 100644 --- a/revision_externa/NOTA_PARA_EL_AUTOR.md +++ b/revision_externa/NOTA_PARA_EL_AUTOR.md @@ -1,16 +1,18 @@ # Nota para el autor: el paquete de la revisión externa -*6 de octubre de 2026, corregida ese día con una revisión del paquete y con tus decisiones. Puesta al día el 7 de octubre de 2026: el paquete congela ahora la especificación v0.15.* +*6 de octubre de 2026, corregida ese día con una revisión del paquete y con tus decisiones. Puesta al día el 7 de octubre de 2026, primero para la v0.15 y por la noche para la v0.16: el paquete congela ahora la especificación v0.16.* ## Qué congela -El paquete congelaba la v0.14. Desde el 7-10 congela: +El paquete congelaba la v0.14, y el 7-10 por la mañana la v0.15. Desde el 7-10 por la noche congela: -- **Especificación v0.15**, aprobada el 7-10: tag `spec-v0.15`, commit `fe50885` de `datekeys-go` (también la cabeza de la rama `v0.15` y de `main`). SHA-256 del texto `45105e69…e3f3`, y del CDDL, que gana la regla `release`, `63565d5e…19b5`. La documentación de Go que arregló `22f184c` está dentro de `fe50885`: un solo commit congelado para Go. -- **TypeScript 0.4.0**: tag `v0.4.0`, commit `7650418`, con `testdata` en `fe50885`. -- **Dart**: rama `v0.15`, commit `faa2c4c`, sin tag, con `testdata` en `fe50885`. +- **Especificación v0.16**, aprobada el 7-10: tag `spec-v0.16`, commit `b6ff17a` de `datekeys-go` (también la cabeza de la rama `v0.16` y de `main`). SHA-256 del texto `807d4fe8…45e1`, y del CDDL, que solo cambia su comentario de cabecera, `ba3ceb24…c3a3`. La documentación de Go está a la v0.16 en el mismo commit: un solo commit congelado para Go. +- **TypeScript 0.5.0**: tag `v0.5.0`, commit `2c305cf`, con `testdata` en `b6ff17a`. Es la versión que publicaste el 7-10 para esto: la v0.16 y las palabras al azar. +- **Dart**: rama `v0.16`, commit `b53afdc`, sin tag, con `testdata` en `b6ff17a`. -La v0.15 es la recuperación a largo plazo, y el paquete la cuenta: el objeto release (§47.1), el release en la mano y el paso 9.c (§49, §63), los archivos y servicios de caché de todas las rondas (§50), las reglas 26 y 27 de §62.1 y el anexo de recuperación sin software de DateKeys (§79). Q12 pasa a preguntar por ese diseño, y de K3 queda solo lo que la v0.15 no cierra: no hay ningún archivo ni servicio alojado. +La v0.15 es la recuperación a largo plazo, y el paquete la cuenta: el objeto release (§47.1), el release en la mano y el paso 9.c (§49, §63), los archivos y servicios de caché de todas las rondas (§50), las reglas 26 y 27 de §62.1 y el anexo de recuperación sin software de DateKeys (§79). Q12 pregunta por ese diseño, y de K3 queda solo lo que la v0.15 no cierra: no hay ningún archivo ni servicio alojado. + +La v0.16 es la respuesta a la revisión de Astra de la v0.15, y el paquete la cuenta también: el sello sin `accuracy` (§29.7, §29.11), el JSON de drand estricto (§47.1), la llave de palabras y el último bloque completo en el anexo (§79.5, §79.7) y las evidencias de la firma con certificados (§29.10, reglas 21 y 22). Hay una pregunta nueva, Q13, en el nivel 1; la carta dice que la revisión de Astra también es de IA; y K17, las erratas, queda cerrado. ## Qué contiene @@ -19,46 +21,46 @@ En inglés, porque el revisor puede no leer español: | Fichero | Para qué | |---|---| | `README.md` | La carta: qué es DateKeys, qué se pide, qué se entrega, qué queda congelado y que todas las revisiones hasta hoy son de IA | -| `design_overview.md` | El diseño criptográfico, autocontenido y con sus §, para leer en una hora; la sección 8, nueva, es el objeto release y la recuperación | -| `threat_model.md` | Objetivos, no objetivos y modelo de amenazas (§4, §5, §7, §36.1, §55), con lo nuevo de la v0.14 y de la v0.15: la recuperación tras la fecha (§7.6, §50) y el reloj local (4.11) | -| `scope_and_questions.md` | Alcance, 12 preguntas ordenadas y 17 problemas ya conocidos (K1 a K17), para que no se redescubran | +| `design_overview.md` | El diseño criptográfico, autocontenido y con sus §, para leer en una hora; la sección 8 es el objeto release y la recuperación, y la v0.16 se cuenta en 4.6, 4.7, 5, 8.1, 8.4 y 10 | +| `threat_model.md` | Objetivos, no objetivos y modelo de amenazas (§4, §5, §7, §36.1, §55), con lo nuevo de la v0.14, de la v0.15 (la recuperación tras la fecha, §7.6, §50, y el reloj local, 4.11) y de la v0.16 (el sello sin `accuracy` y las evidencias que caben) | +| `scope_and_questions.md` | Alcance, 13 preguntas ordenadas y 17 problemas ya conocidos (K1 a K17, el último cerrado en la v0.16), para que no se redescubran | | `artifacts.md` | Repos, commits, cómo pasar los gates, los vectores uno a uno, los 27 objetivos de fuzzing, las dependencias con versión y la trazabilidad | | `precedence_and_language.md` | **Propuesta**: español normativo, precedencia texto > CDDL > testdata > implementación, y los cambios de texto para la próxima versión | ## Tus decisiones (6-10) 1. **Idioma y precedencia: aprobada la propuesta**, con dos cambios: un párrafo al final de §1, no un §0, para no descolocar la numeración; y la regla 4 sin «vectores disputados». Una discrepancia es un defecto, decide el texto, se anota en el HANDOFF y se corrige en la versión siguiente con su caso en §76; hasta entonces los vectores no se tocan, porque los gates no lo permiten. Entre implementaciones, la de referencia primero, como dicen §16 y §67. Si el inglés pasa a normativo se decide en la v1.0. -2. **Las etiquetas del §76 no abren versión.** La carta ya declara que todas las revisiones anteriores son de IA. El texto corregido, con la precedencia y el registro de la revisión externa (§75, punto 10), va en la versión que se abra con los hallazgos del revisor. La v0.15 se abrió después para la recuperación a largo plazo y no los lleva: irán en la v0.16 o la que siga al informe. -3. **TypeScript: una versión cerrada con el `testdata` congelado.** El 6-10 fue la `0.3.0` (`3abd7bf`); desde el 7-10 es la `0.4.0`, en `7650418`, con el tag `v0.4.0`, que implementa la 0.15. El motivo sigue: el revisor tiene que poder pasar el TypeScript contra los mismos vectores que la referencia. Renombrar la carpeta `App` no hace falta: el revisor ve el nombre del bundle. -4. **Traducción: primero, buscar un revisor que lea español.** Elimina la decisión y el trabajo de contrastar cada hallazgo con el texto normativo. Si no lo hay, traducir solo el núcleo normativo, con un borrador de IA y tu revisión: §4 a §7, §10 a §13, §26 a §44.1, §51 a §57, §62.1, §63 y §69 a §72. En la v0.15 son unas 31 300 palabras de las 58 300 del texto (en la v0.14, 30 600 de 52 600). El resto lo cubre `design_overview.md`, y §76 se resume en una página. La carta dice que toda traducción es informativa y que tú contrastas cada hallazgo con el texto español: ese trabajo es tuyo. - - Para decidir: esa lista no incluye §47.1, §49 y §50, el objeto release, las fuentes y los archivos, unas 1 500 palabras más, sobre los que pregunta Q12. Hoy los cubre la sección 8 de `design_overview.md`. El anexo §79 (unas 1 700) es informativo. +2. **Las etiquetas del §76 no abren versión.** La carta ya declara que todas las revisiones anteriores son de IA. El texto corregido, con la precedencia y el registro de la revisión externa (§75, punto 10), va en la versión que se abra con los hallazgos del revisor. La v0.15 se abrió después para la recuperación a largo plazo, y la v0.16 para la revisión de Astra, y ninguna los lleva: irán en la versión que siga al informe. La v0.16 ya arregló uno de los cambios de texto propuestos, la cabecera «prevista». +3. **TypeScript: una versión cerrada con el `testdata` congelado.** El 6-10 fue la `0.3.0` (`3abd7bf`); el 7-10, la `0.4.0` (`7650418`), de la 0.15, y por la noche la `0.5.0`, en `2c305cf`, con el tag `v0.5.0`, que implementa la 0.16. El motivo sigue: el revisor tiene que poder pasar el TypeScript contra los mismos vectores que la referencia. Renombrar la carpeta `App` no hace falta: el revisor ve el nombre del bundle. +4. **Traducción: primero, buscar un revisor que lea español.** Elimina la decisión y el trabajo de contrastar cada hallazgo con el texto normativo. Si no lo hay, traducir solo el núcleo normativo, con un borrador de IA y tu revisión: §4 a §7, §10 a §13, §26 a §44.1, §51 a §57, §62.1, §63 y §69 a §72. En la v0.16 son unas 31 800 palabras de las 61 000 del texto (en la v0.15, 31 300 de 58 300; en la v0.14, 30 600 de 52 600). El resto lo cubre `design_overview.md`, y §76 se resume en una página. La carta dice que toda traducción es informativa y que tú contrastas cada hallazgo con el texto español: ese trabajo es tuyo. + - Para decidir: esa lista no incluye §47.1, §49 y §50, el objeto release, las fuentes y los archivos, unas 1 700 palabras más, sobre los que preguntan Q12 y Q13. Hoy los cubre la sección 8 de `design_overview.md`. El anexo §79 (unas 2 300, con la llave de palabras de la v0.16) es informativo. 5. **Revisor y alcance: dos niveles, con presupuesto cerrado por nivel.** - - Nivel 1, obligatorio: el protocolo y el Go de referencia como evidencia, con Q1 a Q4, Q6 a Q8 y Q10 a Q12. + - Nivel 1, obligatorio: el protocolo y el Go de referencia como evidencia, con Q1 a Q4, Q6 a Q8 y Q10 a Q13. - Nivel 2, aparte u opcional: Q5 y Q9, el lector CMS/X.509/RFC 3161 y las reglas del localizador, que son revisión de parsers y piden otro perfil. - TypeScript y Dart, fuera del alcance pagado, disponibles si el revisor quiere mirarlos. El paquete sirve tal cual como pliego para pedir precio. Una opción gratuita antes de pagar: enseñar Q1 y Q10 al equipo de drand, que son preguntas sobre su propio IBE. Es decisión tuya, porque supone enseñar el proyecto fuera. 6. **Qué se comparte y cómo.** - - `git bundle` de los tres repos con todo el historial y los tags, porque §76 cita commits; y un `.tar` de cada árbol en el commit congelado, con su SHA-256, para quien no quiera bundles. Dart no tiene tag: el bundle lleva la rama `v0.15`, y el `.tar` se hace en `faa2c4c`. + - `git bundle` de los tres repos con todo el historial y los tags, porque §76 cita commits; y un `.tar` de cada árbol en el commit congelado, con su SHA-256, para quien no quiera bundles. Dart no tiene tag: el bundle lleva la rama `v0.16`, y el `.tar` se hace en `b53afdc`. - El código entero: sin él no puede decir dónde discrepa la implementación ni pasar los gates. - - El repo `docs`, no. Si el revisor lee español, los siete ficheros que cita `artifacts.md` §6, en una carpeta aparte; si no, se quitan esas referencias. `spec_v0.15/decisiones.md` y `diseno_recuperacion.md` describen el fichero `.dkr` que quitaste antes de aprobar, con una nota al principio que lo dice; el spec lo da por descartado (§76, v0.15, cambio 4). + - El repo `docs`, no. Si el revisor lee español, los siete ficheros que cita `artifacts.md` §6, en una carpeta aparte; si no, se quitan esas referencias. `spec_v0.15/decisiones.md` y `diseno_recuperacion.md` describen el fichero `.dkr` que quitaste antes de aprobar, con una nota al principio que lo dice; el spec lo da por descartado (§76, v0.15, cambio 4). `spec_v0.16/decisiones.md` cuenta las ocho decisiones de la v0.16 y cómo se aprobaron. - Un NDA mutuo simple hasta la publicación, y en el encargo, el consentimiento para nombrarle en §76. - La entrega, cifrada con `age` a la clave pública del revisor, con el SHA-256 del archivo por otro canal. El contacto de la revisión es tu dirección directa; `info@` queda como contacto de seguridad del repo. ### Documentación de Go -La documentación atrasada de la v0.14 (la trazabilidad, los README, la cabecera del CDDL y `SECURITY.md`) se arregló el 6-10 en `22f184c`, y está dentro de `fe50885`, que la pone además en la v0.15. Queda `docs/README.md`, que llama `datekeys-ts/` a la carpeta que en esta máquina es `App`: se arregla al renombrarla. +La documentación atrasada de la v0.14 (la trazabilidad, los README, la cabecera del CDDL y `SECURITY.md`) se arregló el 6-10 en `22f184c`; `fe50885` la puso en la v0.15, y `b6ff17a`, el commit del tag, en la v0.16, con las filas nuevas de la trazabilidad. Queda `docs/README.md`, que llama `datekeys-ts/` a la carpeta que en esta máquina es `App`: se arregla al renombrarla. ### Lo que no he podido comprobar - Que el H3 del texto coincide con `h3` de kyber: lo dice el spec y lo comprueban los vectores (`tlock_steps.json`, generado contra kyber), pero quien escribió el paquete no leyó kyber. Está como pregunta Q10. -- Los gates del 7-10 no los volvió a pasar quien puso el paquete al día: las cifras (Go `scripts/check.sh` en `fe50885`; TypeScript 8 106 pruebas, 1 omitida; Dart 2 211 en la VM y 694 en Node) son las de la sesión que cerró la v0.15. +- Los gates sí se pasaron en los commits congelados de la v0.16, en la misma sesión que puso el paquete al día (ver «Orden», punto 2). ## Orden -1. Cerrar la versión de TypeScript: hecho, la `0.4.0` en `7650418`. -2. **Pasar los gates en los commits congelados.** Hecho el 7-10: Go, `scripts/check.sh` entero en `fe50885`, con la comprobación del anexo, y `FUZZ_PARALLEL=4 scripts/fuzz.sh 20s` con sus 27 objetivos, `FuzzDecodeRelease` entre ellos, sin fallos; TypeScript, `npm run verify` en `7650418`, con 8 106 pruebas y 1 omitida; Dart, `tool/check.sh` en `faa2c4c`, con 2 211 pruebas en la VM y 694 en Node. -3. Corregir la nota y el paquete: hecho el 6-10 para la v0.14, y el 7-10 para la v0.15 (esta puesta al día). +1. Cerrar la versión de TypeScript: hecho, la `0.5.0` en `2c305cf`. +2. **Pasar los gates en los commits congelados.** Hecho el 7-10 por la noche: Go, `scripts/check.sh` entero en `b6ff17a`, con la comprobación del anexo sobre cuatro fixtures, y `FUZZ_PARALLEL=4 scripts/fuzz.sh 20s` con sus 27 objetivos, sin fallos; TypeScript, `npm run verify` en `2c305cf`, con 8 273 pruebas y 1 omitida; Dart, `tool/check.sh` en `b53afdc`, con 2 286 pruebas en la VM y 720 en Node. +3. Corregir la nota y el paquete: hecho el 6-10 para la v0.14, y el 7-10 para la v0.15 y para la v0.16 (esta puesta al día). 4. Elegir revisor y nivel de alcance, y pedir presupuesto. 5. Traducir el núcleo, solo si el revisor no lee español. 6. NDA, bundles y envío. diff --git a/revision_externa/README.md b/revision_externa/README.md index 4a10202..1326b53 100644 --- a/revision_externa/README.md +++ b/revision_externa/README.md @@ -1,6 +1,6 @@ # DateKeys: request for an external cryptographic review -*Draft package, 6 October 2026; brought up to specification v0.15 on 7 October 2026. Prepared for the author before it is sent; see `NOTA_PARA_EL_AUTOR.md` for what is still to be decided.* +*Draft package, 6 October 2026; brought up to specification v0.15 and then to v0.16 on 7 October 2026. Prepared for the author before it is sent; see `NOTA_PARA_EL_AUTOR.md` for what is still to be decided.* ## What DateKeys is @@ -21,6 +21,8 @@ The guiding principle is: never trust the server for a property the client can v Version 0.15 adds long-term recovery, without changing the `.dkc` or `.dkk` formats: a **release object**, the public BLS signature of one round as a small CBOR record (spec §47.1); a distinction between a release fetched from a network source and a **release in hand**, which the local clock no longer vetoes (spec §49, §63 step 9.c); recovery from **release archives and cache services** that keep the releases of all rounds, with an informative archive format and no promise of hosting (spec §50); and an informative **annex to open a capsule without DateKeys software** (spec §79), which the reference proves on fixtures with code that imports nothing from DateKeys, tlock or drand. +Version 0.16 answers a review of v0.15 by Astra, an AI system, and changes no format: a valid RFC 3161 seal proves that it came before the opening date only when its token carries `accuracy`, and otherwise gives its reason (spec §29.7, §29.11); the annex also derives a key of words, with a recipe without tables for the letters of the DateKeys lists and `UnicodeData.txt` of Unicode 18.0.0 for any other text, and allows a full last age chunk (§79.5, §79.7); a signature with certificates keeps the chains without their roots and the OCSP responses that fit, and the writer says what it leaves out (§29.10, §62.1 rules 21 and 22); and drand's JSON, accepted as caller input, is read strictly: no repeated names, exact names once escapes are decoded, an integer round (§47.1). + ## What we ask We ask for a cryptographic review of the protocol as specified, with the reference implementation as an aid. In particular: @@ -30,6 +32,7 @@ We ask for a cryptographic review of the protocol as specified, with the referen 3. Whether the byte-level description of the root of trust (spec §12.2, §63 steps 10 and 11 and the paragraphs after the flow) is complete and correct, so that an implementer needs no other source. 4. Whether the parsing surfaces (CBOR profile, age headers, the CMS/X.509/RFC 3161 reader of §29.10–§29.11, locator addresses) are specified tightly enough to avoid divergence and attack. 5. Whether the long-term recovery design of v0.15 is sound: the release object and its check at step 10, accepting a release in hand without comparing it with the clock (§63 step 9.c), archives and cache services as the recovery path (§50), and the annex of §79. +6. Whether the changes of v0.16 are right: a seal without `accuracy` giving no proof of anteriority, the strict reading of drand's JSON, the key of words in the annex, and what a signature with certificates keeps. The ranked questions are in `scope_and_questions.md`, in two levels of scope: level 1, the protocol with the Go reference as evidence, and level 2, the parsers of the CMS/X.509/RFC 3161 reader and of the locator, which may be commissioned separately. Known open problems are listed there too, so that you do not spend time rediscovering them. @@ -48,15 +51,15 @@ Scope, budget and timeline are to be agreed with the author. | Item | Identifier | |---|---| -| Specification | `datekeys-go/spec/DateKeys_Protocol_Specification_v0.15.md`, tag `spec-v0.15`, commit `fe5088549186465e08d55f89680be986076bf165`, approved 7 October 2026 | -| Its SHA-256 | `45105e693be4187af4dd30f4d254402612587b6427c746f5d29f07a541c1e3f3` (recorded in `spec/README.md`; checked on 7 October 2026) | -| CBOR schemas | `datekeys-go/spec/datekeys.cddl` at the same commit: SHA-256 `63565d5e969d08d761cf8f302e767d457372ff0543dd6a6fad9d9fcff9c519b5` (v0.15 adds the rule `release`) | -| Shared test data | `datekeys-go/testdata/` at the same tag: 142 files, documented in `testdata/README.md` | -| Reference implementation (Go) | `datekeys-go` at `spec-v0.15` / `fe50885`, which is also the head of branch `v0.15` and of `main`. Its documentation (README, SECURITY.md, `docs/traceability.md`, the header comment of `spec/datekeys.cddl`) is at v0.15 in the same commit: one frozen commit for Go | -| TypeScript implementation | `datekeys-ts` 0.4.0, tag `v0.4.0`, commit `76504183d3bc59051106bae57d1427ae228ae918` | -| Dart implementation | `datekeys-dart`, branch `v0.15`, commit `faa2c4c89154b4ff405941227682b949a1cda5d3` (no tag) | +| Specification | `datekeys-go/spec/DateKeys_Protocol_Specification_v0.16.md`, tag `spec-v0.16`, commit `b6ff17a5fa5f119aa8125356437a09c657b15d0b`, approved 7 October 2026 | +| Its SHA-256 | `807d4fe85ac09ad6f97abc75ab3e2156bb2f3fb0dc589777f4420627fad545e1` (recorded in `spec/README.md`; checked on 7 October 2026) | +| CBOR schemas | `datekeys-go/spec/datekeys.cddl` at the same commit: SHA-256 `ba3ceb24203ef49f55d5da021b7e940ae6780ef83fccb10aa3d305e4dcfac3a3` (v0.15 adds the rule `release`; v0.16 changes only the header comment) | +| Shared test data | `datekeys-go/testdata/` at the same tag: 150 files, documented in `testdata/README.md` | +| Reference implementation (Go) | `datekeys-go` at `spec-v0.16` / `b6ff17a`, which is also the head of branch `v0.16` and of `main`. Its documentation (README, SECURITY.md, `docs/traceability.md`, the header comment of `spec/datekeys.cddl`) is at v0.16 in the same commit: one frozen commit for Go | +| TypeScript implementation | `datekeys-ts` 0.5.0, tag `v0.5.0`, commit `2c305cf` | +| Dart implementation | `datekeys-dart`, branch `v0.16`, commit `b53afdc` (no tag) | -Note on TypeScript and Dart: `datekeys-ts` 0.4.0 and `datekeys-dart` at `faa2c4c` implement specification 0.15, with their `testdata/` at tag `spec-v0.15` (`fe50885`), so they run against the same frozen vectors as the reference. The previous TypeScript version, 0.3.0, implemented 0.14. +Note on TypeScript and Dart: `datekeys-ts` 0.5.0 and `datekeys-dart` at `b53afdc` implement specification 0.16, with their `testdata/` at tag `spec-v0.16` (`b6ff17a`), so they run against the same frozen vectors as the reference. The previous TypeScript version, 0.4.0, implemented 0.15. ## How this package is organised @@ -70,7 +73,7 @@ Note on TypeScript and Dart: `datekeys-ts` 0.4.0 and `datekeys-dart` at `faa2c4c | `precedence_and_language.md` | A proposal for the author: which language is normative, and precedence between the text, the CDDL, the test vectors and the implementation | | `NOTA_PARA_EL_AUTOR.md` | A short note in Spanish for the author: what is still missing before sending | -The normative text is the Spanish specification. The English files here are informative summaries; where they disagree with the specification, the specification wins. Section numbers (§) refer to `DateKeys_Protocol_Specification_v0.15.md`. +The normative text is the Spanish specification. The English files here are informative summaries; where they disagree with the specification, the specification wins. Section numbers (§) refer to `DateKeys_Protocol_Specification_v0.16.md`. ## Prior reviews: all by AI systems @@ -79,6 +82,7 @@ No human has reviewed DateKeys so far. Every review to date was done by AI syste - Claude (Anthropic), in the working sessions that wrote the specification and the implementations, including the completeness reviews of 29 September 2026 (`docs/REVISION_completitud_protocolo.md`, against v0.8.2) and 6 October 2026 (`docs/REVISION_completitud_v0.13.md`, against v0.13). - Fable and Astra, also AI systems (confirmed by the author on 6 October 2026), for the design of format 3 (v0.10) and of the signature and the seal (v0.11). - The long-term recovery of v0.15 (6 and 7 October 2026) was designed and drafted in the same Claude working sessions (`docs/diseno_recuperacion.md`, `docs/spec_v0.15/decisiones.md`) and approved by the author; it has had no review outside those AI-assisted sessions. +- Astra reviewed v0.15 on 7 October 2026, with five findings; v0.16 is the answer, drafted and implemented in the Claude working sessions (`docs/spec_v0.16/decisiones.md`) and approved by the author the same day. The §76 block of v0.16 calls it «la revisión de Astra»: an AI review too. Some passages of spec §76 describe these reviews with words that suggest otherwise: diff --git a/revision_externa/artifacts.md b/revision_externa/artifacts.md index 505aebd..b9440cf 100644 --- a/revision_externa/artifacts.md +++ b/revision_externa/artifacts.md @@ -1,35 +1,35 @@ # Artifacts -*State on 7 October 2026, specification v0.15. Paths are relative to each repository.* +*State on 7 October 2026, specification v0.16. Paths are relative to each repository.* ## 1. Repositories and frozen commits | Repository | Role | Frozen at | Language of docs | |---|---|---|---| -| `datekeys-go` | Specification (`spec/`), CDDL, shared test data (`testdata/`), reference implementation in Go: library and CLI | tag `spec-v0.15`, commit `fe5088549186465e08d55f89680be986076bf165` (also the head of branch `v0.15` and of `main`) | English README (a Spanish one too); spec in Spanish | -| `datekeys-ts` | TypeScript library and static pages `/inspect` and `/create` | tag `v0.4.0`, commit `76504183d3bc59051106bae57d1427ae228ae918` (implements spec 0.15) | Spanish README | -| `datekeys-dart` | Pure Dart library, for a future Flutter app | branch `v0.15`, commit `faa2c4c89154b4ff405941227682b949a1cda5d3`, no tag (implements spec 0.15) | Spanish README | +| `datekeys-go` | Specification (`spec/`), CDDL, shared test data (`testdata/`), reference implementation in Go: library and CLI | tag `spec-v0.16`, commit `b6ff17a5fa5f119aa8125356437a09c657b15d0b` (also the head of branch `v0.16` and of `main`) | English README (a Spanish one too); spec in Spanish | +| `datekeys-ts` | TypeScript library and static pages `/inspect` and `/create` | tag `v0.5.0`, commit `2c305cf` (implements spec 0.16) | Spanish README | +| `datekeys-dart` | Pure Dart library, for a future Flutter app | branch `v0.16`, commit `b53afdc`, no tag (implements spec 0.16) | Spanish README | - The repositories are private, on a Gitea server on the author's LAN (`g.activething.com`). They are not reachable from outside. The author will provide them by another means (for example `git bundle` files or archives); see `NOTA_PARA_EL_AUTOR.md`. - The gates of `datekeys-ts` and `datekeys-dart` compare their `testdata/` with a sibling checkout `../datekeys-go`. Lay the three out side by side: ```text work/ - datekeys-go/ at spec-v0.15 - datekeys-ts/ at v0.4.0 (the author's machine names this folder App) - datekeys-dart/ at faa2c4c + datekeys-go/ at spec-v0.16 + datekeys-ts/ at v0.5.0 (the author's machine names this folder App) + datekeys-dart/ at b53afdc ``` Specification files at the tag: | File | SHA-256 | |---|---| -| `spec/DateKeys_Protocol_Specification_v0.15.md` (4 734 lines, about 58 300 words, Spanish) | `45105e693be4187af4dd30f4d254402612587b6427c746f5d29f07a541c1e3f3` | -| `spec/datekeys.cddl` (341 lines, English comments; v0.15 adds the rule `release`) | `63565d5e969d08d761cf8f302e767d457372ff0543dd6a6fad9d9fcff9c519b5` | +| `spec/DateKeys_Protocol_Specification_v0.16.md` (4 810 lines, about 61 000 words, Spanish) | `807d4fe85ac09ad6f97abc75ab3e2156bb2f3fb0dc589777f4420627fad545e1` | +| `spec/datekeys.cddl` (340 lines, English comments; v0.15 adds the rule `release`, v0.16 changes no schema) | `ba3ceb24203ef49f55d5da021b7e940ae6780ef83fccb10aa3d305e4dcfac3a3` | -Both were checked on 7 October 2026 with `git show spec-v0.15: | sha256sum`. The documentation of the Go repository (README, SECURITY.md, `docs/traceability.md`, the header comment of the CDDL) is at v0.15 in the same commit, so one commit freezes Go. +Both were checked on 7 October 2026 with `git show spec-v0.16: | sha256sum`. The documentation of the Go repository (README, SECURITY.md, `docs/traceability.md`, the header comment of the CDDL) is at v0.16 in the same commit, so one commit freezes Go. -`spec/README.md` lists the SHA-256 of every frozen version from v0.8.2 to v0.15. Earlier versions are in the same folder; §76 records each normative change with its reproducible case. The specification is CC-BY-4.0; the code is Apache-2.0. +`spec/README.md` lists the SHA-256 of every frozen version from v0.8.2 to v0.16. Earlier versions are in the same folder; §76 records each normative change with its reproducible case. The specification is CC-BY-ND-4.0 (since 7 October 2026; it was CC-BY-4.0); the code is Apache-2.0. ## 2. Build and gates @@ -44,18 +44,20 @@ go test -tags interop ./capsule # the official age and tle CLIs open our go test -tags integration ./capsule ./provider/drand # live Quicknet (network) ``` -`scripts/check.sh` runs, in order: `gofmt`; `go mod verify`; `go mod tidy` leaves `go.mod` and `go.sum` unchanged; `go vet`; `go test -race`; coverage of at least 90 % in `codec`, `capsule`, `accesskey`, `datekey` and `agewrap`; `govulncheck` v1.8.0 (downloads the tool); `scripts/recovery_check.sh` (v0.15, below); and `genfixtures`, which regenerates `testdata/` and fails if any committed file changes. +`scripts/check.sh` runs, in order: `gofmt`; `go mod verify`; `go mod tidy` leaves `go.mod` and `go.sum` unchanged; `go vet`; `go test -race`; coverage of at least 90 % in `codec`, `capsule`, `accesskey`, `datekey` and `agewrap`; `govulncheck` v1.8.0 (downloads the tool); `scripts/recovery_check.sh` (v0.15 and v0.16, below); and `genfixtures`, which regenerates `testdata/` and fails if any committed file changes. -`scripts/recovery_check.sh` proves the annex of spec §79: it opens the fixtures `format3_single` (`time_only`) and `format3_time_and_key_portable` (`time_and_key`, with its `.dkk`) with `scripts/recovery`, using the release objects of `testdata/releases/`, and compares the BODY it recovers with the plaintext fixture. `scripts/recovery` imports no DateKeys, tlock or drand package: only the Go standard library, `golang.org/x/crypto` (ChaCha20-Poly1305), `filippo.io/age` and drand's BLS12-381 library (`github.com/drand/kyber-bls12381`, with the interfaces of `github.com/drand/kyber`). Its test checks that rule and runs over eight fixtures of the three formats (spec §76, v0.15 change 4). +`scripts/recovery_check.sh` proves the annex of spec §79: it opens the fixtures `format3_single` (`time_only`), `format3_time_and_key_portable` (`time_and_key`, with its `.dkk`), and, since v0.16, `format3_time_and_key_words` (with the text of the words of the annex vector) and `format3_full_chunk` (a PAYLOAD_AGE of one full STREAM chunk) with `scripts/recovery`, using the release objects of `testdata/releases/`, and compares the BODY it recovers with the plaintext fixture. `scripts/recovery` imports no DateKeys, tlock or drand package: only the Go standard library (PBKDF2 included), `golang.org/x/crypto` (ChaCha20-Poly1305), `filippo.io/age` and drand's BLS12-381 library (`github.com/drand/kyber-bls12381`, with the interfaces of `github.com/drand/kyber`). It takes the words with `-words` and, for text outside the recipe without tables of §79.7, `UnicodeData.txt` with `-unicodedata`, checked by its SHA-256. Its tests check the import rule, run over ten fixtures of the three formats, and compare both normalisations of §79.7 with every case of `vectors/wordkey.json` (spec §76, v0.15 change 4; v0.16 changes 2 and 3). `scripts/fuzz.sh` has 27 targets: `codec` (Decoder, Walk, Peek, Unmarshal, EncodeImpliesWalk), `extension` (DecodeArray), `profile` (Decode), `provider` (DecodeRelease, new in v0.15: the release object of §47.1), `datekey` (Parse), `agewrap` (Stanzas), `accesskey` (Decode), `capsule` (ParsePrelude, DecodeHeader, DecodeControl, DecodeHead, EvaluateSecurity, Inspect, EncodeImpliesDecode), `internal/pathrule` (CheckPath), `locator` (Unmarshal, ParseInfo, CheckURI, CheckResolvedIP), `internal/der` (DERCheck), `internal/cms` (ParseSignature, ParseToken, ParseCert). Each worker keeps a 100 MB shared-memory file in the temporary directory; `FUZZ_MINIMIZE` (default 0) sets the time spent minimising a new input. -The CLI (`cmd/datekeys`) has `encrypt`, `decrypt`, `inspect`, `author keygen`, `author public`, `profile hash`, `datekey resolve` and `version` (`README.md`). Since v0.15, `decrypt -release ` takes a release in hand (a release object, drand's JSON or a local release archive), makes no request and does not compare it with the clock. +The CLI (`cmd/datekeys`) has `encrypt`, `decrypt`, `inspect`, `author keygen`, `author public`, `profile hash`, `datekey resolve` and `version` (`README.md`). Since v0.15, `decrypt -release ` takes a release in hand (a release object, drand's JSON or a local release archive), makes no request and does not compare it with the clock. `encrypt` writes the recovery annex next to the capsule and says what opening will take (§62.1 rules 26 and 27), and draws random words with `-new-words` or takes them from dice with `-dice`. Gate and fuzzing record: -- On 7 October 2026, `scripts/check.sh` (without fuzzing) passed on `fe50885`, the frozen commit. -- On 7 October 2026, `FUZZ_PARALLEL=4 scripts/fuzz.sh 20s` ran the 27 targets on `fe50885`, `FuzzDecodeRelease` among them, with no failing input. The previous run, on 6 October 2026, covered the 26 targets of v0.14 on `39b2033`. +- On 7 October 2026, `scripts/check.sh` (without fuzzing) passed on `b6ff17a`, the frozen commit, and before on `4f78854` and `3fd0e93` of the same branch. +- On 7 October 2026, `FUZZ_PARALLEL=4 scripts/fuzz.sh 20s` ran the 27 targets on `b6ff17a`, with no failing input. +- For v0.15: `scripts/check.sh` passed on `fe50885`. +- For v0.15: `FUZZ_PARALLEL=4 scripts/fuzz.sh 20s` ran the 27 targets on `fe50885`, `FuzzDecodeRelease` among them, with no failing input. The previous run, on 6 October 2026, covered the 26 targets of v0.14 on `39b2033`. - Earlier: 60 s per target on `69dbb0c`, clean (`docs/HANDOFF.md`, 6 October 2026). ### datekeys-ts (Node.js 20 or later) @@ -67,7 +69,7 @@ npm run verify # svelte-check, typecheck, tests with coverage threshold npm run testdata:check # testdata/ equals ../datekeys-go at the recorded commit ``` -Coverage thresholds are 100 % for the cryptographic and format modules listed in its README. A guard test fails if a file of `testdata/` is not used by any test, and `src/lib/dependencies.test.ts` pins the exact runtime dependencies. On 7 October 2026, `npm run verify` passed with 8 106 tests (1 skipped) on `7650418`, the release commit of 0.4.0, with `testdata/` at `fe50885` (`testdata/SOURCE.json`). +Coverage thresholds are 100 % for the cryptographic and format modules listed in its README. A guard test fails if a file of `testdata/` is not used by any test, and `src/lib/dependencies.test.ts` pins the exact runtime dependencies. On 7 October 2026, `npm run verify` passed with 8 273 tests (1 skipped) on `2c305cf`, the release commit of 0.5.0, with `testdata/` at `b6ff17a` (`testdata/SOURCE.json`). ### datekeys-dart (Dart SDK 3.13 or later; Node.js for the JavaScript run) @@ -78,11 +80,11 @@ tool/check.sh # dart format, dart analyze --fatal-infos, dart test, da # and testdata/ against ../datekeys-go ``` -On 7 October 2026 the gate passed on `faa2c4c` with 2 211 tests on the VM and 694 on Node, with `testdata/` at `fe50885` (142 files). +On 7 October 2026 the gate passed on `b53afdc` with 2 286 tests on the VM and 720 on Node, with `testdata/` at `b6ff17a` (150 files). ## 3. Shared test vectors (`datekeys-go/testdata/`) -Generated by the reference implementation (`go run ./internal/testkit/genfixtures -out testdata`). The `.dkc` and `.dkk` fixtures, `security_cms.json` and `locator.json` hold randomness and are frozen. TypeScript and Dart copy `testdata/` from a Go commit and never generate fixtures. Every file says `"spec": "0.15"`. The format of each file is documented in `testdata/README.md` (1 152 lines, English), so that no Go code needs to be read. At `fe50885` there are 142 files; v0.15 adds `vectors/release.json`, the five files of `releases/` and the field `source` of `mutations.json`. +Generated by the reference implementation (`go run ./internal/testkit/genfixtures -out testdata`). The `.dkc` and `.dkk` fixtures, `security_cms.json` and `locator.json` hold randomness and are frozen. TypeScript and Dart copy `testdata/` from a Go commit and never generate fixtures. Every file says `"spec": "0.16"`. The format of each file is documented in `testdata/README.md` (1 186 lines, English), so that no Go code needs to be read. At `b6ff17a` there are 150 files; v0.15 adds `vectors/release.json`, the five files of `releases/` and the field `source` of `mutations.json`; v0.16 makes `security_cms.json` again, with `seal_reason`, adds 26 cases of drand's JSON to `release.json` and the annex vector to `wordkey.json`, and brings two fixtures, `format3_time_and_key_words` and `format3_full_chunk`. | File | Content | Spec | |---|---|---| @@ -91,7 +93,7 @@ Generated by the reference implementation (`go run ./internal/testkit/genfixture | `vectors/dk1.json` | canonical `dk1_` strings, and rejected encodings with their code | §18, §19, §66 | | `vectors/cbor.json` | the CBOR profile, and one block of vectors per schema, CONTROL_CBOR in the three formats | §58, CDDL | | `vectors/tlock_ibe.json` | H2 of the tlock IBE: the serialisation of a GT element | §63 step 11 | -| `vectors/release.json` | the release object: valid and invalid encodings, drand's JSON, each with its result at step 10 (`ERR_NON_CANONICAL_CBOR`, `ERR_UNSUPPORTED_VERSION`, `ERR_PROFILE_MISMATCH`, `ERR_ROUND_MISMATCH`, `ERR_RELEASE_INVALID`); and the lookups of a local release archive | §47.1, §50, §63 step 10 (v0.15) | +| `vectors/release.json` | the release object: valid and invalid encodings, drand's JSON, each with its result at step 10 (`ERR_NON_CANONICAL_CBOR`, `ERR_UNSUPPORTED_VERSION`, `ERR_PROFILE_MISMATCH`, `ERR_ROUND_MISMATCH`, `ERR_RELEASE_INVALID`); and the lookups of a local release archive. Since v0.16, 38 cases of drand's JSON, 26 of them for the strict reading: repeated names, escaped names, `ROUND`, rounds with a fraction, an exponent, a sign, 0 or 2^53, lone surrogates | §47.1, §50, §63 step 10 (v0.15, v0.16) | | `releases/.cbor` | the release object of each published round the fixtures use: 1000, 1001, 1004 and 2000 (111 bytes each) | §47.1 (v0.15) | | `releases/archive_1000_1004.bin` | a local release archive in the informative format of §50, rounds 1000 to 1004, with 1002 and 1003 missing (zero-filled) | §50 (v0.15) | | `vectors/tlock_steps.json` | steps 10 and 11 for Quicknet value by value: round message, hash to G1, and the decryption of a tlock stanza with H2, H4, H3 and the file key | §63 steps 10 and 11 (v0.14) | @@ -100,11 +102,11 @@ Generated by the reference implementation (`go run ./internal/testkit/genfixture | `vectors/path_fold.json` | the R7 key of segments, and their NFD | §29.5, §29.5.1 | | `vectors/head_schema.json` | format 3 heads and the result of decoding them | §29.4 to §29.6, §69.1 | | `vectors/security.json` | security areas in the context of a capsule, their verdicts and lines | §29.3, §29.7, §29.9 | -| `vectors/security_cms.json` | security areas with an `alg` 2 signature or a `seal_type` 2 seal, with context, verdicts, results and lines | §29.7, §29.10, §29.11 | +| `vectors/security_cms.json` | security areas with an `alg` 2 signature or a `seal_type` 2 seal, with context, verdicts, results and lines; made again for v0.16 (143 cases), with the reason of S5, `seal_reason` | §29.7, §29.10, §29.11 | | `vectors/ed25519_strict.json` | Ed25519 signatures and the result of the strict profile | §29.9 | | `vectors/note.json` | public note data and the result of its rules | §24.1, §29.6 | | `vectors/resolved_ip.json` | the IP a locator name resolves to, NAT64 included, and whether a reader may connect | §44.1 (v0.13) | -| `vectors/wordkey.json` | key of words: the words of a text, what a writer refuses, the derived identity | §38.1, §64 | +| `vectors/wordkey.json` | key of words: the words of a text, what a writer refuses, the derived identity; since v0.16 the text of the annex vector, also with its marks apart | §38.1, §64, §79.7 | | `vectors/locator.json` | the `datekeys.capsule` extension, its envelope and locator, and what a reader rejects and uses | §44.1, §64 | | `vectors/mutations.json` | the mutation corpus: 222 cases, the 178 mutations of §64 and further cases. Since v0.15 each case names its release `source`: `supplied` (a release in hand, 220 cases) or `network` (2 cases); four cases are new (cases 219 to 222), and «round not reached yet» now opens with a release in hand | §63, §64 | | `vectors/inspect_differential.json` | 5 110 mutations of fourteen fixtures with the verdict of steps 1 to 8 | §63 | @@ -113,13 +115,13 @@ Generated by the reference implementation (`go run ./internal/testkit/genfixture | `fixtures/.plaintext` | the content of each capsule (formats 1 and 2: the content; format 3: BODY) | §67 | | `fixtures/.inspect.json` | the exact output of `datekeys inspect -json` | §63 | -Twenty-six official capsules (`testdata/README.md`): five of format 1 (v0.8.2, compatibility), seven of format 2 (v0.9, compatibility) and fourteen of format 3, among them `format3_signed` (`alg` 1, F4), `format3_signed_cms` (`alg` 2, two signers, ECDSA P-256 and RSA 2048, CAdES-T each, F6), `format3_sealed` (`alg` 1 and an RFC 3161 seal, S4) and `format3_note`. Each record embeds the published Quicknet signature that opens it, so every fixture decrypts offline; since v0.15 the same signatures are also in `releases/` as release objects. Test secrets (`payload_identity`, `access_material`, the seed of the test author key) are in the records on purpose. +Twenty-eight official capsules (`testdata/README.md`): five of format 1 (v0.8.2, compatibility), seven of format 2 (v0.9, compatibility) and sixteen of format 3, among them `format3_signed` (`alg` 1, F4), `format3_signed_cms` (`alg` 2, two signers, ECDSA P-256 and RSA 2048, CAdES-T each, F6), `format3_sealed` (`alg` 1 and an RFC 3161 seal with `accuracy`, S4), `format3_note`, and, since v0.16, `format3_time_and_key_words` (a key of words, its text in `words_text`) and `format3_full_chunk`. Each record embeds the published Quicknet signature that opens it, so every fixture decrypts offline; since v0.15 the same signatures are also in `releases/` as release objects. Test secrets (`payload_identity`, `access_material`, the seed of the test author key) are in the records on purpose. ## 4. Dependencies ### Go (`datekeys-go/go.mod`, Go 1.26.8) -No dependency changed in v0.15: `go.mod` and `go.sum` are identical at `39b2033` and `fe50885`; the TypeScript `package.json` and lock file change only the package version from 0.3.0 to 0.4.0; the Dart `pubspec.yaml` and `pubspec.lock` are identical at `013b069` and `faa2c4c`. The recovery program `scripts/recovery` uses only modules already in `go.mod`. +No dependency changed in v0.15 or v0.16: `go.mod` and `go.sum` are identical at `39b2033`, `fe50885` and `b6ff17a`; the TypeScript `package.json` and lock file change only the package version, to 0.4.0 and then to 0.5.0; the Dart `pubspec.yaml` and `pubspec.lock` are identical at `013b069`, `faa2c4c` and `b53afdc`. The recovery program `scripts/recovery` uses only modules already in `go.mod`. Direct: @@ -136,7 +138,7 @@ Indirect: `filippo.io/hpke` v0.4.0, `github.com/BurntSushi/toml` v1.6.0, `github The Go standard library provides Ed25519 (with strict checks in `internal/ed25519strict`), RSA, ECDSA, SHA-2 and PBKDF2. CBOR (`codec`), DER (`internal/der`) and the CMS/X.509/RFC 3161 reader (`internal/cms`) are the module's own code. -### TypeScript (`datekeys-ts/package.json` at `v0.4.0`, exact versions) +### TypeScript (`datekeys-ts/package.json` at `v0.5.0`, exact versions) Runtime: @@ -149,7 +151,7 @@ Runtime: `age-encryption` brings `@scure/base` 2.4.0 and `@noble/post-quantum` 0.5.4, which carries its own `@noble/curves` and `@noble/hashes` 2.0.1. The IBE core (`ibe.ts`) is derived from `tlock-js` (MIT); `tlock-js` itself is not a dependency. Development: TypeScript 5.9.3, Vitest 5.0.1, Vite 8.3.0, Svelte 5.57.1, SvelteKit 2.70.3, svelte-check 4.7.6, adapter-static 3.0.10, `@types/node` 24.13.6. -### Dart (`datekeys-dart/pubspec.yaml` and `pubspec.lock` at `faa2c4c`) +### Dart (`datekeys-dart/pubspec.yaml` and `pubspec.lock` at `b53afdc`) - Runtime: `crypto` 3.0.7 (SHA-1, SHA-2, HMAC), with `typed_data` 1.4.0 transitive. Everything else is own code: HKDF, PBKDF2, scrypt, ChaCha20-Poly1305, X25519, Ed25519, BLS12-381, ECDSA, RSA, DER, CMS and CBOR. - Development: `test` 1.31.1 or later (`^1.31.1`). @@ -157,9 +159,9 @@ Runtime: ## 5. Traceability -`datekeys-go/docs/traceability.md` (261 lines) maps every normative section of the specification to the Go code that implements it and the tests that exercise it, row by row from §3 to §76, with a row for the informative annex §79, and marks cases of §64 not yet in the repository as *pending*. It is intended for the external reviewer. +`datekeys-go/docs/traceability.md` (262 lines) maps every normative section of the specification to the Go code that implements it and the tests that exercise it, row by row from §3 to §76, with a row for the informative annex §79, and marks cases of §64 not yet in the repository as *pending*. It is intended for the external reviewer. -At v0.15 in the frozen commit `fe50885`, with the rows of v0.15: §45 (the Release API answers with the release object), §47.1 (the release object, `provider/release.go`, `FuzzDecodeRelease`), §49 (a release in hand), §50 (archives and cache services) and §79 (`scripts/recovery`). The documentation fixes of v0.14 (`22f184c`: one drand scheme, 19 normative errors, no signed release of the module yet) are included in that commit. +At v0.16 in the frozen commit `b6ff17a`. The rows of v0.16: §29.7 and §29.11 (the reason of S5, `capsule.SealReason`, `Token.HasAccuracy` and `Token.BTSP`), §47.1 (`ParseDrandJSON` and `provider/drandjson.go`), §62.1 (`Result.Security` for rule 19; rules 21 and 22 *pending*, since no writer asks an authority yet), §67 (the two fixtures) and §79 (the key of words of `scripts/recovery`). The rows of v0.15: §45 (the Release API answers with the release object), §47.1 (the release object, `provider/release.go`, `FuzzDecodeRelease`), §49 (a release in hand), §50 (archives and cache services) and §79 (`scripts/recovery`). The documentation fixes of v0.14 (`22f184c`: one drand scheme, 19 normative errors, no signed release of the module yet) are included in that commit. ## 6. Other documents a reviewer may want @@ -170,4 +172,5 @@ All in the private `docs` repository; in Spanish: - `spec_v0.14/decisiones.md`: the ten decisions of the v0.14 draft. - `diseno_recuperacion.md`: the design of the long-term recovery (6 October 2026), with the options and the author's decisions, AI-assisted. - `spec_v0.15/decisiones.md`: the decisions of the v0.15 draft (7 October 2026). It describes the `.dkr` release file, which the author removed before approval; a note at its top says so (spec §76, v0.15 change 4). +- `spec_v0.16/decisiones.md`: the eight decisions of the v0.16 draft (7 October 2026), the answer to Astra's review of v0.15, with a note on how they were approved. - `spec_v0.10/revision_fable.md`, `spec_v0.11/revision_fable_astra.md`: reviews by the AI systems Fable and Astra. diff --git a/revision_externa/design_overview.md b/revision_externa/design_overview.md index 29fbc49..f92ff9a 100644 --- a/revision_externa/design_overview.md +++ b/revision_externa/design_overview.md @@ -1,6 +1,6 @@ -# DateKeys v0.15: design overview for a cryptographic reviewer +# DateKeys v0.16: design overview for a cryptographic reviewer -*Informative. Every statement here summarises the Spanish specification `DateKeys_Protocol_Specification_v0.15.md` (tag `spec-v0.15`); the section sign (§) refers to it. Where this summary and the specification disagree, the specification wins. Reading time: about an hour.* +*Informative. Every statement here summarises the Spanish specification `DateKeys_Protocol_Specification_v0.16.md` (tag `spec-v0.16`); the section sign (§) refers to it. Where this summary and the specification disagree, the specification wins. Reading time: about an hour.* Notation: `||` is concatenation; `uint32_be`, `uint64_be` are big-endian integers; SHA-256 is FIPS 180-4; "age" is the C2SP age v1 format; Quicknet is the drand network of §12. @@ -12,6 +12,7 @@ Notation: `||` is concatenation; `uint32_be`, `uint64_be` are big-endian integer - No new cryptography (§28, §30, §37): DateKeys composes three standard age files and the tlock IBE of drand. It defines framing, CBOR, bindings, stanza rules, padding, the format 3 content, the author signature profile and the verification flow. - The protocol does not define storage, discovery, distribution or delivery of `.dkk` (§6). - Since v0.15 the release of a round has a data format, the release object (§47.1), and long-term recovery rests on archives and cache services of all rounds, with an annex to open a capsule without DateKeys software (§50, §79). See section 8. +- v0.16 answers a review of v0.15 by Astra, an AI system, without changing any format: a seal without `accuracy` (4.7), the strict reading of drand's JSON (8.1), the key of words in the annex (8.4) and what a signature with certificates keeps (4.6, section 10). ## 2. Provider Profile and root of trust @@ -244,7 +245,7 @@ seal: 0 → seal_type 1 → token - `security` never decides opening: no failure of it has an error code, stops step 17 or changes another code. Its only output is verdicts (§29.3, §29.7). - Defined: `alg` 1 (strict Ed25519), `alg` 2 (CMS with X.509), `seal_type` 2 (RFC 3161). Reserved: `seal_type` 1 and 3; `alg` and `seal_type` 4294967295 for tests. With `alg` 2 the seal is inside the signature and key 3 MUST NOT exist. -- Verdicts: X (area unreadable), F0–F6 for the signature, S0–S5 for the seal, with fixed texts the official SDK MUST use (§29.7). A reader MUST NOT say a capsule was signed before the date except by a valid seal with t + accuracy < round_time. +- Verdicts: X (area unreadable), F0–F6 for the signature, S0–S5 for the seal, with fixed texts the official SDK MUST use (§29.7). A reader MUST NOT say a capsule was signed before the date except by a valid seal that carries `accuracy`, with t + accuracy < round_time (v0.16). S5 gives its reason. ### 4.4 What the author signature covers (§29.8) @@ -287,7 +288,7 @@ This is cofactorless RFC 8032 verification with canonical A and R; an implementa - Closed algorithm table: SHA-256/384/512; RSASSA-PKCS1-v1_5 and RSASSA-PSS (2048–4096-bit keys, odd modulus, odd exponent 3 to 2³¹ − 1); ECDSA on P-256, P-384, P-521, uncompressed keys. No brainpool, GOST or SM2. - A field-by-field certificate profile; the certificate's own signature and extensions other than those listed decide nothing. - Per required signer: absent → not verifiable → invalid → no seal → invalid seal → certificate not valid at seal time t → valid. Verdict: F2 if any is invalid; F5 if any is absent, not verifiable, unsealed, badly sealed or out of validity, or if key 3 exists; F6 if all valid. -- DateKeys never checks who issued a certificate or seal, revocation, or qualification; an official validator does. The capsule keeps the evidence (signature, certificate, seal, OCSP response) for later validation. +- DateKeys never checks who issued a certificate or seal, revocation, or qualification; an official validator does. The capsule keeps the evidence that fits in the area for later validation: always the signature, each signer's certificate and its seal; and, if they fit, the chains of the signers and of the time-stamping authorities without their roots, and the OCSP responses (v0.16: rule 21 no longer recommends pruning the chain to one certificate). What does not fit, the writer names, and only exists where it was exported. - The table and the certificate profile are provisional (§74). ### 4.7 RFC 3161 seal (§29.11) @@ -305,7 +306,7 @@ SEAL_SUBJECT = SHA-256("datekeys:dkc3:seal-subject:v1" || 0x00 messageImprint = SHA-256(SEAL_SUBJECT) ; the TSA never sees SEAL_SUBJECT ``` -Token profile, in order: form (S2), algorithms (S1), verification (S3). t = `genTime`, precision = `accuracy` or 0. S4 if t + precision < round_time, S5 otherwise. A seal never changes the signature verdict. Seals outside the capsule (OpenTimestamps, archive re-seals RFC 4998) are not defined. +Token profile, in order: form (S2), algorithms (S1), verification (S3). t = `genTime`, precision = `accuracy`, with 0 in the fields it does not carry (RFC 3161 §2.4.2). S4 only if the token carries `accuracy` and t + precision < round_time; S5 otherwise, with its reason, the first that holds: sealed after the date or too close to it (precision 0 without `accuracy`); no `accuracy` under the best-practices policy of ETSI EN 319 421 (BTSP, 0.4.0.2023.1.1), which requires it (ETSI EN 319 422 §5.2.2); no `accuracy` (v0.16). A reader MUST NOT assume a precision the token does not state, not even from its policy. In F6, the line of a signer whose seal does not prove the date gives the same reason. A seal never changes the signature verdict. Seals outside the capsule (OpenTimestamps, archive re-seals RFC 4998) are not defined. ## 5. Key of words (§38.1) @@ -323,6 +324,7 @@ id = PBKDF2-HMAC-SHA256(P, S, 600000 iterations, 32 bytes) ; an X25519 ident - `capsule_id` in the salt makes the same words give a different key per capsule, so each guess tests one capsule. - After the date, anyone holding the `.dkc` can test words offline (§38.1, §55.2). - Vector: «perro luna casa verde tren mar», Quicknet chain hash, round 1000, `capsule_id` `000102…0f` → `id` = `fceec4d8ca8de86c85a1f26ed49f82a2b38431bd0ce36db995ae7dfd49b96e41`. +- Since v0.16 the annex (§79.7) repeats the derivation for whoever opens a capsule without DateKeys software, with a recipe without tables that is exact for the letters of the DateKeys lists (printable ASCII, á é í ó ú ü ñ and their capitals, and the marks U+0300 to U+036F), and for any other text the full normalisation from `UnicodeData.txt` of Unicode 18.0.0, named by its SHA-256. Its second vector: «Ñandú», two spaces, «PINGÜINO», a tab and «camión árbol Éter ola» → «nandu pinguino camion arbol eter ola» → `id` = `273295d29370126a3be50b743132718d3cd9137fb3bb4cb20aa23163d2e19bb7`. ## 6. The `.dkk` access key (§40 to §44) @@ -407,7 +409,7 @@ round 1000 of Quicknet: 111 bytes (testdata/releases/1000.cbor) - Validation, all at step 10, with the layers of §69.1: an empty input or one over 1024 bytes → `ERR_NON_CANONICAL_CBOR`, before decoding (no valid encoding exceeds 165 bytes); another type tag → `ERR_NON_CANONICAL_CBOR`; a version other than 1 → `ERR_UNSUPPORTED_VERSION`; CBOR profile and schema → `ERR_NON_CANONICAL_CBOR`. There are no layer-4 fields: `chain_hash`, round and signature are compared in that order at step 10 (`ERR_PROFILE_MISMATCH`, `ERR_ROUND_MISMATCH`, `ERR_RELEASE_INVALID`). A signature of the wrong length for the scheme passes the schema and is `ERR_RELEASE_INVALID`. - A reader MAY decode it on receipt, but MUST report its errors only at step 10, after steps 1 to 9: a capsule without credentials still gives `ERR_ACCESS_REQUIRED` (§69.1). - Trust: the object is not signed and has no "verified" field. For one round and one public key there is a single valid BLS signature, so any copy that verifies at step 10 is the release, whatever its source. -- drand's JSON, `{"round": …, "signature": "…"}`, SHOULD also be accepted as caller input (an input whose first non-whitespace byte is `{`). It names no chain, so step 10 compares no `chain_hash`; `randomness`, if present, MUST be the SHA-256 of the signature; an input over 8192 bytes or unreadable → `ERR_RELEASE_INVALID` at step 10, before the round. A Release Cache and the Release API MUST store and serve the release object, never this JSON. +- drand's JSON, `{"round": …, "signature": "…"}`, SHOULD also be accepted as caller input (an input whose first non-whitespace byte is `{`). It names no chain, so step 10 compares no `chain_hash`; `randomness`, if present, MUST be the SHA-256 of the signature; an input over 8192 bytes or unreadable → `ERR_RELEASE_INVALID` at step 10, before the round. Since v0.16 it is read strictly: JSON of RFC 8259 in UTF-8 whose value is an object, no object repeating a name, names compared exactly once their escapes are decoded (`"\u0072ound"` is `round`; `Round` is another name), no escape of a lone surrogate, and `round` a number without sign, fraction or exponent from 1 to 2⁵³ − 1. A common JSON reader keeps the last of two repeated names or folds case, and two readers would see two rounds in one input. A Release Cache and the Release API MUST store and serve the release object, never this JSON. - Vectors: `release.json`, `releases/.cbor`. ### 8.2 Two kinds of source, and step 9.c (§49, §63 step 9) @@ -430,9 +432,10 @@ round 1000 of Quicknet: 111 bytes (testdata/releases/1000.cbor) - It says how to open a Quicknet capsule if no DateKeys software exists: the Quicknet parameters (chain hash, public key, genesis time, period, q, DST), the `.dkc` frame and header, the release (object, archive entry or drand JSON) and its BLS check, the tlock stanza and FK_TIME (H2, H3, H4 as in §63), opening an age file from its file key (HKDF, the header HMAC, STREAM with ChaCha20-Poly1305), the inner layers (`age -d` with the identity of a `.dkk`, a recipient or a key of words; the Bech32 encoding of an X25519 identity), and the content of each format. - Needed: the `.dkc`, the release, a credential in `time_and_key`, a BLS12-381 library with pairing and the RFC 9380 hash to G1, SHA-256, HMAC-SHA256, HKDF-SHA256, ChaCha20-Poly1305, a CBOR decoder, and `age`. drand's tools do not serve: `tle` fetches the release from the network and accepts no given release, and `age` accepts no file key, which is why the annex describes those two steps in full. -- What it does not check (§79.8): it checks what decides that the result is correct (the release signature, r·G2 == U, every age MAC and every file's SHA-256), but not canonical encodings, `header_binding`, the 16 stanzas, the zero padding or the path rules. A capsule a conforming reader would reject may open by the annex; its content is what the age MACs sealed, without the guarantees of a conforming reader. +- Since v0.16 it also derives a key of words (§79.7, section 5) and states that the last STREAM chunk may be full (§79.5). +- What it does not check (§79.9, §79.8 in v0.15): it checks what decides that the result is correct (the release signature, r·G2 == U, every age MAC and every file's SHA-256), but not canonical encodings, `header_binding`, the 16 stanzas, the zero padding or the path rules. A capsule a conforming reader would reject may open by the annex; its content is what the age MACs sealed, without the guarantees of a conforming reader. - The official SDK SHOULD keep the annex text next to each `.dkc` (§62.1 rule 27); it contains no data of any capsule. -- Proof: `scripts/recovery_check.sh` (part of `scripts/check.sh`) opens `format3_single` (`time_only`) and `format3_time_and_key_portable` (`time_and_key`) with `scripts/recovery`, which imports no DateKeys package, nor `drand/tlock` or `drand/drand` (it uses `drand/kyber` and `drand/kyber-bls12381` for BLS, `filippo.io/age` and `golang.org/x/crypto`), and compares the recovered BODY with the fixtures (`artifacts.md` section 2). +- Proof: `scripts/recovery_check.sh` (part of `scripts/check.sh`) opens `format3_single` (`time_only`), `format3_time_and_key_portable` (`time_and_key`) and, since v0.16, `format3_time_and_key_words` (with its words) and `format3_full_chunk` (a full last chunk) with `scripts/recovery`, which imports no DateKeys package, nor `drand/tlock` or `drand/drand` (it uses `drand/kyber` and `drand/kyber-bls12381` for BLS, `filippo.io/age` and `golang.org/x/crypto`), and compares the recovered BODY with the fixtures (`artifacts.md` section 2). ## 9. Canonical CBOR and limits (§57, §58, §58.1) @@ -443,10 +446,10 @@ round 1000 of Quicknet: 111 bytes (testdata/releases/1000.cbor) ## 10. Writer rules (§61, §62, §62.1) -Selected MUST rules: write format 3 only; reject an unlock instant not after the writer's clock (the specification notes that a clock running late can still seal to an already published round, rule 2); 1 to 16 credentials, canonical and not low order; 16 slots with decoys in random order; all randomness from a CSPRNG, fresh per capsule (`capsule_id`, I_PAYLOAD, I_ACCESS, `credential_id`, decoys, permutation); know L before sealing; write the exact SEALED_CONTROL_LEN (resolved by sealing a provisional control of the same length, rule 7); the 32 KiB area; a fresh head salt; self-decoding of CONTROL_CBOR, HEAD_CBOR and SECURITY_CBOR with reader rules (rule 17); verify every signature and seal before writing (rule 19); deliver AUTHOR_MESSAGE as text with its code before each signature (rule 20); never store I_PAYLOAD, CONTROL_CBOR or content on disk while waiting for signatures (rule 25). SHOULD: self-check after sealing (rule 11) and erase secrets (rule 12); since v0.15, warn when sealing that opening years later needs the `.dkc`, the `.dkk` in `time_and_key`, and the release of the round, which exists only after the date (rule 26), and keep the text of the recovery annex next to the `.dkc` (rule 27). +Selected MUST rules: write format 3 only; reject an unlock instant not after the writer's clock (the specification notes that a clock running late can still seal to an already published round, rule 2); 1 to 16 credentials, canonical and not low order; 16 slots with decoys in random order; all randomness from a CSPRNG, fresh per capsule (`capsule_id`, I_PAYLOAD, I_ACCESS, `credential_id`, decoys, permutation); know L before sealing; write the exact SEALED_CONTROL_LEN (resolved by sealing a provisional control of the same length, rule 7); the 32 KiB area; a fresh head salt; self-decoding of CONTROL_CBOR, HEAD_CBOR and SECURITY_CBOR with reader rules (rule 17); verify every signature and seal before writing, and warn of a seal without `accuracy` (rule 19, v0.16); deliver AUTHOR_MESSAGE as text with its code before each signature (rule 20); never store I_PAYLOAD, CONTROL_CBOR or content on disk while waiting for signatures (rule 25). SHOULD: self-check after sealing (rule 11) and erase secrets (rule 12); since v0.15, warn when sealing that opening years later needs the `.dkc`, the `.dkk` in `time_and_key`, and the release of the round, which exists only after the date (rule 26), and keep the text of the recovery annex next to the `.dkc` (rule 27); since v0.16, keep the chains without roots and the OCSP responses that fit, MUST say what does not fit, and SHOULD offer to export it (rules 21 and 22). ## 11. What the reader should check against the code - The reference implementation implements no cryptography itself: age is `filippo.io/age`, tlock is `drand/tlock` (exported core), BLS is drand/kyber on `kilic/bls12-381`, signatures use the Go standard library; CBOR, DER and the CMS/X.509/RFC 3161 reader are the module's own code (`datekeys-go/SECURITY.md`). - The TypeScript and Dart implementations implement the tlock IBE themselves: TypeScript in `ibe.ts`, derived from `tlock-js`, on `@noble/curves` 2.4.0; Dart in pure Dart on `BigInt`, not constant-time, a choice the author accepted (`datekeys-dart/README.md`). -- The release object is the module's own code (`provider/release.go`, on its CBOR codec); a release in hand reaches `capsule.Open` through `provider.Supplier`, and `datekeys decrypt -release` reads a release object, drand's JSON or a local archive (`docs/traceability.md`, rows §47.1 and §49). `scripts/recovery`, the program behind the annex of §79, deliberately uses none of the module's code. +- The release object is the module's own code (`provider/release.go`, on its CBOR codec), and so is the strict reader of drand's JSON (`provider/drandjson.go`, v0.16), which the relay client uses too; a release in hand reaches `capsule.Open` through `provider.Supplier`, and `datekeys decrypt -release` reads a release object, drand's JSON or a local archive (`docs/traceability.md`, rows §47.1 and §49). `scripts/recovery`, the program behind the annex of §79, deliberately uses none of the module's code. diff --git a/revision_externa/precedence_and_language.md b/revision_externa/precedence_and_language.md index 8273928..782e5c7 100644 --- a/revision_externa/precedence_and_language.md +++ b/revision_externa/precedence_and_language.md @@ -6,8 +6,8 @@ The completeness review of v0.13 (step 3) asks, before an external review, to de ## 1. What the sources say today -- **Specification text** (`DateKeys_Protocol_Specification_v0.15.md`, Spanish). It uses RFC 2119 keywords in English with Spanish equivalents (§2). It does not say which language is normative or what wins when sources disagree. -- **CDDL** (`spec/datekeys.cddl`). Its header calls itself the «Normative companion» of the specification. The text delegates to it: «cualquier violación de una regla normativa de `datekeys.cddl` … → `ERR_NON_CANONICAL_CBOR`» (§57), and layer 3 of §69.1 checks «toda regla normativa de `datekeys.cddl`». Some CDDL rules are marked as non-normative implementation limits of the reference (§74). Its header comment names the current version, v0.15, and does not mention precedence. +- **Specification text** (`DateKeys_Protocol_Specification_v0.16.md`, Spanish). It uses RFC 2119 keywords in English with Spanish equivalents (§2). It does not say which language is normative or what wins when sources disagree. +- **CDDL** (`spec/datekeys.cddl`). Its header calls itself the «Normative companion» of the specification. The text delegates to it: «cualquier violación de una regla normativa de `datekeys.cddl` … → `ERR_NON_CANONICAL_CBOR`» (§57), and layer 3 of §69.1 checks «toda regla normativa de `datekeys.cddl`». Some CDDL rules are marked as non-normative implementation limits of the reference (§74). Its header comment names the current version, v0.16, and does not mention precedence. - **Test data** (`testdata/`, `testdata/README.md`). The README says: «The rules that decide each verdict are in the specification; this file points to them». §16 says the definitive vectors MUST be generated from the reference implementation and frozen before v1.0. §76 lists a fixture, a mutation test and the CDDL among the sources of a reproducible case. - **Reference implementation** (Go). §16 and §67 make it the generator of the vectors. The v0.8.2 refinements of §76 record cases where the reference and `testdata/README.md` held rules that the text did not, and the text was then changed to match. @@ -25,9 +25,9 @@ So in practice, until now, a gap between sources was closed by writing the rule 4. **A disagreement is a defect.** Any disagreement found between the sources is a defect: the text decides. It is recorded in the project's working notes (`docs/HANDOFF.md`) and fixed in the next version, with its reproducible case in §76. Until then the vectors and fixtures are not touched: the gates regenerate `testdata/` from the reference and fail on any change, and the TypeScript guard fails on a file that no test runs. 5. **Reviews are labelled by who did them.** §76 names each review with its kind: internal and AI-assisted, or external and human, with the reviewer's name, scope and date for an external one (§75 item 10). -## 3. Spec text changes this would need (next version, v0.16 or later) +## 3. Spec text changes this would need (next version, v0.17 or later) -The v0.15 text is tagged and does not change; none of the passages below changed in v0.15, which was the long-term recovery. These changes would go into the next version, each recorded in its §76 block: +The v0.16 text is tagged and does not change. None of the passages below changed in v0.15, the long-term recovery, or in v0.16, the answer to Astra's review, except item 6, which v0.16 fixed. These changes would go into the next version, each recorded in its §76 block: 1. **A new paragraph on language and precedence, at the end of §1** (decided by the author on 6 October 2026: not a §0, which would shift the numbering every document cites). Draft wording in Spanish (the normative language), for the author to edit: @@ -39,10 +39,11 @@ The v0.15 text is tagged and does not change; none of the passages below changed - «El diseño pasó una revisión de seguridad externa y dos revisiones adversariales» (v0.10 block): say that the security review was by Fable, an AI system; - «la revisión cruzada de Fable y Astra» (v0.11 block): say that Fable and Astra are AI systems; - «tres revisiones independientes» (v0.11 change 8): say that they were AI-assisted reviews; - - «segunda implementación independiente» (v0.8.2 refinements and amendment): say that the TypeScript implementation was written with the reference code in view. + - «segunda implementación independiente» (v0.8.2 refinements and amendment): say that the TypeScript implementation was written with the reference code in view; + - «la revisión de Astra» (v0.16 block): say that Astra is an AI system. 4. **§76, list of sources.** Add «revisión interna asistida por IA» as its own source, separate from «revisión criptográfica o técnica externa». 5. **§75 item 10.** Say that the external review is recorded in §76 with the reviewer's name, scope and date. -6. **Header, line 8.** «Implementación de referencia prevista: Go» → the reference implementation exists (`datekeys-go`). +6. **Header, line 8.** «Implementación de referencia prevista: Go» → the reference implementation exists (`datekeys-go`). Done in v0.16 (§76, v0.16 change 6). 7. **§16 and §67.** Align with rule 4: the vectors come from the reference, but the text decides; a vector that contradicts the text is a defect. 8. **§59.** Optionally add that a published English translation is informative and carries the SHA-256 of the Spanish version it translates. @@ -50,14 +51,14 @@ The v0.15 text is tagged and does not change; none of the passages below changed Not normative; they can be done in the repositories at any time, and the external reviewer will see them first: -- `spec/datekeys.cddl`, header comment: a line pointing to the precedence rule (it already names the current version, v0.15). +- `spec/datekeys.cddl`, header comment: a line pointing to the precedence rule (it already names the current version, v0.16). - `testdata/README.md`: one line stating the precedence rule. - `spec/README.md`: one line stating that the Spanish text is normative. -- `docs/traceability.md` and `README.md` of `datekeys-go`: at v0.15 in the frozen commit `fe50885` (`artifacts.md` section 5). +- `docs/traceability.md` and `README.md` of `datekeys-go`: at v0.16 in the frozen commit `b6ff17a` (`artifacts.md` section 5). ## 5. Decided by the author (6 October 2026) - The proposal is approved, with a paragraph at the end of §1 and rule 4 as written above. - Among implementations, the reference first. - Whether English becomes normative is left for v1.0. -- These text changes do not open a version now: they go into the version that records the findings of the external review, together with the labels of §76 and the record of the review (§75 item 10). The cover letter already states that every prior review was by AI. (v0.15, approved on 7 October 2026, is the long-term recovery and does not carry them.) +- These text changes do not open a version now: they go into the version that records the findings of the external review, together with the labels of §76 and the record of the review (§75 item 10). The cover letter already states that every prior review was by AI. (v0.15, approved on 7 October 2026, is the long-term recovery, and v0.16, approved the same day, the answer to Astra's review of v0.15; neither carries them.) diff --git a/revision_externa/scope_and_questions.md b/revision_externa/scope_and_questions.md index 34ff6d8..6dbfb37 100644 --- a/revision_externa/scope_and_questions.md +++ b/revision_externa/scope_and_questions.md @@ -1,10 +1,10 @@ # Scope and questions -*Section numbers (§) refer to `DateKeys_Protocol_Specification_v0.15.md`, tag `spec-v0.15`. "Known" marks a problem the project already knows about, with its source, so that you do not spend time rediscovering it; your opinion on it is still welcome.* +*Section numbers (§) refer to `DateKeys_Protocol_Specification_v0.16.md`, tag `spec-v0.16`. "Known" marks a problem the project already knows about, with its source, so that you do not spend time rediscovering it; your opinion on it is still welcome.* ## 0. Levels of scope -- **Level 1, required:** the protocol, with the Go reference implementation as evidence. Questions Q1 to Q4, Q6 to Q8 and Q10 to Q12. +- **Level 1, required:** the protocol, with the Go reference implementation as evidence. Questions Q1 to Q4, Q6 to Q8 and Q10 to Q13. - **Level 2, separate or optional:** Q5 and Q9, the CMS/X.509/RFC 3161 reader and the rules of the locator addresses. They are parser reviews and may need another profile of reviewer. - **Not in the paid scope:** the TypeScript and Dart implementations. They are available, with the same vectors, if the reviewer wants to look at them. @@ -21,6 +21,7 @@ - **Error precedence** as a possible oracle (§63, §69.1). - **Writer rules** that affect security: randomness, decoy disposal, self-checks (§62.1). - **Long-term recovery and the provider** (v0.15): the provider model (§7.6, §71), the release object (§47.1), network sources and a release in hand (§49), archives and cache services (§50), step 9.c and the release checks of step 10 (§63), the writer rules 26 and 27 (§62.1), and the informative recovery annex (§79). +- **The changes of v0.16:** a seal without `accuracy` (§29.7, §29.11), the strict reading of drand's JSON (§47.1), the key of words and the full last chunk in the annex (§79.5, §79.7), and the evidence a signature with certificates keeps (§29.10, §62.1 rules 19, 21 and 22). The reference implementation (Go), and the TypeScript and Dart implementations, are in scope as aids and as evidence: please report where an implementation disagrees with the text. @@ -114,9 +115,21 @@ v0.15 gives long-term recovery a design (§76, «Cambios normativos de la v0.15 - **Release object (§47.1).** Is the record `{0: "datekeys-release", 1: 1, 2: chain_hash, 3: round, 4: signature}`, unsigned and without a "verified" flag, sound as the single form a cache, the Release API and an archive entry use? Is naming the chain by drand's `chain_hash`, checked against the pinned profile first at step 10 (`ERR_PROFILE_MISMATCH`), enough, given that drand's JSON, also accepted as input, names no chain? Any issue in the size limit (1 to 1024 bytes, `ERR_NON_CANONICAL_CBOR`) or in reporting its errors only at step 10? - **Release in hand and step 9.c (§49, §63 step 9.c).** Since v0.15 a release in hand (a release object or drand's JSON from a file, or the entry of a local archive) is not compared with the local clock; 9.c applies only before a network request, and the person MAY ask a network source before `round_time`. The specification argues that a valid signature of a future round exists only if drand is compromised (§7.6), when the clock no longer protects confidentiality. Is that argument complete? Is there any risk in accepting a release in hand without the clock: for example a product that presents "opened before its date" in a misleading way, a test or debugging path that could be abused, or a future scheme where a signature for a future round could exist without a compromise? - **Archives and cache services (§50).** Is it sound to rest long-term recovery on archives of all rounds and on cache services, local or remote, from DateKeys or others, verified with the pinned key and never trusted, rather than on a release kept next to each capsule (the rejected `.dkr`, §76 v0.15 change 4)? Is the informative archive format (a CBOR header, then fixed-size signatures, missing rounds as zeros) adequate, and is treating a zero-filled, short, other-chain or out-of-range entry as `ERR_RELEASE_UNAVAILABLE` at step 9 right? Is the privacy statement complete (a remote archive or cache service learns the round; a local one does not; keeping only the rounds of known capsules reveals their dates)? -- **The annex (§79).** Is the annex correct and sufficient to open a capsule decades later without DateKeys software, and is its list of what it does not check (§79.8) honest about the weaker guarantee? +- **The annex (§79).** Is the annex correct and sufficient to open a capsule decades later without DateKeys software, and is its list of what it does not check (§79.9; §79.8 in v0.15) honest about the weaker guarantee? Q13 asks about what v0.16 added to it. - Is the written provider model (§7.6, v0.14) still accurate and complete with this design? -- **Known:** the specification promises no hosted archive or cache service; a project archive or service and its hosting are future work (§74), and none exists today. A capsule years ahead still depends on someone keeping the release of its round, the `.dkc` and, with a locator, the envelope rest (§50). If the network stops signing before the round, nothing opens the capsule (§7.6). The SDK rules 26 and 27 (warn when sealing; keep the annex next to the `.dkc`) are SHOULD and are not implemented in the clients yet; the Go CLI does not implement them either, nor the MAY of asking a network source before `round_time` (`docs/spec_v0.15/decisiones.md`, decision 11). +- **Known:** the specification promises no hosted archive or cache service; a project archive or service and its hosting are future work (§74), and none exists today. A capsule years ahead still depends on someone keeping the release of its round, the `.dkc` and, with a locator, the envelope rest (§50). If the network stops signing before the round, nothing opens the capsule (§7.6). The SDK rules 26 and 27 (warn when sealing; keep the annex next to the `.dkc`) are SHOULD; since 7 October 2026 the Go CLI and the `/create` page of `datekeys-ts` 0.5.0 implement them. Neither implements the MAY of a local reminder for `round_time` or of asking a network source before it (`docs/spec_v0.15/decisiones.md`, decision 11). + +### Q13. The changes of v0.16: seal precision, drand's JSON, the annex and the evidence (§29.7, §29.10, §29.11, §47.1, §62.1 rules 19, 21 and 22, §79.5, §79.7; v0.16) + +v0.16 answers a review of v0.15 by Astra, an AI system (§76, «Cambios normativos de la v0.16»; `docs/spec_v0.16/decisiones.md`): + +- **A seal without `accuracy` (§29.7, §29.11).** A valid seal is S4 only when its token carries `accuracy` and t + accuracy < round_time; otherwise S5, with a reason: sealed after or too close, no `accuracy` under the BTSP policy of ETSI EN 319 421 (0.4.0.2023.1.1), or no `accuracy`. A reader MUST NOT assume a precision from the policy. Is refusing anteriority without `accuracy` right, rather than a fixed margin or a table of policies with their bound (future work, §74)? Is the BTSP reason sound, given that an OID declares conformity and does not certify it? +- **The certificate at t (§29.10, step 6 of «Verificación»).** The certificate of a signer of `alg` 2 must be valid at `genTime`; with an `accuracy`, the true instant lies within t ± accuracy. Should validity cover the whole interval? +- **drand's JSON (§47.1).** Are the strict rules (RFC 8259 in UTF-8, an object, no repeated name in any object, names compared after decoding escapes, no lone surrogate, an integer round from 1 to 2⁵³ − 1, strings for `signature` and `randomness`) complete enough that two readers never see two rounds in one input? +- **The key of words in the annex (§79.7).** Is the recipe without tables exactly the normalisation of §38.1 for the text it covers, and is naming `UnicodeData.txt` of Unicode 18.0.0 by its SHA-256 a sound way to make the rest reproducible decades later? The reference checks both against every case of `wordkey.json`. +- **The last age chunk (§79.5).** The annex now says the last chunk may be full; is the rest of 79.5 faithful to C2SP age? +- **The evidence of a signature with certificates (§29.10, §62.1 rules 21 and 22).** The writer SHOULD keep the chains without their roots and the OCSP responses that fit, MUST say what it leaves out and SHOULD offer to export it; it never leaves out a signature, a signer's certificate or its seal. Is that enough for a long-term validator (CAdES with validation data, ETSI EN 319 122)? +- **Known:** no writer of the three libraries asks a time-stamping authority or signs with certificates yet, so rules 21 and 22 have no code; the library writer only returns the verdicts of the area it wrote (`Result.Security` in Go) so that an application can warn of a seal without `accuracy` (rule 19). The decision not to publish a recovery package (a bundle of `UnicodeData.txt`, the recovery program and the lists named by the annex) is recorded in `docs/spec_v0.16/decisiones.md`, decision 5: the annex cannot name the SHA-256 of a package that contains it, and there is no public host yet. ## 4. Known open problems (summary) @@ -140,7 +153,7 @@ So that they are not rediscovered. Sources: §74, §75, `docs/REVISION_completit | K14 | `kilic/bls12-381` is archived; `drand/tlock` has had no tagged release since August 2024 | `datekeys-go/SECURITY.md` | | K15 | The `datekeys.` prefix of `extension_id` is used but not reserved | review v0.13, 2.8 | | K16 | Three formats must be read forever, which multiplies cases in §64 and §69.1 (decided: capsules of older formats exist) | §70; review v0.13, 3.4 | -| K17 | Editorial, still in v0.15: header line 8 says «Implementación de referencia prevista»; §1 lists the Release API and Release Cache among what the document defines, while §45 to §47 fix only what they serve (the release object) and leave the HTTP form informative, and no service exists; the second list of §74 ends with a semicolon | review v0.13, 3.8 | +| K17 | Editorial points of v0.15 (the header line «Implementación de referencia prevista», §1 listing the Release API and Release Cache apart, the semicolon at the end of a list of §74, §79 naming only `drand/kyber-bls12381`): **closed in v0.16** | §76, v0.16 change 6 | ## 5. Not a question: stated non-goals diff --git a/revision_externa/threat_model.md b/revision_externa/threat_model.md index 58e5192..6fbac78 100644 --- a/revision_externa/threat_model.md +++ b/revision_externa/threat_model.md @@ -1,6 +1,6 @@ -# DateKeys v0.15: threat model, goals and non-goals +# DateKeys v0.16: threat model, goals and non-goals -*Informative English summary of spec §3, §4, §5, §7, §36.1, §55, §55.1 and §55.2 of `DateKeys_Protocol_Specification_v0.15.md`, with §45 to §50 and §79 where they concern recovery and the clock. The Spanish text is the reference. Additions of v0.14 are marked **(v0.14)**, those of v0.15 **(v0.15)**.* +*Informative English summary of spec §3, §4, §5, §7, §36.1, §55, §55.1 and §55.2 of `DateKeys_Protocol_Specification_v0.16.md`, with §45 to §50 and §79 where they concern recovery and the clock. The Spanish text is the reference. Additions of v0.14 are marked **(v0.14)**, those of v0.15 **(v0.15)** and those of v0.16 **(v0.16)**.* ## 1. Guiding principle (§3) @@ -110,10 +110,11 @@ With a signature or seal in format 3: - a writer can create two different capsules with the same `capsule_id`, both signed (equivocation); the creator can publish `capsule_digest` before the date against it (§43); - whoever can open a capsule can remake it after the date with another area, without a signature or with another; only a seal earlier than the round proves a signature existed before the date; - a dishonest or compromised TSA can misdate its seals; the protocol does not audit it, and the verdict names it; +- **(v0.16)** a seal whose token states no `accuracy` proves nothing before the date (S5, with its reason): without it, RFC 3161 leaves the precision to the TSA's policy, which the reader does not know, and no fixed margin is conservative for every TSA; - the external signing application receives AUTHOR_MESSAGE, which does not reveal the content; a compromised page or fake signing application can obtain a signature for a capsule the signer has not seen; a co-signing organisation that signs only AUTHOR_MESSAGE never sees the content. The AUTHOR_MESSAGE code lets the signer compare what is signed with what DateKeys shows; - a signer may sign under coercion, and the signature does not show it; - a stolen author key cannot be revoked: a reader that saved it keeps showing its label; -- DateKeys does not check who issued a certificate or a seal: anyone can make a certificate in another's name or a seal with any date; an official validator checks them with the evidence the capsule keeps. +- DateKeys does not check who issued a certificate or a seal: anyone can make a certificate in another's name or a seal with any date; an official validator checks them with the evidence the capsule keeps, which **(v0.16)** is only what fit in the area: the writer names what it left out (§29.10, §62.1 rule 21). ### 4.10 Web client (§7.10, §59) (v0.14) @@ -178,4 +179,6 @@ These are stated limits, not findings: - DateKeys never checks who issued a certificate or a seal (§29.10, §29.11). - **(v0.15)** No release archive or cache service is promised or hosted; long-term opening depends on someone keeping the releases (§50, §74). - **(v0.15)** A release in hand is not compared with the reader's clock (§63 step 9.c). -- **(v0.15)** The recovery annex does not check canonical encodings, `header_binding`, the 16 stanzas, the zero padding or the path rules; a capsule a conforming reader would reject may open by the annex (§79.8). +- **(v0.15)** The recovery annex does not check canonical encodings, `header_binding`, the 16 stanzas, the zero padding or the path rules; a capsule a conforming reader would reject may open by the annex (§79.9). +- **(v0.16)** A reader assumes no precision for a seal without `accuracy`, not even from its policy; a table of policies with their precision is future work (§29.11, §74). +- **(v0.16)** The evidence of a signature with certificates may be incomplete when it does not fit in the area; it then exists only where the writer exported it (§29.10).