lib/datekeys.dart exports the verification of releases (PinnedProfile,
Release, ReleaseSource, verifyRelease, suppliedRelease, fetchRelease and
quicknetScheme) and checkCompressedPoint with BlsGroup and PointVerdict, as
datekeys-ts does; the curve arithmetic, the IBE and the tlock stanza stay
internal, and encryption waits for the writer of stage 6. The README
describes the modules, the deliberate differences with Go, the caveat
that BigInt is not constant time, the timings on the VM and on Node.js,
and the generators of test/vectors/.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ -4,6 +4,28 @@ 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
### Etapa 3: BLS12-381 y tlock (05-10-2026)
- **BLS12-381, de código propio,** como lo calcula `kilic/bls12-381` v0.1.0 para `drand/kyber-bls12381` v0.3.4:
- la capa del cuerpo, `Fp`, un extension type sobre `BigInt`, con `FpWide` para las sumas de productos sin reducir; la única que toca la representación, para que unos limbs fijos la puedan sustituir sola;
- Fp2, Fp6 y Fp12 con las fórmulas de kilic, reduciendo cada coeficiente una vez, el Frobenius con sus coeficientes y el cuadrado ciclotómico;
- G1 y G2, su codificación comprimida y los veredictos de `FromCompressed` (§12.2), con `checkCompressedPoint`, que `lib/datekeys.dart` exporta como `datekeys-ts`. El subgrupo de G2 se comprueba con ψ(P) = [x]·P;
- el emparejamiento ate óptimo con las rectas y la exponenciación final de kilic: GT es su valor, serializado c1 antes que c0 en cada nivel;
- el hash a G1 del RFC 9380 con el DST de Quicknet y de tlock, sumando las salidas del mapa en E′ como kilic.
- **El IBE de tlock** (`lib/src/ibe.dart`), `DecryptCCAonG2` y `EncryptCCAonG2` de `drand/kyber` v1.3.2 para Quicknet, como `ibe.ts`: H2 sobre GT en el orden de kilic, H3 con su rechazo de candidatos, H4, la identidad de la ronda y las puertas de la firma y de U, con razones y textos fijos que no llevan ningún valor del cálculo. El cifrado admite un sigma dado, para reproducir byte a byte los vectores de Go; es interno hasta el escritor, la etapa 6.
- **Releases** (`lib/src/release.dart`): `verifyRelease` es `provider.Verify`, en su orden y con sus textos, solo para el scheme de Quicknet, como `release.ts`; `suppliedRelease`; y `fetchRelease`, la regla del paso 9: lo que lance una fuente es `ERR_RELEASE_UNAVAILABLE`. Los exporta `lib/datekeys.dart`, con `PinnedProfile`, lo que lee del perfil, que llega con la etapa 4.
- **El stanza tlock** (`lib/src/tlock.dart`): `unwrapTlockStanza` hace lo que `NewTimeIdentity` y su `Unwrap` con los argumentos y el cuerpo del stanza, y `wrapTlockStanza` lo que `NewTimeRecipient`, con los códigos y los textos de `agewrap`. Es interno: lo usará la apertura de la etapa 4.
- **Diferencias con Go, a propósito,** las de `datekeys-ts`: otro scheme que el de Quicknet da `ERR_UNKNOWN_PROFILE` con un texto propio, y el punto en el infinito nunca es una firma válida, mientras que Go la acepta si la clave pública también es el punto en el infinito, una clave que ningún perfil pinneado tiene.
- **`BigInt` no es de tiempo constante.** Verificar y descifrar solo manejan datos públicos; al cifrar, sigma y r son secretos. El README lo explica.
- **Vectores de Go** en `test/vectors/`, que escriben cuatro programas de `tool/` con las librerías de la caché de módulos, en el contexto del módulo de `datekeys-go` y sin cambiar nada en él:
- `bls12381_vectors.json`: las 157 codificaciones límite de `datekeys-ts` con el veredicto de Go, y decodificaciones, sumas, múltiplos, emparejamientos, hashes a G1, el mapa de un elemento y firmas BLS con una semilla fija;
- `ibe_vectors.json`, port del generador de `datekeys-ts` sobre los fixtures de `testdata/`: GT y H2, H3, H4, identidades de rondas, el stanza de cada fixture con su file key, los ciphertexts de kyber y los veredictos de `DecryptCCAonG2`;
- `tlock_vectors.json`, port también: el cifrado de kyber con sigma fijo y los ciphertexts que escribió `datekeys-ts` y abre Go;
- `release_vectors.json`: los veredictos, códigos y textos de `provider.Verify`, `NewTimeIdentity` con `Unwrap` y `NewTimeRecipient`.
- **Pruebas.** 71 nuevas en la VM y 30 en Node.js. La etapa se hizo en paralelo con la 2, en otra rama, desde la etapa 1; con las dos integradas hay 367 pruebas en la VM, más una aplazada, y 113 en Node.js. Las que leen los vectores llevan `@TestOn('vm')`; en Node.js corren las propiedades de la aritmética y unos pocos vectores de Go copiados en Dart, que una prueba en la VM compara con los JSON. Un emparejamiento tarda allí un cuarto de segundo, así que los bucles sacan menos casos.
- **Fallos inyectados**, uno a uno y revertidos: 25, en la torre, las curvas, el emparejamiento, el hash, el IBE, los releases y el stanza. Las pruebas los detectan todos, en la VM y en Node.js.
- **`tool/bls12381_bench.dart`** mide BLS12-381 y tlock en la VM y compilado a JavaScript: en la VM, un emparejamiento tarda unos 11 ms, la verificación de la firma de una ronda 16 ms y el descifrado de un stanza 20 ms. Las cifras, en el README.
### Etapa 2: primitivas y `age` (05-10-2026)
- **Primitivas, de código propio.** Son internas: `lib/datekeys.dart` no las exporta.
@ -6,10 +6,13 @@ Es la tercera implementación de la especificación, después de la de referenci
## Estado
Están hechas las etapas 0, 1 y 2 del plan (`docs/PLAN_dart.md` del espacio de trabajo):
Están hechas las etapas 0 a 3 del plan (`docs/PLAN_dart.md` del espacio de trabajo):
- 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 2, las primitivas y la lectura de `age`.
- la etapa 2, las primitivas y la lectura de `age`;
- la etapa 3, BLS12-381 y tlock: el emparejamiento, el hash a G1, el IBE de drand y la verificación de la firma de la ronda.
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.
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:
@ -36,22 +39,47 @@ La etapa 2 trae las primitivas, todas de código propio salvo SHA-512, y la lect
Notas de la etapa 2:
- **La identity de scrypt** rechaza por defecto un factor de trabajo por encima de 16, el de los ficheros de clave de autor (§29.12), como `SetMaxWorkFactor(16)` en el `authorkey` de Go. El de `age` es 22: 4 GiB de memoria, que un fichero hostil podría pedir a un móvil. `ScryptIdentity(maxWorkFactor: …)` lo cambia.
- **El STREAM** se descifra según llega el texto cifrado (`AgePayloadDecryptor`), como el lector de Go: entrega el texto de cada chunk en cuanto se autentica, y un fallo que revela un byte posterior llega en la llamada siguiente.
- **La identity de `OUTER_TIME_AGE`** necesita tlock y llega con la etapa 3; la del perfil, con la etapa 4. Por eso `checkTimeStanzas` recibe la ronda, el chain hash y el id del perfil.
- **La identity de `OUTER_TIME_AGE`** se compone en la etapa 4, con el perfil: `checkTimeStanzas` de esta etapa, que recibe la ronda, el chain hash y el id del perfil, y `checkTlockProfile` y `unwrapTlockStanza` de la etapa 3.
La etapa 3 porta BLS12-381 de `kilic/bls12-381` v0.1.0, sobre el que calcula `drand/kyber-bls12381` v0.3.4 para drand y tlock; el IBE de `encrypt/ibe` de `drand/kyber` v1.3.2, el de `tlock` v1.2.0 con Quicknet; y `provider.Verify` y el stanza tlock de `agewrap` de `datekeys-go`, con las mismas comprobaciones en el mismo orden y los mismos textos de error. Como `datekeys-ts`, verifica solo el scheme de Quicknet, `bls-unchained-g1-rfc9380`. Todo es código propio: de `package:crypto` usa solo SHA-256.
| Módulo | Contenido | En Go |
|---|---|---|
| `lib/src/bls12381_fp.dart` | El cuerpo Fp sobre `BigInt` (`Fp`) y las sumas de productos sin reducir (`FpWide`): la única capa que toca la representación de un elemento | `fp.go` de kilic |
| `lib/src/bls12381_tower.dart` | Fp2, Fp6 y Fp12 con las fórmulas de kilic, cada coeficiente reducido una vez; el Frobenius y el cuadrado ciclotómico; GT serializado c1 antes que c0 en cada nivel | `fp2.go`, `fp6.go`, `fp12.go` de kilic |
| `lib/src/bls12381_curve.dart` | G1 y G2 en coordenadas jacobianas, su codificación comprimida y los veredictos de `FromCompressed` (§12.2): `checkCompressedPoint` | `g1.go`, `g2.go` de kilic |
| `lib/src/bls12381_pairing.dart` | El emparejamiento ate óptimo: el bucle de Miller con las rectas de kilic y su exponenciación final | `pairing.go` de kilic |
| `lib/src/bls12381_hash.dart` | `expand_message_xmd`, `hash_to_field`, el mapa SWU simplificado, la isogenia de grado 11 y el cofactor: el hash a G1 del RFC 9380 con el DST de Quicknet | `hash_to_field.go`, `swu.go`, `isogeny.go` de kilic |
| `lib/src/ibe.dart` | El IBE-CCA de tlock sobre G2 (§63 paso 11): H2, H3 con su rechazo de candidatos, H4, la identidad de la ronda, el descifrado y el cifrado, este con sigma inyectable | `encrypt/ibe` de kyber |
| `lib/src/release.dart` | `verifyRelease` (§17, §51, §63 paso 10), `Release`, `ReleaseSource`, `suppliedRelease` y `fetchRelease`, la regla del paso 9 | `provider` |
| `lib/src/tlock.dart` | El stanza tlock de `OUTER_TIME_AGE` (§32, §35, §63 paso 11): abrirlo, como `NewTimeIdentity` y su `Unwrap`, y escribirlo, como `NewTimeRecipient` | `agewrap` |
Notas de la etapa 3:
- **La capa del cuerpo.**`Fp` es un extension type sobre `BigInt`, sin envoltorio en ejecución, y `FpWide` una suma de productos sin reducir. La torre, las curvas, el emparejamiento y el hash solo usan sus operaciones: una implementación con limbs fijos, más rápida, cambiaría ese fichero y nada más.
- **Los veredictos de un punto** son los de `FromCompressed` de kilic: el flag de compresión a 1; el punto en el infinito solo como `0xc0` y ceros; coordenadas menores que p, sin reducir; un punto de la curva; y un punto del subgrupo de orden r. En G1 el subgrupo se comprueba con [r]·P = O; en G2, con ψ(P) = [x]·P (Scott, eprint 2021/1130, como noble), que las pruebas comparan con [r]·P = O en puntos fuera del subgrupo, también con torsión de cada orden pequeño del cofactor.
- **GT** es el valor del emparejamiento de kilic, con su exponenciación final, f^(3·(p⁴ − p² + 1)/r), y se serializa en su orden (§63, «Serialización de GT en H2»).
- **El hash a G1** sigue a kilic, que suma las dos salidas del mapa en E′ antes de la isogenia. kilic se aparta del RFC 9380 solo donde ningún hash llega: dos salidas iguales u opuestas, que suma con la fórmula de E. Este código las suma con la ley de grupo de E′, como el RFC.
- **Las diferencias con Go, a propósito,** son las de `datekeys-ts`: otro scheme que el de Quicknet da `ERR_UNKNOWN_PROFILE` con un texto propio, donde Go verificaría los otros schemes de drand; y el punto en el infinito nunca es una firma válida (§63 paso 10), mientras que Go la acepta si la clave pública también es el punto en el infinito, una clave que ningún perfil pinneado tiene (§12.1). Las pruebas fijan las dos.
- **El stanza tlock.**`unwrapTlockStanza` recibe los argumentos y el cuerpo del único stanza y hace lo que `NewTimeIdentity` y su `Unwrap` en Go: el perfil, los argumentos, otra vez el release y el cuerpo. El número y el tipo de los stanzas los comprueban las reglas de `agewrap` de la etapa 2, que necesitan la cabecera entera. Se guarda el último release verificado: el paso 11 vuelve a verificar el del paso 10, como en Go, sin otro emparejamiento.
- **La fuente de releases.** La librería no trae cliente HTTP: recibe una `ReleaseSource`, como `OpenOptions.Source` en Go. `fetchRelease` aplica la regla del paso 9: lo que lance la fuente es `ERR_RELEASE_UNAVAILABLE`, con su texto y ningún otro código.
- **Lo que se exporta.**`lib/datekeys.dart` exporta la verificación de releases y `checkCompressedPoint`, como `datekeys-ts`. El IBE y el stanza tlock son internos: los usará la apertura de la etapa 4. El cifrado no se exporta todavía: es del escritor, la etapa 6.
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`;
- `CborDecoder.uint` devuelve un `int`, porque todos los esquemas acotan sus enteros en 2^53-1, y `uint64` devuelve un `BigInt`;
- SHA-256, ChaCha20 y Salsa20 trabajan con palabras de 32 bits: suman de dos a cinco y enmascaran la suma, y en cada rotación enmascaran la mitad desplazada a la izquierda, así que la VM y la web dan los mismos 32 bits;
- Poly1305 guarda el acumulador y r en diez limbs de 13 bits: cada producto queda por debajo de 2^31 y cada suma por debajo de 2^35, y sus acarreos se toman con `~/`, no con un desplazamiento, que en la web truncaría a 32 bits;
- el cuerpo de curve25519 es el de TweetNaCl en su versión de JavaScript: dieciséis limbs de 16 bits en un `Float64List`, con sumas de productos por debajo de 2^44.
- el cuerpo de curve25519 es el de TweetNaCl en su versión de JavaScript: dieciséis limbs de 16 bits en un `Float64List`, con sumas de productos por debajo de 2^44;
- en BLS12-381 los elementos del cuerpo y los escalares son `BigInt`, y una ronda es un `int` hasta 2^53-1, cuyos 8 bytes se escriben como dos mitades de 32 bits.
**`BigInt` no es de tiempo constante.** La librería lo usa solo con datos públicos: la reducción de escalares módulo ℓ y las comprobaciones de `onCurve` en Ed25519, que solo verifica, y el factor de trabajo de un stanza scrypt. Los secretos (el escalar de X25519, las claves de HMAC, ChaCha20 y Poly1305) van en la aritmética de limbs, sin ramas ni índices que dependan de ellos; ni la VM ni un motor de JavaScript prometen tiempo constante, aun así.
**`BigInt` no es de tiempo constante.** En las primitivas se usa solo con datos públicos: la reducción de escalares módulo ℓ y las comprobaciones de `onCurve` en Ed25519, que solo verifica, y el factor de trabajo de un stanza scrypt. Los secretos de las primitivas (el escalar de X25519, las claves de HMAC, ChaCha20 y Poly1305) van en la aritmética de limbs, sin ramas ni índices que dependan de ellos; ni la VM ni un motor de JavaScript prometen tiempo constante, aun así.
BLS12-381, en cambio, hace con `BigInt` toda su aritmética. Verificar un release y descifrar un stanza tlock solo manejan datos públicos: la firma de la ronda lo es desde que drand la publica, y el stanza va en la cápsula. Cifrar no: sigma y r son secretos, y el tiempo del código depende de ellos. El escritor (etapa 6) cifrará el stanza tlock donde ese tiempo no se pueda observar, o con una capa del cuerpo de limbs fijos sin ramas que dependan de los datos.
Las etapas siguientes traen el resto del protocolo en este orden:
| Etapa | Contenido |
|---|---|
| 3 | BLS12-381 y tlock |
| 4 | Formatos, inspección (pasos 1 a 8) y apertura (pasos 9 a 18) |
| 5 | Firma y sello, con los textos de los veredictos |
| 6 | Escritor |
@ -59,7 +87,19 @@ Las etapas siguientes traen el resto del protocolo en este orden:
## Rendimiento
`dart run tool/bench.dart` mide las primitivas en la VM; compilado a JavaScript, `dart compile js -O2 -o bench.js tool/bench.dart && node bench.js`. Las cifras del 5 de octubre de 2026, en el PC de desarrollo (Windows 11, Dart 3.13, Node.js 24.9):
Las cifras del 5 de octubre de 2026 son del PC de desarrollo (Windows 11, Dart 3.13, Node.js 24.9). No hay cifras de un móvil de gama media: están por medir.
### Primitivas
`dart run tool/bench.dart` mide las primitivas en la VM. Compilado a JavaScript:
```bash
dart compile js -O2 -o bench.js tool/bench.dart
```
```bash
node bench.js
```
| Operación | VM | Node.js |
|---|---|---|
@ -71,7 +111,36 @@ Las etapas siguientes traen el resto del protocolo en este orden:
En la VM, el HMAC de `package:crypto`, que calcula otra vez los estados de la clave en cada llamada, tarda unos 3,5 s en las mismas 600 000 iteraciones.
La app llama a PBKDF2 y a scrypt en un `Isolate` (plan, «Rendimiento»). Las cifras en un móvil de gama media se miden en la etapa 3.
La app llama a PBKDF2 y a scrypt en un `Isolate` (plan, «Rendimiento»).
### BLS12-381 y tlock
`dart run tool/bls12381_bench.dart` mide BLS12-381 y tlock en la VM. Compilado a JavaScript:
Son medianas de 15 ejecuciones en la VM y de 7 en Node.js:
| Operación | VM | Node.js |
|---|---|---|
| Decodificar un punto de G1, la firma | 3 ms | 60 ms |
| Decodificar un punto de G2, U | 1,3 ms | 40 ms |
| Un emparejamiento | 11 ms | 230 ms |
| Verificar la firma de una ronda de Quicknet | 16 ms | 380 ms |
| La misma verificación, decodificando además la clave pinneada | 18 ms | 420 ms |
| Descifrar un stanza tlock (IBE) | 20 ms | 435 ms |
| Cifrar un stanza tlock (IBE) | 20 ms | 460 ms |
| Pasos 10 y 11: verificar el release y abrir el stanza | 35 ms | 760 ms |
La verificación hace el hash a G1, decodifica la firma y comprueba e(H(m), clave) · e(−firma, G2) = 1 con un solo bucle de Miller para los dos pares y una exponenciación final. El descifrado decodifica U, hace un emparejamiento y comprueba U = r·G2. En los pasos 10 y 11, el paso 11 verifica otra vez el release, como en Go, sin repetir el emparejamiento del paso 10.
Una estimación para un móvil: si uno de gama media, con Dart compilado AOT para ARM64, va de dos a cuatro veces más lento que esta VM, la verificación y el descifrado tardarán entre 30 y 80 ms cada uno, y los pasos 10 y 11 juntos, entre 70 y 150 ms. La app los llama en un `Isolate` (plan, «Rendimiento»). En la web, el `BigInt` de dart2js es unas veinte veces más lento que el de la VM; una capa del cuerpo de limbs fijos sería la forma de acelerarlo.
## Versiones
@ -84,7 +153,7 @@ La rama sigue la versión de la especificación: `v0.11`, hasta que `datekeys-go
## Dependencias
- **En ejecución:** solo `package:crypto`, para SHA-1, SHA-2 y HMAC. Todo lo demás es código propio: HKDF, PBKDF2, scrypt, ChaCha20-Poly1305, X25519, Ed25519, BLS12-381, ECDSA, RSA, DER, CMS y CBOR. Hoy la librería usa de `package:crypto`solo SHA-512, en Ed25519: SHA-256 y HMAC-SHA256 son propios, porque PBKDF2 los necesita con los estados de la clave calculados una vez.
- **En ejecución:** solo `package:crypto`, para SHA-1, SHA-2 y HMAC. Todo lo demás es código propio: HKDF, PBKDF2, scrypt, ChaCha20-Poly1305, X25519, Ed25519, BLS12-381, ECDSA, RSA, DER, CMS y CBOR. Hoy la librería usa de `package:crypto`SHA-512, en Ed25519, y SHA-256, en BLS12-381 y tlock. Las primitivas tienen además su propio SHA-256 con HMAC-SHA256, porque PBKDF2 los necesita con los estados de la clave calculados una vez.
- **En desarrollo:** solo `package:test`, aprobado el 5 de octubre de 2026. No hay paquete de lints: las reglas del análisis están en `analysis_options.yaml`.
- **`pubspec.lock`** va en el repositorio, para que las pruebas usen siempre las mismas versiones.
@ -123,7 +192,7 @@ dart run tool/sync_testdata.dart check --against ../datekeys-go
- 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`.
`test/vectors/` tiene los vectores de las primitivas y de `age`. Los escribe Go, con las librerías de la caché de módulos que usan`datekeys-go` y `filippo.io/age`; 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:
`test/vectors/` tiene los vectores de las primitivas, de `age`, de BLS12-381 y de tlock. 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 `provider` y `agewrap`; 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 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
cd ../datekeys-go && go run ../datekeys-dart/tool/gen_primitive_vectors.go -out ../datekeys-dart/test/vectors
@ -133,16 +202,37 @@ cd ../datekeys-go && go run ../datekeys-dart/tool/gen_primitive_vectors.go -out
cd ../datekeys-go && go run ../datekeys-dart/tool/gen_age_vectors.go -out ../datekeys-dart/test/vectors
```
```bash
cd ../datekeys-go && go run ../datekeys-dart/tool/bls12381_go_vectors.go ../datekeys-ts/src/lib/dkc/testing/bls12381-vectors.json > ../datekeys-dart/test/vectors/bls12381_vectors.json
```
```bash
cd ../datekeys-go && go run ../datekeys-dart/tool/ibe_go_vectors.go ../datekeys-dart/testdata/fixtures ../datekeys-ts/src/lib/dkc/testing/ibe-vectors.json > ../datekeys-dart/test/vectors/ibe_vectors.json
```
```bash
cd ../datekeys-go && go run ../datekeys-dart/tool/tlock_go_vectors.go ../datekeys-ts/src/lib/dkc/testing/tlock-vectors.json > ../datekeys-dart/test/vectors/tlock_vectors.json
```
```bash
cd ../datekeys-go && go run ../datekeys-dart/tool/release_go_vectors.go ../datekeys-dart/testdata > ../datekeys-dart/test/vectors/release_vectors.json
```
| Fichero | Contenido |
|---|---|
| `primitives.json` | SHA-256, HMAC, HKDF (RFC 5869), PBKDF2 (con el vector del §38.1), scrypt (RFC 7914), ChaCha20, Poly1305 y ChaCha20-Poly1305 (RFC 8439), X25519 (RFC 7748, BoringSSL y los puntos de orden pequeño), Ed25519 (las 64 primeras líneas de `sign.input` de Go, cuyas tres primeras son las de la RFC 8032, y sus mutaciones), el Base64 de Go y el Bech32 de `age` |
| `primitives.g.dart` | El mismo JSON como constante de Dart, para las pruebas compiladas a JavaScript, que no leen ficheros |
| `age.json` | Ficheros con stanzas X25519 y scrypt, sus cortes y manipulaciones, un corpus de cabeceras contra la gramática del §28.1 y el límite de 2 MiB, y las reglas e identities de `agewrap`, con el texto del error de Go en cada caso |
| `age_fixtures.json` | El `PAYLOAD_AGE` de cada fixture con su `payload_identity`, y el `INNER_ACCESS_AGE` de los `time_and_key`, que Go saca de `OUTER_TIME_AGE` con el release del fixture |
| `bls12381_vectors.json` | Las 157 codificaciones límite congeladas de `datekeys-ts` con el veredicto de Go calculado otra vez, y, con una semilla fija, decodificaciones (con la clase del fallo de kilic: formato, curva o subgrupo), sumas, múltiplos, emparejamientos, hashes a G1 (también los mensajes del apéndice J.9.1 del RFC 9380), el mapa de un elemento, los excepcionales incluidos, y firmas BLS sobre G1 |
| `ibe_vectors.json` | GT y H2, H3 con candidatos rechazados, H4, identidades de rondas, el stanza tlock de cada fixture de `testdata/` con sus valores intermedios y su file key, los ciphertexts de kyber y los veredictos de `DecryptCCAonG2` sobre copias editadas del stanza de `time_only` |
| `tlock_vectors.json` | El cifrado de kyber con sigma fijo, reproducido byte a byte, y los ciphertexts que escribió `datekeys-ts` y abrió Go |
| `release_vectors.json` | Los veredictos, códigos y textos de `provider.Verify`, de `NewTimeIdentity` con su `Unwrap` y de `NewTimeRecipient` |
- Los fixtures que leen los generadores son los de `testdata/` de este repositorio, la copia sincronizada.
- `primitives.json` sale igual en cada ejecución. `age` 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`y los cuatro ficheros de BLS12-381 y tlock 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.
- 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.
- Las pruebas que corren en Node.js no leen ficheros. Los valores de Go que usan están en `primitives.g.dart`, `test/bls12381_constants.dart` y `test/ibe_constants.dart`. Una prueba en la VM compara los dos últimos con los JSON.