Spec v0.16 draft: the decisions for the author and the handoff

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
main
dev 7 hours ago
parent fe42297994
commit 569d8c369f

@ -15,13 +15,13 @@ 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.15` en `6158be2`; `main` en `fe50885` | `spec-v0.15` en `fe50885`, y los de las versiones anteriores | Spec v0.15 aprobada, implementación de referencia, `testdata` compartido; `c49c67c` añade las palabras al azar, `27a75ee` el alfabeto de cada lista y la fuerza de las palabras, `96d8992` arregla `TestGenerate`, `e671032` añade la lista inglesa de la EFF, `92e7154` los dados y `aefc8f6` lo que dice el SDK al sellar |
| `datekeys-go` | `v0.16` en `2c29625`, el borrador; `v0.15` en `6158be2`; `main` en `fe50885` | `spec-v0.15` en `fe50885`, y los de las versiones anteriores | Spec v0.15 aprobada, implementación de referencia, `testdata` compartido; `c49c67c` añade las palabras al azar, `27a75ee` el alfabeto de cada lista y la fuerza de las palabras, `96d8992` arregla `TestGenerate`, `e671032` añade la lista inglesa de la EFF, `92e7154` los dados y `aefc8f6` lo que dice el SDK al sellar |
| `App` (`datekeys-ts`) | `v0.10` en `e8b5d35`; `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.15, y páginas `/inspect` y `/create`, con las palabras al azar; la última publicada es la 0.4.0 |
| `datekeys-dart` | `v0.15` en `e2296b0` | ninguno | Librería Dart completa, de la spec 0.15, con las palabras al azar; las ramas `v0.11` a `v0.14` se quedan atrás |
| `docs` | `main` | — | Este repo |
| `web` | `main` en `f2b8a38` | — | Landing de datekeys.com, sin remoto |
- **Spec:** la v0.15 está aprobada desde el 7-10, con SHA-256 `45105e693be4187af4dd30f4d254402612587b6427c746f5d29f07a541c1e3f3`. Es la recuperación a largo plazo: el objeto release, los archivos y servicios de caché que guardan todas las rondas, el release en la mano en el paso 9.c (opción B: no se compara con el reloj) y el anexo de recuperación del §79. No cambia ningún formato de `.dkc` ni de `.dkk`. No hay ningún borrador abierto. Las versiones aprobadas y sus SHA-256 están en `datekeys-go/spec/README.md`.
- **Spec:** la v0.15 está aprobada desde el 7-10, con SHA-256 `45105e693be4187af4dd30f4d254402612587b6427c746f5d29f07a541c1e3f3`. Es la recuperación a largo plazo: el objeto release, los archivos y servicios de caché que guardan todas las rondas, el release en la mano en el paso 9.c (opción B: no se compara con el reloj) y el anexo de recuperación del §79. No cambia ningún formato de `.dkc` ni de `.dkk`. El borrador de la v0.16 está abierto en la rama `v0.16` (ver «Protocolo», punto 0). Las versiones aprobadas y sus SHA-256 están en `datekeys-go/spec/README.md`.
- **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 `fe50885`, 142 ficheros, los mismos que en `aefc8f6`, de donde TypeScript y Dart copian hoy `testdata`, `wordlists` y `annex`. Gates el 7-10:
- Go: `scripts/check.sh` entero en `fe50885`, con el anexo de recuperación abriendo fixtures sin código de DateKeys, y `scripts/fuzz.sh 20s` en `fe50885` con sus 27 objetivos, sin fallos; `scripts/check.sh` entero otra vez en `27a75ee`, `96d8992`, `e671032`, `92e7154`, `aefc8f6` y `6158be2`;
@ -55,15 +55,16 @@ La recuperación a largo plazo quedó hecha con la v0.15, y las palabras al azar
### Protocolo
0. **La revisión de Astra de la v0.15 (7-10), para la v0.16.** Cinco hallazgos, todos comprobados y aceptados; la v0.15 no cambia. Tras su segunda respuesta, la dirección es:
- **Sello sin `accuracy`** (§29.11): S4 solo con una cota de precisión conocida; sin ella el sello verifica pero no acredita anterioridad, y S5 pasa a «No acredita que se sellara antes de la fecha de apertura», con el motivo. Se descarta el margen fijo que propuso Claude: ningún margen finito es conservador para toda TSA. Astra comprobó la política BTSP de ETSI EN 319 421 V1.3.1 (OID `0.4.0.2023.1.1`, §5.2; cota de un segundo, §5.1 y TIS-7.7.2-03), pero TIS-7.7.1-01 exige el perfil de EN 319 422, cuyo §5.2.2 obliga a llevar `accuracy`: un token BTSP sin ella incumple su perfil y da S5, «falta la precisión que exige su perfil»; aceptarlo con un segundo sería una tolerancia de DateKeys que habría que documentar y probar. Un OID declara conformidad, no la certifica. La propuesta de Claude: S4 solo con `accuracy` presente y válida, y un registro de políticas con cota fuera del token que hoy estaría vacío, así que basta con decir que una versión posterior podrá registrarlas. Hay que comprobar las cláusulas citadas al redactar.
- **Anexo y llave de palabras** (§79.6): el anexo incluirá la derivación de §38.1 (normalización, PBKDF2 con su sal y sus rondas, vector), con una receta exacta para un subconjunto explícito y comprobado (los alfabetos de las listas de DateKeys) y, para el resto, las tablas de Unicode 18.0.0 en un paquete de recuperación publicado una vez (el spec, esos datos, los vectores y `scripts/recovery`), no junto a cada cápsula: el anexo nombra su versión, su SHA-256 y el de cada fichero, para recuperarlo de cualquier copia y comprobar que es el esperado. `scripts/recovery` abrirá con palabras, con casos que ejerciten la normalización.
- **Último bloque de `age`** (§79.5): «el último puede ser más corto», y un vector con un último bloque completo. `scripts/recovery` ya lo hace bien.
- **Evidencias de la firma con certificado** (§29.10, regla 21): guardar la cadena sin la raíz y las respuestas OCSP cuando quepan; si no caben, el escritor dice qué deja fuera, también de la TSA y de los intermedios, y permite exportarlo; §29.10 promete solo lo conservado. Ligado a la medida del área (punto 3).
- **JSON de drand** (§47.1): regla estricta, con vectores: nombres exactos tras decodificar sus escapes (`"\u0072ound"` es `round`), un nombre repetido es `ERR_RELEASE_INVALID`, la ronda un entero sin fracción ni exponente. Hoy Go y TypeScript leen como `encoding/json`: el último gana y los nombres no distinguen mayúsculas.
- Pendiente del autor: aprobar esta dirección y cuándo abrir la v0.16 (antes o después del informe de la revisión externa).
0. **El borrador de la v0.16 (7-10), con la revisión de Astra de la v0.15.** En la rama `v0.16` de `datekeys-go` (`a2b71c2` y `2c29625`), sin código todavía: `SpecVersion` sigue en 0.15. Las [decisiones para el autor](spec_v0.16/decisiones.md) traen ocho, con su recomendación. En resumen:
- un sello sin `accuracy` da S5, con su motivo, y uno propio para la política BTSP de ETSI (cláusulas comprobadas en los textos de ETSI);
- el anexo trae la llave de palabras (79.7), con una receta sin tablas para las letras de las listas y `UnicodeData.txt` 18.0.0 por su SHA-256 para lo demás. Se aparta de Astra en un punto: no hay paquete de recuperación, porque el anexo no puede dar el SHA-256 de un paquete que lo contiene y no hay sitio público donde alojarlo (decisión 5);
- el último bloque de `age` puede estar completo;
- la regla 21 guarda las cadenas sin la raíz y las respuestas OCSP que quepan, y dice lo que deja fuera;
- el JSON de drand se lee estricto: sin nombres repetidos, nombres exactos y una ronda entera de 1 a 2⁵³ − 1;
- las erratas de K17 y de `drand/kyber` que estaban pendientes (punto 1) ya van aquí.
Pendiente del autor: aprobar el borrador, y si el anexo dice en su cabecera que es CC BY 4.0. Al aprobarlo, se implementa en Go y después en TypeScript y Dart (ver «Al aprobar» en las decisiones).
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).
Con ellos, dos retoques editoriales que el texto no puede llevar tras su tag: los de K17 del paquete (la cabecera «prevista», el §1 con la Release API y la Release Cache, el punto y coma del §74), y el §79, que nombra solo `drand/kyber-bls12381` cuando `scripts/recovery` usa también las interfaces de `drand/kyber`.
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.
3. **Medir el área de 32 KiB y cerrar el perfil CMS** (§74; §75, punto 13), con firmas reales con certificado de varios países y sellos de autoridades reales. Necesita firmas del autor o permiso para pedir sellos a una autoridad pública.
4. **Lo que el §74 aún llama provisional:** los esquemas de bytes de la cabecera, el control y la `.dkk`, los límites de los campos y los vectores definitivos del perfil. Conviene congelarlo con el informe de la revisión delante.
@ -156,4 +157,5 @@ La recuperación a largo plazo quedó hecha con la v0.15, y las palabras al azar
El [README](README.md#documentos) los lista. Para retomar, lo principal es:
- [revision_externa/](revision_externa/NOTA_PARA_EL_AUTOR.md): el paquete y su nota;
- [REVISION_completitud_v0.13.md](REVISION_completitud_v0.13.md): qué falta antes de la v1.0;
- [spec_v0.15/decisiones.md](spec_v0.15/decisiones.md): las decisiones de la última versión, y [diseno_recuperacion.md](diseno_recuperacion.md), su diseño.
- [spec_v0.16/decisiones.md](spec_v0.16/decisiones.md): las decisiones del borrador abierto;
- [spec_v0.15/decisiones.md](spec_v0.15/decisiones.md): las de la última versión aprobada, y [diseno_recuperacion.md](diseno_recuperacion.md), su diseño.

@ -51,6 +51,7 @@ Para retomar el trabajo, lee [HANDOFF.md](HANDOFF.md): el estado de cada repo, l
| [revision_externa/](revision_externa/NOTA_PARA_EL_AUTOR.md) | El paquete para una revisión criptográfica externa, en inglés, con una [nota para el autor](revision_externa/NOTA_PARA_EL_AUTOR.md) |
| [diseno_recuperacion.md](diseno_recuperacion.md) | Diseño de la recuperación a largo plazo: el objeto de release, el reloj del paso 9.c, el archivo de releases y el anexo de recuperación, con las decisiones para el autor. Su fichero `.dkr` se descartó al aprobar la v0.15 |
| [spec_v0.15/](spec_v0.15/decisiones.md) | La v0.15, aprobada el 7-10, la recuperación a largo plazo: las [decisiones del autor](spec_v0.15/decisiones.md), sin el fichero `.dkr`, que se descartó |
| [spec_v0.16/](spec_v0.16/decisiones.md) | El borrador v0.16 (7-10), con la revisión de Astra de la v0.15: las [decisiones para el autor](spec_v0.16/decisiones.md), con su recomendación |
| [spec_v0.9/](spec_v0.9/README.md) | Papeles de trabajo del borrador v0.9: diseño, revisiones y correcciones pendientes |
| [spec_v0.10/](spec_v0.10/formato3_diseno.md) | Formato de cápsula 3 en diseño, en tres entregas: varios ficheros, firma de autor y sello de tiempo. El diseño, con sus revisiones incorporadas, la revisión de Fable y la revisión final del borrador del spec |
| [spec_v0.11/](spec_v0.11/llave_palabras.md) | Papeles de trabajo de la v0.11, ya etiquetada. Contiene: <br>la [llave de palabras](spec_v0.11/llave_palabras.md); <br>la [consulta a Fable y Astra sobre el tamaño del área de firmas y sellos](spec_v0.11/area_firmas_para_revision.md) y [su propuesta](spec_v0.11/revision_fable_astra.md); <br>la [revisión del borrador](spec_v0.11/revision_borrador.md); <br>la [revisión de lo hecho en la sesión del 1 y 2 de octubre](spec_v0.11/revision_sesion_1_2_octubre.md), con los fallos pendientes de arreglar |

@ -0,0 +1,85 @@
# Borrador v0.16: decisiones para el autor
*7 de octubre de 2026. El borrador está en la rama `v0.16` de `datekeys-go` (`2c29625`), en `spec/DateKeys_Protocol_Specification_v0.16.md`. Recoge la revisión de Astra de la v0.15, con la dirección acordada tras su segunda y su tercera respuesta: cinco hallazgos, todos comprobados contra el texto y el código. Todavía no hay código: `SpecVersion` sigue en 0.15, y el anexo que escribe la CLI es el de la v0.15.*
Si apruebas lo que sigue tal como está, basta con decir «apruebo el borrador». Después se implementa en Go, con sus vectores, y se lleva a TypeScript y a Dart. La versión se cierra con su tag cuando las tres pasen.
## Lo que hace el borrador
1. **El sello sin `accuracy`** (§29.7, §29.11). Un sello válido solo acredita que es anterior a la fecha de apertura (S4) si su token lleva `accuracy` y t + precisión < round_time. Sin `accuracy` da S5, y S5 cambia de texto: «No acredita que se sellara antes de la fecha de apertura: ‹motivo›.» Hay tres motivos, que se comprueban en este orden:
- «se selló después de esa fecha o demasiado cerca de ella»;
- «el sello no dice la precisión que exige su política», si la política del token es la BTSP de ETSI (0.4.0.2023.1.1), que obliga a llevar `accuracy`;
- «el sello no dice su precisión», en los demás casos.
En F6, la línea de un firmante cuyo sello no lleva `accuracy` dice «sin acreditar que fuera antes de la fecha de apertura» y el motivo. El texto anterior de S5, «Sellado después de la fecha de apertura», era falso para un sello anterior a la fecha cuya precisión llegaba a ella.
2. **La llave de palabras en el anexo** (§79.7, nueva). El anexo trae la derivación entera: P, la sal, PBKDF2 con 600 000 iteraciones y dos vectores. La normalización va en dos niveles:
- **Sin tablas**, exacta para el texto que dan las listas de DateKeys: ASCII; á, é, í, ó, ú, ü y ñ con sus mayúsculas; y las marcas de U+0300 a U+036F. Se quitan las marcas, cada letra con tilde pasa a su letra base, A a Z pasan a minúsculas y se parte por los espacios.
- **Completa** para cualquier otro texto: NFD, quitar las marcas, minúscula simple y partir por los espacios. Usa `UnicodeData.txt` de Unicode 18.0.0, que el anexo nombra por su SHA-256 y su dirección en unicode.org.
El segundo vector, «Ñandú», dos espacios, «PINGÜINO», un tabulador y «camión árbol Éter ola», da la misma llave que «nandu pinguino camion arbol eter ola» y que el mismo texto con las tildes escritas como marcas sueltas. La v0.16 renumera El contenido como 79.8 y Lo que el anexo no comprueba como 79.9.
3. **El último bloque de `age`** (79.5). «El último más corto» pasa a «el último puede ser más corto, o estar completo». Con 65 536 bytes de plaintext hay un solo bloque, completo y marcado como último. `scripts/recovery` ya lo hacía bien, pero ningún fixture lo comprobaba.
4. **Las evidencias de la firma con certificado** (§29.10, §62.1 reglas 21 y 22). El escritor SHOULD guardar:
- la cadena de cada firmante, sin su raíz;
- la de la autoridad de cada sello, sin su raíz;
- las respuestas OCSP.
Así se sustituye el «podar a un certificado por firmante» de la v0.15. Si algo no cabe, el escritor MUST decir qué deja fuera y SHOULD ofrecer exportarlo. Nunca deja fuera una firma, el certificado de un firmante ni su sello. §29.10 ya no promete la respuesta OCSP: promete lo que la cápsula conserva.
5. **El JSON de drand, estricto** (§47.1):
- ningún objeto repite un nombre;
- los nombres se comparan exactos tras decodificar sus escapes;
- un sustituto suelto hace el JSON mal formado;
- `round` es un entero sin signo de 1 a 2⁵³ − 1, sin fracción ni exponente.
Lo demás es `ERR_RELEASE_INVALID`. Hoy las tres implementaciones leen como `encoding/json` de Go: el último de dos nombres repetidos gana, y `ROUND` vale como `round`. Comprobado: `{"round":1000,"ROUND":1001,…}` da la ronda 1001 en Go, y 1000 en un lector con `JSON.parse` o con el `json` de Python.
6. **Erratas.**
- §1 junta en una línea la Release API, la Release Cache y el objeto release.
- La lista de §74 acaba en punto.
- §77 añade ETSI EN 319 421 y 319 422.
- §79 nombra las interfaces de `drand/kyber`, que `scripts/recovery` también importa.
- La cabecera ya no dice «prevista» de la implementación de referencia.
No cambia ningún formato. Cambian dos veredictos, el del sello sin `accuracy` y el de algunos JSON de drand, y §70 y §76 lo registran.
## Decisiones
1. **El sello sin `accuracy` acredita como S5, sin margen ni tabla de políticas.** Es lo que pidió Astra: ningún margen fijo vale para toda TSA, y la precisión de una política solo la sabe quien la conoce. Una tabla de políticas con su precisión, para dar S4 a un sello sin `accuracy`, queda en §74 como trabajo futuro: habría que mantenerla en el spec y en las tres implementaciones.
- Recomendación: aprobar.
2. **Un motivo propio para un token BTSP sin `accuracy`.** Cuesta comparar un OID, y dice algo útil: que la autoridad incumple su propia política, y no solo que el sello no basta. Las cláusulas están comprobadas en los textos de ETSI: EN 319 421 V1.3.1, §5.1 (1 s o mejor), §5.2 (el OID), TIS-7.7.1-01 (el perfil de EN 319 422) y TIS-7.7.2-03; y EN 319 422 V1.1.1, §5.2.2 («the accuracy field shall be present»).
- Recomendación: aprobar.
3. **El escritor MUST avisar de un sello sin `accuracy`** (regla 19) y SHOULD ofrecer pedirlo a otra autoridad. No lo rechaza: el sello sigue probando que la firma existía en t. Hoy ningún escritor pide sellos, ni la CLI ni `/create`, así que la regla no cambia ningún código.
- Recomendación: aprobar.
4. **La receta sin tablas.** Cubre las letras de las dos listas, el español y el inglés de la EFF, y cualquier ASCII. Una letra de fuera, como la ç catalana o la ß, ya necesita las tablas. Ampliarla a todo Latin-1 es posible, pero alarga el anexo con casos que las listas no dan.
- Recomendación: aprobar como está.
5. **Sin paquete de recuperación en el spec.** Astra proponía nombrar en el anexo un paquete de recuperación por su versión, su SHA-256 y el SHA-256 de cada fichero. El borrador nombra solo `UnicodeData.txt` por su SHA-256. Sirve cualquier copia que lo cumpla, y unicode.org conserva todas sus versiones. Un paquete tiene dos problemas:
- el anexo no puede dar el SHA-256 de un paquete que lo contiene;
- necesita un sitio público donde alojarlo, y hoy no hay ninguno: el Gitea no es nuestro.
Cuando haya sitio, el paquete puede llevar `UnicodeData.txt`, el código de `scripts/recovery` y las listas, y el anexo lo nombraría sin contenerse a sí mismo.
- Recomendación: aprobar sin paquete, y añadirlo a §74 cuando haya sitio público.
6. **Las evidencias, SHOULD guardar y MUST decir lo que falta.** No es un MUST guardar las cadenas, porque pueden no caber ni en 64 KiB con varios firmantes. Los veredictos del lector no cambian: un certificado de más no decide nada. Ningún escritor firma hoy con certificados.
- Recomendación: aprobar. La medida del área (§74, §75 punto 13) incluirá las cadenas sin la raíz.
7. **La ronda del JSON de drand, de 1 a 2⁵³ − 1**, como en el objeto release. La ronda 0 y las mayores pasan de `ERR_ROUND_MISMATCH` a `ERR_RELEASE_INVALID`. Así el JSON y el objeto tienen el mismo rango.
- Recomendación: aprobar.
8. **Los vectores de los sellos.** En `security_cms.json`, once de los trece casos que dan S4 llevan un token sin `accuracy`, porque el generador no la escribe si es 0. Con la v0.16 darían S5, y algunos dejarían de probar lo que dicen. Por ejemplo, «an authority named with 50 spaces» prueba cómo se muestra el nombre de la autoridad, y S5 no lo muestra. La propuesta:
- regenerar esos casos con una `accuracy` de 1 s, para que sigan en S4;
- añadir los casos sin `accuracy` de §64: años antes de la fecha, de la política BTSP, después de la fecha y en `alg` 2;
- añadir uno con una `accuracy` de 0 segundos.
Los fixtures no cambian: `format3_sealed` y `format3_signed_cms` ya llevan `accuracy`.
- Recomendación: aprobar.
## Lo que queda para después
- **La revisión externa.** Su paquete sigue en la v0.15. Al cerrar la v0.16 se le añade este cambio, que responde a una revisión.
- **La licencia del anexo.** El anexo es texto del spec, CC BY 4.0, y ni su cabecera ni el README de Go lo dicen. Está pendiente de tu respuesta: si apruebas añadirla, irá en la cabecera que genera `annex_test.go`.
## Al aprobar
- `SpecVersion` 0.16, el SHA-256 en `spec/README.md`, el anexo regenerado con `DATEKEYS_WRITE_ANNEX=1`, el tag `spec-v0.16` y `main`.
- En Go:
- los veredictos y textos del sello;
- el lector estricto del JSON de drand;
- `scripts/recovery` con las palabras;
- el fixture con un último bloque completo;
- los vectores nuevos.
- TypeScript y Dart siguen a Go con los vectores sincronizados. En TypeScript, la guarda exige una prueba para cada fichero nuevo de `testdata`.
Loading…
Cancel
Save

Powered by TurnKey Linux.