Stage 5b in the README, the changelog and the library

lib/datekeys.dart exports author.dart and security.dart, as package
capsule of Go exports the commitments and the evaluation, and the tests
that imported them from lib/src import them from the library.

The README and the changelog give the testdata of the branch v0.12 of
datekeys-go, the modules of part 5b with their notes, the boundary with
the reader of CMS of part 5c, the vectors of the security area, and the
tests and the faults injected.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
v0.11
dev 2 days ago
parent a7f6f94c19
commit a7a7423d3e

@ -4,6 +4,27 @@ Cambios notables de la librería Dart. El proyecto usa versionado semántico; mi
## Especificación 0.11, en la rama `v0.11` — sin versión ## Especificación 0.11, en la rama `v0.11` — sin versión
### Etapa 5b: los compromisos, `SECURITY_CBOR`, la firma de `alg` 1 y los veredictos (05-10-2026)
- **`testdata/` de la rama `v0.12` de `datekeys-go`,** en `c531e93`, cuyo `testdata/` es el de `601e6d2`, el de `datekeys-ts`: 133 ficheros, que dicen aún `"spec": "0.11"`, como el `SpecVersion` de Go, hasta que el autor apruebe el borrador. Frente al tag `spec-v0.11`, trae los fixtures `format3_unsigned` y `format3_note`, `format3_seal_unsupported` con `seal_type` 4294967295, los registros nuevos de `format3_sealed` y `format3_signed_cms`, el corpus de 218 casos, `note.json`, `security.json` con su contexto y sus líneas, `security_cms.json` de 135 casos y `locator.json`, que es de la etapa 7.
- Los generadores de `tool/` que leen el `testdata/` lo leen otra vez: `mutation_texts.json`, `open_cases.json`, `formats_*.json` con `formats_vectors.g.dart`, `ibe_vectors.json` y `age_fixtures.json` cambian; `release_vectors.json`, `primitives.json` y las vistas de `open_vectors.g.dart` salen iguales. `age.json` no lee el `testdata/` y queda congelado.
- Las pruebas cuentan 26 fixtures y 218 casos, la inspección de `format3_note` da la nota de su registro, y los 16 casos de `note.json` dan el resultado y el detalle de Go. Ningún caso descubrió una diferencia con Go: la librería no cambia.
- **Los compromisos** (`lib/src/author.dart`), port de `signature.go`: `payloadCommit`, `controlCommit` sobre `CONTROL_SIG` en cada formato, `headDigest`, `signersDigest`, `authorMessage` con su prefijo y sus 99 bytes, `authorCode`, que toma los bytes como Go, `sigPart` y `sealSubject`.
- **`SECURITY_CBOR`** (`lib/src/security.dart`), port de `format3.go` y de `signature.go`: el mapa exterior, `author-signature` y `seal` con los esquemas y los límites de Go, sus codificadores y sus lectores, y `evaluateSecurity`, que nunca lanza:
- X para un mapa exterior que falla su capa 2 o 3, la versión 2 incluida;
- F0 a F4 para la firma, con `verifyStrict` en `alg` 1 y la clave buscada entre las guardadas por su cadena `dkauthor1…`, y S0 a S2 para el sello;
- un fallo dentro de una parte es de esa parte, F1 o S2, como Go recupera un panic;
- sin contexto, lee como un lector de la v0.10.
- **La frontera con el lector de CMS** de la parte 5c es `CmsEvaluator`, con `evaluateSignature` y `evaluateSeal`, como `evaluateCMS` y `evaluateSeal` de Go. Sin él, la firma de `alg` 2 y el sello de `seal_type` 2 en un contexto quedan sin evaluar, en null, nunca con un veredicto supuesto; la otra parte se evalúa igual. `holderText`, el nombre de un certificado del §29.7, ya está aquí.
- **Los veredictos** (`lib/src/verdicts.dart`) con los textos del borrador v0.12: `Verdict.text`, `Verdicts.lines`, con los nombres entre « y », la autoridad de cada sello en las líneas de F6 con su aviso, los resultados en español y t en RFC 3339 con su fracción, y `Verdicts.sealedAt`, con `Detail`, `SignerLine` y `SignerResult`. `Verdicts` puede tener evaluada una parte sola. Partir las líneas en filas con ` ↳ ` es de la CLI de Go, no de su librería, y no se porta.
- **La apertura evalúa el área como Go:** `OpenOptions.evaluator` es ahora `evaluateSecurityInput`, con `securityContext`, el `newSecurityContext` de Go con el `head_digest`. `format3_signed`, `format3_unsigned`, `format3_signature_unsupported`, `format3_seal_unsupported`, `format3_security_v2` y `format3_note` dan al abrirse los veredictos y las líneas de Go; `format3_signed_cms` y `format3_sealed`, la parte que no necesita el lector de CMS.
- **`lib/datekeys.dart`** exporta `author.dart` y `security.dart`, como el paquete `capsule` de Go.
- **Vectores de Go:**
- `tool/security_go_vectors.go`, en el contexto del módulo de `datekeys-go` en `c531e93`, escribe `security_vectors.json`: los compromisos, también del control de cada fixture en cada formato; los codificadores; 1730 evaluaciones de `EvaluateSecurityIn` en 23 contextos y sin contexto, del mapa exterior, de `author-signature` y de `seal` rotos de todas las formas de sus esquemas y en sus límites, de firmas de `alg` 1 válidas e inválidas, también los casos de «Taming the many EdDSAs» hechos sobre `AUTHOR_MESSAGE` buscando el contexto, y de 1500 mutaciones de una semilla fija; las líneas y `SealedAt` de veredictos con cada detalle; y `holderText`, al que llega con `go:linkname`. `security_vectors.g.dart` lleva todo salvo siete de cada ocho evaluaciones, para Node.js;
- `tool/open_go_vectors.go` guarda en `open_cases.json` los veredictos de cada cápsula del formato 3 que se abre, con sus líneas, y abre los fixtures firmados con `alg` 1 también con su clave guardada, F3, y con otra, F4.
- **Pruebas.** Las 1730 evaluaciones de Go, con sus veredictos, sus líneas, `alg` y `seal_type` y las partes del lector de CMS; los 24 casos de `security.json`, 23 enteros y uno sin su sello de `seal_type` 2; los compromisos, la firma y el sello de cada fixture del formato 3 frente a su registro; los veredictos de cada apertura de `open_cases.json` y de los 11 casos del corpus que se abren; y la frontera con un lector de CMS de prueba. 58 pruebas nuevas en la VM y 14 en Node.js: 1378 y 305 en total.
- **Fallos inyectados**, uno a uno y revertidos: 12, y las pruebas los detectan todos en la VM y en Node.js: los compromisos de D y de `SEAL_SUBJECT` en otro orden, el prefijo de `AUTHOR_MESSAGE` cambiado, una clave de orden pequeño aceptada, F4 con la clave guardada y F3 con la etiqueta de otra clave, un evaluador que falla la apertura, la línea de F0 y el resultado de un firmante en inglés, un nombre de 65 puntos de código mostrado, y F1 o S1 supuestos para `alg` 2 o `seal_type` 2 sin el lector de CMS.
### Etapa 4c: el head, la nota pública, la inspección y la apertura (05-10-2026) ### Etapa 4c: el head, la nota pública, la inspección y la apertura (05-10-2026)
- **La nota pública del §24.1** (`lib/src/note.dart`), port de `CheckNote`, `NewNote` y `Note` de `extension` de `datekeys-go` en `c531e93`: `checkNote` y `checkNoteData`, con la longitud, el UTF-8 y las reglas de texto del autor declarado en ese orden y con los textos de Go; `newNote`, `publicNote` y `unusableNote`, y `Header.publicNote` y `Header.unusableNote`. `StandardExtensions` comprueba ya la nota como el `Standard` de Go, y su parámetro `validateNote` desaparece. - **La nota pública del §24.1** (`lib/src/note.dart`), port de `CheckNote`, `NewNote` y `Note` de `extension` de `datekeys-go` en `c531e93`: `checkNote` y `checkNoteData`, con la longitud, el UTF-8 y las reglas de texto del autor declarado en ese orden y con los textos de Go; `newNote`, `publicNote` y `unusableNote`, y `Header.publicNote` y `Header.unusableNote`. `StandardExtensions` comprueba ya la nota como el `Standard` de Go, y su parámetro `validateNote` desaparece.

@ -6,7 +6,7 @@ Es la tercera implementación de la especificación, después de la de referenci
## Estado ## Estado
Están hechas las etapas 0 a 4 del plan (`docs/PLAN_dart.md` del espacio de trabajo): Están hechas las etapas 0 a 4 del plan (`docs/PLAN_dart.md` del espacio de trabajo) y la parte 5b de la etapa 5:
- la etapa 0, el paquete, sus herramientas y `testdata/` sincronizado; - la etapa 0, el paquete, sus herramientas y `testdata/` sincronizado;
- la etapa 1, los errores normativos, los bytes, el perfil CBOR del §58 y el DER estricto, también el de los tiempos; - la etapa 1, los errores normativos, los bytes, el perfil CBOR del §58 y el DER estricto, también el de los tiempos;
- la etapa 2, las primitivas y la lectura de `age`; - la etapa 2, las primitivas y la lectura de `age`;
@ -14,11 +14,12 @@ Están hechas las etapas 0 a 4 del plan (`docs/PLAN_dart.md` del espacio de trab
- la etapa 4, en tres partes: - la etapa 4, en tres partes:
- la 4a, las reglas de rutas y de textos con las tablas de Unicode 18.0.0, y la llave de palabras; - la 4a, las reglas de rutas y de textos con las tablas de Unicode 18.0.0, y la llave de palabras;
- la 4b, los formatos de la cápsula y de la llave de acceso: las tramas, `PUBLIC_HEADER`, `CONTROL_CBOR` de los tres formatos, la `.dkk`, las extensiones, el Provider Profile, la DateKey con sus rondas y el relleno; - la 4b, los formatos de la cápsula y de la llave de acceso: las tramas, `PUBLIC_HEADER`, `CONTROL_CBOR` de los tres formatos, la `.dkk`, las extensiones, el Provider Profile, la DateKey con sus rondas y el relleno;
- la 4c, el head del formato 3, la nota pública, la inspección (pasos 1 a 8) y la apertura (pasos 9 a 18) de los tres formatos. - la 4c, el head del formato 3, la nota pública, la inspección (pasos 1 a 8) y la apertura (pasos 9 a 18) de los tres formatos;
- la parte 5b de la etapa 5: los compromisos de lo que firma un autor y sella un sello, `SECURITY_CBOR`, la firma de `alg` 1 y los veredictos con sus textos y sus líneas.
La librería ya abre cápsulas reales, de los tres formatos, con todas sus credenciales. La firma y el sello, la etapa 5, no: sus veredictos llegan por un punto de enganche que hoy no evalúa nada. La librería ya abre cápsulas reales, de los tres formatos, con todas sus credenciales, y evalúa su área de seguridad como Go: la firma de `alg` 1 y todos los veredictos de su forma. La firma de `alg` 2 y el sello de `seal_type` 2 necesitan el lector de CMS: hasta la parte 5c quedan sin evaluar, nunca con un veredicto supuesto.
Las etapas 2 y 3 se hicieron en paralelo, en ramas aparte desde la etapa 1, y se integraron el 5 de octubre de 2026. Las partes 4a y 4b también: la 4a, en la rama `stage4a`, se integró encima de la 4b el mismo día. La 4c se hizo después, en la rama `v0.11`. Las etapas 2 y 3 se hicieron en paralelo, en ramas aparte desde la etapa 1, y se integraron el 5 de octubre de 2026. Las partes 4a y 4b también: la 4a, en la rama `stage4a`, se integró encima de la 4b el mismo día. La 4c se hizo después, en la rama `v0.11`, y la 5b también, en paralelo con la 5a, el lector de CMS, que va en la rama `stage5a`.
La etapa 1 porta tres ficheros de `datekeys-go` en `601e6d2`, con las mismas lecturas, las mismas comprobaciones en el mismo orden y los mismos textos de error: La etapa 1 porta tres ficheros de `datekeys-go` en `601e6d2`, con las mismas lecturas, las mismas comprobaciones en el mismo orden y los mismos textos de error:
@ -133,11 +134,32 @@ Notas de la parte 4c:
- **La salida.** El contenido de los formatos 1 y 2 va a `OpenOptions.output`, un `ByteSink`, según `age` autentica cada chunk, y los ficheros del formato 3 a `OpenOptions.sink`, un `FileSink`, en el orden del head. Los dos son obligatorios para su formato: sin ellos, la apertura lanza un `ArgumentError` justo después del paso 2, antes de pedir nada, como `ErrSinkRequired` y `errWriterRequired` de Go. La salida se cierra solo al publicar y se aborta tras cualquier fallo, también de un paso anterior al 17 y también para una cápsula del formato 3; el sink se aborta tras cualquier fallo posterior a su `begin` (§56). Lo que reciben es suyo: copias, nunca vistas de un búfer que la apertura siga leyendo. - **La salida.** El contenido de los formatos 1 y 2 va a `OpenOptions.output`, un `ByteSink`, según `age` autentica cada chunk, y los ficheros del formato 3 a `OpenOptions.sink`, un `FileSink`, en el orden del head. Los dos son obligatorios para su formato: sin ellos, la apertura lanza un `ArgumentError` justo después del paso 2, antes de pedir nada, como `ErrSinkRequired` y `errWriterRequired` de Go. La salida se cierra solo al publicar y se aborta tras cualquier fallo, también de un paso anterior al 17 y también para una cápsula del formato 3; el sink se aborta tras cualquier fallo posterior a su `begin` (§56). Lo que reciben es suyo: copias, nunca vistas de un búfer que la apertura siga leyendo.
- **El resultado.** `openCapsule` no lanza por una cápsula inválida: el fallo está en `Opened.error` y es la última comprobación, con el texto de Go. `Opened.checks` son las de todos los pasos, con el detalle que Go escribe en cada uno. - **El resultado.** `openCapsule` no lanza por una cápsula inválida: el fallo está en `Opened.error` y es la última comprobación, con el texto de Go. `Opened.checks` son las de todos los pasos, con el detalle que Go escribe en cada uno.
- **Las credenciales.** `OpenOptions.identities` son identities X25519 en bruto, de 32 bytes: las del llamador y la llave de palabras, que `wordKey` deriva de la cadena, la ronda y el `capsule_id` que da la inspección, como hace la CLI de Go. La `.dkk` va decodificada (`accessKey`) o todavía codificada (`accessKeyFile`), que se decodifica en el paso 9.a y solo para `time_and_key`. La apertura no borra las credenciales del llamador; sí sus copias, la `.dkk` que decodifica, `I_PAYLOAD` y las claves de cada fichero `age`. - **Las credenciales.** `OpenOptions.identities` son identities X25519 en bruto, de 32 bytes: las del llamador y la llave de palabras, que `wordKey` deriva de la cadena, la ronda y el `capsule_id` que da la inspección, como hace la CLI de Go. La `.dkk` va decodificada (`accessKey`) o todavía codificada (`accessKeyFile`), que se decodifica en el paso 9.a y solo para `time_and_key`. La apertura no borra las credenciales del llamador; sí sus copias, la `.dkk` que decodifica, `I_PAYLOAD` y las claves de cada fichero `age`.
- **La firma y el sello** son de la etapa 5. El área de `security` se lee solo hasta donde lo exigen la trama de `BODY` y el área, y sus veredictos los da `OpenOptions.evaluator`, que recibe lo que toman `newSecurityContext` y `EvaluateSecurityIn` de Go: `SECURITY_CBOR`, los bytes del head, el control decodificado y el formato, el `round_time` y las claves de autor. Se llama, como en Go, al leer el head y antes de decodificarlo. El de hoy, `notEvaluated`, da `Verdicts.notEvaluated`; uno que lance da `Verdicts.failed` y la cápsula se abre igual (§29.3). `OpenOptions.accept`, el `Accept` de Go, ve los veredictos tras todas las comprobaciones del paso 17 y antes del 18: si lanza, no se publica nada, el sink se aborta y `Opened.refusal` guarda lo que lanzó. - **La firma y el sello** son de la etapa 5. El área de `security` se lee solo hasta donde lo exigen la trama de `BODY` y el área, y sus veredictos los da `OpenOptions.evaluator`, que recibe lo que toman `newSecurityContext` y `EvaluateSecurityIn` de Go: `SECURITY_CBOR`, los bytes del head, el control decodificado y el formato, el `round_time` y las claves de autor. Se llama, como en Go, al leer el head y antes de decodificarlo. Desde la parte 5b es `evaluateSecurityInput`; `notEvaluated` da `Verdicts.notEvaluated`, para quien no muestra veredictos; uno que lance da `Verdicts.failed` y la cápsula se abre igual (§29.3). `OpenOptions.accept`, el `Accept` de Go, ve los veredictos tras todas las comprobaciones del paso 17 y antes del 18: si lanza, no se publica nada, el sink se aborta y `Opened.refusal` guarda lo que lanzó.
- **`StandardExtensions`** comprueba ya la nota con las reglas del §24.1, como el `Standard` de Go. El parámetro `validateNote` de la parte 4b, que podía sustituirlas, ya no existe. - **`StandardExtensions`** comprueba ya la nota con las reglas del §24.1, como el `Standard` de Go. El parámetro `validateNote` de la parte 4b, que podía sustituirlas, ya no existe.
- **Las diferencias con Go** son de forma: Go da `Opened.PayloadLength` también tras un fallo (los bytes escritos), y aquí `payloadLength` es solo el de una cápsula abierta; y una identity que no mide 32 bytes es un `ArgumentError` antes de empezar, donde Go recibe objetos `age.Identity`. - **Las diferencias con Go** son de forma: Go da `Opened.PayloadLength` también tras un fallo (los bytes escritos), y aquí `payloadLength` es solo el de una cápsula abierta; y una identity que no mide 32 bytes es un `ArgumentError` antes de empezar, donde Go recibe objetos `age.Identity`.
- **Un fallo de dart2js** de Dart 3.13, ajeno a la librería, que conviene saber en la web: si un objeto llega al campo de otro a través de `c ? null : objeto`, el compilador puede perder las escrituras que reciba allí y leer después sus campos con el valor inicial. Le pasó a `tool/open_bench.dart` con un sink que cuenta bytes, y se reproduce sin la librería. Para pasar el sink o la salida a `OpenOptions`, mejor sin ese condicional. - **Un fallo de dart2js** de Dart 3.13, ajeno a la librería, que conviene saber en la web: si un objeto llega al campo de otro a través de `c ? null : objeto`, el compilador puede perder las escrituras que reciba allí y leer después sus campos con el valor inicial. Le pasó a `tool/open_bench.dart` con un sink que cuenta bytes, y se reproduce sin la librería. Para pasar el sink o la salida a `OpenOptions`, mejor sin ese condicional.
La parte 5b de la etapa 5 porta el área de seguridad del formato 3 de `datekeys-go` en `c531e93`, el borrador v0.12, salvo lo que necesita el lector de CMS de las partes 5a y 5c. El API sigue al de Go:
| Módulo | Contenido | En Go |
|---|---|---|
| `lib/src/author.dart` | Lo que firma un autor y sella un sello (§29.8, §29.11): `payloadCommit`, `controlCommit` sobre `CONTROL_SIG` en cada formato, `headDigest`, `signersDigest`, `authorMessage`, sus 99 bytes y su prefijo, `authorCode`, `sigPart` y `sealSubject` | `signature.go` |
| `lib/src/security.dart` | `SECURITY_CBOR` (§29.3) con sus esquemas y sus límites, sus codificadores y sus lectores (`decodeSecurity`, `decodeAuthorSignature`, `decodeSeal`); `evaluateSecurity`, con la firma de `alg` 1; `SecurityContext`, `securityContext` y `evaluateSecurityInput`, el evaluador de la apertura; `holderText`, el nombre de un certificado del §29.7; y `CmsEvaluator`, la frontera con el lector de CMS | `format3.go`, `signature.go`, `newSecurityContext` de `open3.go`, `holderText` de `signature2.go` |
| `lib/src/verdicts.dart` | Los textos de los veredictos (`Verdict.text`), sus líneas (`Verdicts.lines`), el sello más temprano (`Verdicts.sealedAt`), `Detail`, `SignerLine` y `SignerResult` | `Verdict.Text`, `Verdicts.Lines`, `SealedAt`, `Detail` y `SignerLine` de `format3.go` |
Notas de la parte 5b:
- **El área nunca decide la apertura** (§29.3). `evaluateSecurity` no lanza: X para un mapa exterior que falla su capa 2 o 3, la versión 2 incluida; y para la firma y el sello por separado, la primera fila de la tabla del §29.7 que se cumple. Un fallo dentro de una parte, sea cual sea, es de esa parte, F1 para la firma y S2 para el sello, como Go recupera un panic. Sin contexto lee como un lector de la v0.10: toda firma es F1 y un sello de `seal_type` 2, S1.
- **`alg` 1** se verifica con `verifyStrict`, y la clave se busca entre las guardadas por su cadena `dkauthor1…`, exacta, como en Go: una guardada en mayúsculas no coincide. Las claves de autor y su fichero son de la etapa 7.
- **La frontera con la parte 5c es `CmsEvaluator`:**
- `evaluateSignature(signers, value, hasSeal, context)` da null, que es F1, o F2, F5 o F6 con el `Detail` de los firmantes, como `evaluateCMS` de Go;
- `evaluateSeal(token, signature, context)` da de S1 a S5, y con S4 y S5 la autoridad y t, como `evaluateSeal` de Go.
`evaluateSecurity` lo recibe en `cms`. Sin él, la firma de `alg` 2 y el sello de `seal_type` 2 en un contexto quedan en null, sin evaluar, y la otra parte se evalúa igual: `Verdicts.evaluated` es falso y las líneas son las de la otra parte. Lo que lance el lector, o un veredicto fuera de su rango, es F1 o S2. La 5c lo implementará en `securitycms.dart` y lo pondrá en `evaluateSecurityInput`; `holderText` ya está aquí para ella.
- **Las líneas** son las de Go, byte a byte: los nombres de un certificado entre « y », la autoridad de cada sello en las de F6 con su aviso, los resultados en español y t en RFC 3339 con la fracción del sello. Partir cada línea en filas con ` ↳ ` (§29.7) es de la CLI de Go (`cmd/datekeys/present.go`), no del paquete `capsule`: no se porta, y lo hará la app en una salida de texto.
- **El contexto de la apertura** es `newSecurityContext` con el `head_digest`: un control cuyo `CONTROL_SIG` no se puede codificar deja `control_commit` a cero, como en Go, y la firma no verifica.
- **`authorCode`** toma los bytes del mensaje como Go toma los de un string: un byte que no es UTF-8 se lee como U+FFFD.
- **Lo que se exporta.** `lib/datekeys.dart` exporta `author.dart` y `security.dart` enteros, como el paquete `capsule` de Go; `datekeys-ts` los deja internos.
Los enteros son exactos en la VM y en la web. El `int` de Dart tiene 64 bits con signo en la VM y en la web es un double, exacto hasta 2^53. Por eso la librería no usa un `int` por encima de 2^53-1, ni desplazamientos u operaciones de bits de más de 31 bits: Los enteros son exactos en la VM y en la web. El `int` de Dart tiene 64 bits con signo en la VM y en la web es un double, exacto hasta 2^53. Por eso la librería no usa un `int` por encima de 2^53-1, ni desplazamientos u operaciones de bits de más de 31 bits:
- un entero de CBOR es un `int` hasta 2^53-1 y un `BigInt` por encima, como el `number | bigint` de `datekeys-ts`; - un entero de CBOR es un `int` hasta 2^53-1 y un `BigInt` por encima, como el `number | bigint` de `datekeys-ts`;
- `CborDecoder.uint` devuelve un `int`, porque todos los esquemas acotan sus enteros en 2^53-1, y `uint64` devuelve un `BigInt`; - `CborDecoder.uint` devuelve un `int`, porque todos los esquemas acotan sus enteros en 2^53-1, y `uint64` devuelve un `BigInt`;
@ -155,7 +177,7 @@ Las etapas siguientes traen el resto del protocolo en este orden:
| Etapa | Contenido | | Etapa | Contenido |
|---|---| |---|---|
| 5 | Firma y sello, con los textos de los veredictos, en el `SecurityEvaluator` de la apertura | | 5 | El lector de CMS, en la parte 5a, y en la 5c la firma de `alg` 2 y el sello de `seal_type` 2 sobre él |
| 6 | Escritor | | 6 | Escritor |
| 7 | Localizador y claves de autor | | 7 | Localizador y claves de autor |
@ -275,7 +297,7 @@ Una apertura pequeña es casi toda los pasos 10 y 11, la verificación del relea
| Librería | `version` de `lib/src/version.dart` y de `pubspec.yaml`, que una prueba mantiene iguales | `0.1.0-dev` | | Librería | `version` de `lib/src/version.dart` y de `pubspec.yaml`, que una prueba mantiene iguales | `0.1.0-dev` |
| Especificación | `specVersion` de `lib/src/version.dart`: la que nombra el campo `spec` de cada fichero de `testdata/` | `0.11` | | Especificación | `specVersion` de `lib/src/version.dart`: la que nombra el campo `spec` de cada fichero de `testdata/` | `0.11` |
La rama sigue la versión de la especificación: `v0.11`, hasta que `datekeys-go` cierre la v0.12. La etapa 5 se sincronizará ya con la v0.12. La rama sigue la versión de la especificación: `v0.11`, hasta que `datekeys-go` cierre la v0.12. Desde la etapa 5, `testdata/` es ya el de la rama `v0.12`.
## Dependencias ## Dependencias
@ -304,10 +326,10 @@ tool/check.sh
## Datos de prueba ## Datos de prueba
`testdata/` es una copia de `datekeys-go/testdata` en un commit fijo. `testdata/SOURCE.json` registra el commit y el SHA-256 de cada fichero, igual que en `datekeys-ts`. La copia actual es la del tag `spec-v0.11` (`ae33434`). `testdata/` es una copia de `datekeys-go/testdata` en un commit fijo. `testdata/SOURCE.json` registra el commit y el SHA-256 de cada fichero, igual que en `datekeys-ts`. La copia actual es la de la rama `v0.12` de `datekeys-go` en `c531e93`, cuyo `testdata/` es el de `601e6d2`, el que tiene `datekeys-ts`: 133 ficheros, con los veredictos y las líneas del borrador v0.12. Cada fichero dice aún `"spec": "0.11"`, como el `SpecVersion` de Go, hasta que el autor apruebe el borrador.
```bash ```bash
dart run tool/sync_testdata.dart sync --commit spec-v0.11 dart run tool/sync_testdata.dart sync --commit c531e93
``` ```
```bash ```bash
@ -318,7 +340,7 @@ dart run tool/sync_testdata.dart check --against ../datekeys-go
- Los ficheros de `testdata/` no se editan ni se generan aquí. - Los ficheros de `testdata/` no se editan ni se generan aquí.
- En cada `dart test`, `test/testdata_test.dart` comprueba la copia, y que cada fichero nombre `specVersion`. - En cada `dart test`, `test/testdata_test.dart` comprueba la copia, y que cada fichero nombre `specVersion`.
`test/vectors/` tiene los vectores de las primitivas, de `age`, de BLS12-381, de tlock, de las reglas de rutas y textos, de la llave de palabras, de los formatos y de la apertura. Los escribe Go, con las librerías de la caché de módulos que usa `datekeys-go` (`x/crypto`, `filippo.io/age`, `kilic/bls12-381`, `drand/kyber`, `kyber-bls12381` y `tlock`) y sus paquetes, como `provider`, `agewrap`, `capsule`, `internal/pathrule`, `internal/testkit` y `wordkey`; ningún valor esperado se escribe a mano. Los generadores van en `tool/`, con `//go:build ignore`, y se ejecutan en el contexto del módulo de `datekeys-go`, sin cambiar nada en él; los de las rutas y de la apertura, en una exportación suya. Los de BLS12-381 y tlock dan la misma salida con el tag `spec-v0.11` y con el borrador v0.12, y leen ficheros congelados de `datekeys-ts`, cuya carpeta en esta máquina se llama todavía `App`: `test/vectors/` tiene los vectores de las primitivas, de `age`, de BLS12-381, de tlock, de las reglas de rutas y textos, de la llave de palabras, de los formatos, de la apertura y del área de seguridad. Los escribe Go, con las librerías de la caché de módulos que usa `datekeys-go` (`x/crypto`, `filippo.io/age`, `kilic/bls12-381`, `drand/kyber`, `kyber-bls12381` y `tlock`) y sus paquetes, como `provider`, `agewrap`, `capsule`, `internal/pathrule`, `internal/testkit` y `wordkey`; ningún valor esperado se escribe a mano. Los generadores van en `tool/`, con `//go:build ignore`, y se ejecutan en el contexto del módulo de `datekeys-go`, sin cambiar nada en él; los de las rutas y de la apertura, en una exportación suya. Los de BLS12-381 y tlock dan la misma salida con el tag `spec-v0.11` y con el borrador v0.12, y leen ficheros congelados de `datekeys-ts`, cuya carpeta en esta máquina se llama todavía `App`:
```bash ```bash
cd ../datekeys-go && go run ../datekeys-dart/tool/gen_primitive_vectors.go -out ../datekeys-dart/test/vectors cd ../datekeys-go && go run ../datekeys-dart/tool/gen_primitive_vectors.go -out ../datekeys-dart/test/vectors
@ -356,6 +378,12 @@ cd ../datekeys-go && go run ../datekeys-dart/tool/wordkey_go_vectors.go -out ../
cd ../datekeys-go && go run ../datekeys-dart/tool/mutation_go_texts.go ../datekeys-dart/testdata > ../datekeys-dart/test/vectors/mutation_texts.json cd ../datekeys-go && go run ../datekeys-dart/tool/mutation_go_texts.go ../datekeys-dart/testdata > ../datekeys-dart/test/vectors/mutation_texts.json
``` ```
```bash
cd ../datekeys-go && go run ../datekeys-dart/tool/security_go_vectors.go -testdata ../datekeys-dart/testdata -out ../datekeys-dart/test/vectors
```
`holderText` no se exporta en el paquete `capsule`: `tool/security_go_vectors.go` llega a él con `go:linkname`, que Go permite con un paquete de fuera de la biblioteca estándar.
`internal/pathrule` solo se puede importar desde el árbol de `datekeys-go`, así que el generador de las rutas corre en una exportación suya, hecha con `git archive`, sin tocar el repositorio: `internal/pathrule` solo se puede importar desde el árbol de `datekeys-go`, así que el generador de las rutas corre en una exportación suya, hecha con `git archive`, sin tocar el repositorio:
```bash ```bash
@ -395,18 +423,20 @@ rm -rf "$tmp"
| `pathrule_vectors.g.dart` | El mismo JSON como constante de Dart | | `pathrule_vectors.g.dart` | El mismo JSON como constante de Dart |
| `wordkey_vectors.json` | La llave de palabras de `wordkey`: 400 textos con sus palabras, 515 listas de palabras con el resultado de `Check`, y cuatro llaves con su contraseña P y su sal S, el PBKDF2 de 1000 iteraciones para Node.js y el recipient; la primera es el vector del §38.1 | | `wordkey_vectors.json` | La llave de palabras de `wordkey`: 400 textos con sus palabras, 515 listas de palabras con el resultado de `Check`, y cuatro llaves con su contraseña P y su sal S, el PBKDF2 de 1000 iteraciones para Node.js y el recipient; la primera es el vector del §38.1 |
| `wordkey_vectors.g.dart` | El mismo JSON como constante de Dart | | `wordkey_vectors.g.dart` | El mismo JSON como constante de Dart |
| `mutation_texts.json` | De `tool/mutation_go_texts.go`, port de `scripts/mutation-go-texts.go` de `datekeys-ts` sobre el `testdata/` de este repositorio: el texto del error de `capsule.Open` en cada caso del corpus de mutaciones, `ok` si se abre, y sus comprobaciones con el detalle de cada paso. Si Go y el corpus discreparan en el código o el paso de un caso, lo diría con `go_error` y `go_step`: en ninguno lo hacen, ni con Go en `c531e93` ni en el tag `spec-v0.11`, que dan el mismo fichero | | `mutation_texts.json` | De `tool/mutation_go_texts.go`, port de `scripts/mutation-go-texts.go` de `datekeys-ts` sobre el `testdata/` de este repositorio: el texto del error de `capsule.Open` en cada caso del corpus de mutaciones, `ok` si se abre, y sus comprobaciones con el detalle de cada paso. Si Go y el corpus discreparan en el código o el paso de un caso, lo diría con `go_error` y `go_step`: en ninguno de los 218 casos del corpus del borrador v0.12 lo hacen con Go en `c531e93` |
| `open_cases.json` | `capsule.Open` sobre cada fixture con cada una de sus credenciales, y sobre fixtures editados o con otras opciones en cada paso que el corpus no alcanza: la trama, los campos, las extensiones y los vínculos de una `.dkk` en el paso 9.a, el reloj y los fallos de la fuente del release, las cabeceras `age` de los pasos 11 y 17, un stanza X25519 mal formado en `INNER_ACCESS_AGE`, `CONTROL_CBOR` sellado otra vez, `BODY` del formato 3 sellado otra vez, los sinks y la salida que fallan, el rechazo de `Accept` y las extensiones inutilizables de cada objeto. Cada caso tiene el resultado, el texto, el paso, las comprobaciones con su detalle, las peticiones del release, el estado del sink y el contenido o los ficheros | | `open_cases.json` | `capsule.Open` sobre cada fixture con cada una de sus credenciales, y sobre fixtures editados o con otras opciones en cada paso que el corpus no alcanza: la trama, los campos, las extensiones y los vínculos de una `.dkk` en el paso 9.a, el reloj y los fallos de la fuente del release, las cabeceras `age` de los pasos 11 y 17, un stanza X25519 mal formado en `INNER_ACCESS_AGE`, `CONTROL_CBOR` sellado otra vez, `BODY` del formato 3 sellado otra vez, los sinks y la salida que fallan, el rechazo de `Accept` y las extensiones inutilizables de cada objeto. Cada caso tiene el resultado, el texto, el paso, las comprobaciones con su detalle, las peticiones del release, el estado del sink y el contenido o los ficheros, y los del formato 3 que se abren, sus veredictos con sus líneas, también con la clave de autor guardada |
| `open_heads.json` | `capsule.DecodeHead` de heads de una semilla fija, válidos y rotos en cada capa del §69.1, sin registro y con uno, y `capsule.EncodeHead` | | `open_heads.json` | `capsule.DecodeHead` de heads de una semilla fija, válidos y rotos en cada capa del §69.1, sin registro y con uno, y `capsule.EncodeHead` |
| `open_notes.json` | `extension.CheckNote` sobre textos y bytes, `extension.Note` y `Header.UnusableNote`, y `extension.Standard` con una nota | | `open_notes.json` | `extension.CheckNote` sobre textos y bytes, `extension.Note` y `Header.UnusableNote`, y `extension.Standard` con una nota |
| `open_inspect.json` | El texto del error de `capsule.Inspect` en cada mutación de `inspect_differential.json`, y la salida exacta de `datekeys inspect -json` con notas públicas y extensiones inutilizables | | `open_inspect.json` | El texto del error de `capsule.Inspect` en cada mutación de `inspect_differential.json`, y la salida exacta de `datekeys inspect -json` con notas públicas y extensiones inutilizables |
| `open_vectors.g.dart` | Siete fixtures pequeños, lo que sus registros dicen de ellos y una parte de los cuatro ficheros `open_*.json`, como constantes de Dart | | `open_vectors.g.dart` | Siete fixtures pequeños, lo que sus registros dicen de ellos y una parte de los cuatro ficheros `open_*.json`, como constantes de Dart |
| `security_vectors.json` | El área de seguridad del paquete `capsule`: los compromisos, también `ControlCommit` del control de cada fixture en cada formato; los codificadores; 1730 evaluaciones con `EvaluateSecurityIn` en 23 contextos y sin contexto, del mapa exterior, de `author-signature` y de `seal` rotos de todas las formas de sus esquemas y en sus límites, de firmas de `alg` 1 válidas e inválidas, guardadas o no, con los casos de «Taming the many EdDSAs» hechos sobre `AUTHOR_MESSAGE`, y de mutaciones de una semilla fija, con los veredictos, las líneas, `alg` y `seal_type` leídos y las partes que solo evalúa el lector de CMS; las líneas y el sello más temprano de veredictos con cada detalle; y `holderText` |
| `security_vectors.g.dart` | Todo `security_vectors.json` salvo siete de cada ocho evaluaciones, como constante de Dart |
- Los fixtures que leen los generadores son los de `testdata/` de este repositorio, la copia sincronizada. - Los fixtures que leen los generadores son los de `testdata/` de este repositorio, la copia sincronizada.
- `primitives.json`, los cuatro ficheros de BLS12-381 y tlock, `pathrule_vectors.json`, `wordkey_vectors.json` y los de los formatos salen iguales en cada ejecución. Lo aleatorio de tlock, los ciphertexts de kyber con su sigma y los de `datekeys-ts`, se lee de los ficheros congelados de `datekeys-ts` en `289fe71`, y Go los descifra otra vez. `age`, en cambio, saca sus claves y nonces de `crypto/rand`, así que `age.json` y `age_fixtures.json` cambian en cada ejecución; las pruebas leen lo que esté en el repositorio. - `primitives.json`, los cuatro ficheros de BLS12-381 y tlock, `pathrule_vectors.json`, `wordkey_vectors.json`, los de los formatos y `security_vectors.json` salen iguales en cada ejecución. Lo aleatorio de tlock, los ciphertexts de kyber con su sigma y los de `datekeys-ts`, se lee de los ficheros congelados de `datekeys-ts` en `289fe71`, y Go los descifra otra vez. `age`, en cambio, saca sus claves y nonces de `crypto/rand`, así que `age.json` y `age_fixtures.json` cambian en cada ejecución; las pruebas leen lo que esté en el repositorio. `age.json` no lee `testdata/` y es el congelado de la etapa 2; `age_fixtures.json` se escribió otra vez con el `testdata/` de la v0.12, y fuera de los dos fixtures nuevos y del de `seal_type` 4294967295 sale igual.
- Un fichero `age` de más de un chunk se guarda como su cabecera, su nonce y su file key: la prueba cifra otra vez el texto documentado y comprueba el SHA-256 del fichero entero antes de leerlo. Las cabeceras de megabytes se escriben como partes que se repiten. - Un fichero `age` de más de un chunk se guarda como su cabecera, su nonce y su file key: la prueba cifra otra vez el texto documentado y comprueba el SHA-256 del fichero entero antes de leerlo. Las cabeceras de megabytes se escriben como partes que se repiten.
- Los casos de `open_cases.json` que editan un fixture lo sellan otra vez como el `testkit` de la referencia, con las file keys y los nonces del fixture, así que salen iguales en cada ejecución, y se guardan como ediciones del fixture. - Los casos de `open_cases.json` que editan un fixture lo sellan otra vez como el `testkit` de la referencia, con las file keys y los nonces del fixture, así que salen iguales en cada ejecución, y se guardan como ediciones del fixture.
- Las pruebas que corren en Node.js no leen ficheros. Los valores de Go que usan están en `primitives.g.dart`, `pathrule_vectors.g.dart`, `wordkey_vectors.g.dart`, `formats_vectors.g.dart`, `open_vectors.g.dart`, `test/bls12381_constants.dart` y `test/ibe_constants.dart`. Unas pruebas en la VM comparan con los JSON los de las rutas, la llave de palabras, los formatos, la apertura, BLS12-381 y el IBE. - Las pruebas que corren en Node.js no leen ficheros. Los valores de Go que usan están en `primitives.g.dart`, `pathrule_vectors.g.dart`, `wordkey_vectors.g.dart`, `formats_vectors.g.dart`, `open_vectors.g.dart`, `security_vectors.g.dart`, `test/bls12381_constants.dart` y `test/ibe_constants.dart`. Unas pruebas en la VM comparan con los JSON los de las rutas, la llave de palabras, los formatos, la apertura, el área de seguridad, BLS12-381 y el IBE.
## Licencia ## Licencia

@ -2,19 +2,23 @@
/// DateKeys Access Key (`.dkk`), as `datekeys-go` and `datekeys-ts` implement /// DateKeys Access Key (`.dkk`), as `datekeys-go` and `datekeys-ts` implement
/// them, checked against the same test data. /// them, checked against the same test data.
/// ///
/// Stages 0 to 4 of docs/PLAN_dart.md: the package and its test data, the /// Stages 0 to 4 of docs/PLAN_dart.md and part 5b of stage 5: the package and
/// normative errors of spec §69, byte helpers and the CBOR profile of spec /// its test data, the normative errors of spec §69, byte helpers and the CBOR
/// §58, the primitives and the reading of age files, then BLS12-381 and /// profile of spec §58, the primitives and the reading of age files, then
/// tlock: the check of a compressed point and the verification of releases, /// BLS12-381 and tlock: the check of a compressed point and the verification
/// with the sources that deliver them. Then the key of words of spec §38.1, /// of releases, with the sources that deliver them. Then the key of words of
/// and the formats: the frames of the .dkc and the .dkk, PUBLIC_HEADER, /// spec §38.1, and the formats: the frames of the .dkc and the .dkk,
/// CONTROL_CBOR of the three formats, the .dkk, the extensions with their /// PUBLIC_HEADER, CONTROL_CBOR of the three formats, the .dkk, the
/// registries, the Provider Profile with the pinned Quicknet, the DateKey /// extensions with their registries, the Provider Profile with the pinned
/// with its rounds and times, the padding, the head of format 3 and the /// Quicknet, the DateKey with its rounds and times, the padding, the head of
/// public note. And the reading of a capsule: its inspection, steps 1 to 8 /// format 3 and the public note. And the reading of a capsule: its
/// of spec §63, and its opening, steps 9 to 18, in memory or from a source /// inspection, steps 1 to 8 of spec §63, and its opening, steps 9 to 18, in
/// read by ranges, to a sink of bytes or of files. The signature and the /// memory or from a source read by ranges, to a sink of bytes or of files.
/// seal arrive with stage 5, through the evaluator of the opening. /// And the security area of format 3: what an author signs and a seal seals,
/// SECURITY_CBOR, the signature of alg 1 and the verdicts with their texts
/// and lines, which the opening evaluates as Go; the signature of alg 2 and
/// the seal of seal_type 2 wait for the reader of CMS of stage 5c, behind
/// CmsEvaluator.
/// ///
/// DER, the primitives, age, agewrap, the curve arithmetic, the IBE of tlock /// DER, the primitives, age, agewrap, the curve arithmetic, the IBE of tlock
/// and its stanza, the rules of paths and texts on the Unicode tables, the /// and its stanza, the rules of paths and texts on the Unicode tables, the
@ -23,6 +27,7 @@
library; library;
export 'src/accesskey.dart'; export 'src/accesskey.dart';
export 'src/author.dart';
export 'src/bls12381_curve.dart' export 'src/bls12381_curve.dart'
show BlsGroup, PointVerdict, checkCompressedPoint; show BlsGroup, PointVerdict, checkCompressedPoint;
export 'src/bytes.dart' export 'src/bytes.dart'
@ -59,6 +64,7 @@ export 'src/release.dart'
quicknetScheme, quicknetScheme,
suppliedRelease, suppliedRelease,
verifyRelease; verifyRelease;
export 'src/security.dart';
export 'src/sink.dart'; export 'src/sink.dart';
export 'src/source.dart' show ByteSource, BytesSource; export 'src/source.dart' show ByteSource, BytesSource;
export 'src/verdicts.dart'; export 'src/verdicts.dart';

@ -10,7 +10,6 @@ import 'dart:typed_data';
import 'package:datekeys/datekeys.dart'; import 'package:datekeys/datekeys.dart';
import 'package:datekeys/src/age.dart' show X25519Identity; import 'package:datekeys/src/age.dart' show X25519Identity;
import 'package:datekeys/src/security.dart' show evaluateSecurityInput;
import 'package:datekeys/src/sha256.dart' show sha256; import 'package:datekeys/src/sha256.dart' show sha256;
import 'open_vectors_support.dart'; import 'open_vectors_support.dart';

@ -9,7 +9,6 @@ import 'dart:convert';
import 'dart:typed_data'; import 'dart:typed_data';
import 'package:datekeys/datekeys.dart'; import 'package:datekeys/datekeys.dart';
import 'package:datekeys/src/security.dart' show evaluateSecurityInput;
import 'package:test/test.dart'; import 'package:test/test.dart';
import 'open_support.dart'; import 'open_support.dart';

@ -10,10 +10,8 @@ library;
import 'dart:typed_data'; import 'dart:typed_data';
import 'package:datekeys/datekeys.dart'; import 'package:datekeys/datekeys.dart';
import 'package:datekeys/src/author.dart';
import 'package:datekeys/src/bech32.dart' show bech32Encode; import 'package:datekeys/src/bech32.dart' show bech32Encode;
import 'package:datekeys/src/bytes.dart' show utf8Bytes; import 'package:datekeys/src/bytes.dart' show utf8Bytes;
import 'package:datekeys/src/security.dart';
import 'package:datekeys/src/sha256.dart' show sha256; import 'package:datekeys/src/sha256.dart' show sha256;
import 'open_vectors_support.dart'; import 'open_vectors_support.dart';

@ -11,8 +11,6 @@ import 'dart:math';
import 'dart:typed_data'; import 'dart:typed_data';
import 'package:datekeys/datekeys.dart'; import 'package:datekeys/datekeys.dart';
import 'package:datekeys/src/author.dart';
import 'package:datekeys/src/security.dart';
import 'package:test/test.dart'; import 'package:test/test.dart';
import 'open_vectors_support.dart'; import 'open_vectors_support.dart';

@ -11,10 +11,8 @@ import 'dart:convert';
import 'dart:io'; import 'dart:io';
import 'package:datekeys/datekeys.dart'; import 'package:datekeys/datekeys.dart';
import 'package:datekeys/src/author.dart';
import 'package:datekeys/src/bech32.dart' show bech32Encode; import 'package:datekeys/src/bech32.dart' show bech32Encode;
import 'package:datekeys/src/curve25519.dart' show verifyStrict; import 'package:datekeys/src/curve25519.dart' show verifyStrict;
import 'package:datekeys/src/security.dart';
import 'package:test/test.dart'; import 'package:test/test.dart';
import 'open_vectors_support.dart'; import 'open_vectors_support.dart';

Loading…
Cancel
Save

Powered by TurnKey Linux.