You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
dateKeys-dart/CHANGELOG.md

61 lines
7.9 KiB

# Changelog
Cambios notables de la librería Dart. El proyecto usa versionado semántico; mientras sea 0.x, no hay promesa de estabilidad.
## Especificación 0.11, en la rama `v0.11` — sin versión
### Etapa 2: primitivas y `age` (05-10-2026)
- **Primitivas, de código propio.** Son internas: `lib/datekeys.dart` no las exporta.
- SHA-256 con su compresión, y HMAC-SHA256 con los estados interior y exterior de la clave calculados una vez. Sobre ellos, HKDF-SHA256 (RFC 5869) y PBKDF2-HMAC-SHA256 (RFC 8018), cuyas iteraciones son dos compresiones sobre palabras: 600 000 iteraciones tardan 1,1 s en la VM, frente a unos 3,5 s con el HMAC de `package:crypto`.
- scrypt (RFC 7914) con Salsa20/8, con las comprobaciones y los textos de `scrypt.Key` de Go.
- ChaCha20, Poly1305 en diez limbs de 13 bits, y ChaCha20-Poly1305 (RFC 8439), con el tag comparado en tiempo constante.
- X25519 (RFC 7748) sobre el cuerpo de TweetNaCl en doubles, con clamping y el secreto todo a ceros rechazado con el texto de `crypto/ecdh`.
- Ed25519 estricto (§29.9), port de `internal/ed25519strict`: `verifyStrict`, `canonical`, `smallOrder` y `onCurve`. La aritmética de los puntos es la de TweetNaCl; los escalares módulo ℓ y `onCurve` usan `BigInt`, que no es de tiempo constante, solo con datos públicos.
- El Base64 de Go, con su modo estricto y el offset de sus errores, y el Bech32 de `age`, con sus textos.
- De `package:crypto` solo se usa SHA-512, en Ed25519.
- **Lectura de `age` v1**, port de `filippo.io/age` v1.3.2 (`lib/src/age.dart`):
- la cabecera y sus límites de `internal/format`, con los textos de error de Go;
- el MAC de la cabecera, sobre la cabecera escrita otra vez como la escribe `age`;
- los stanzas X25519 y scrypt. La identity de scrypt rechaza por defecto un factor de trabajo por encima de 16, como `authorkey` de Go; el de `age` es 22;
- la clave del payload y el STREAM de `internal/stream`, que se descifra según llega el texto cifrado, con los mismos casos de fin de fichero que el lector de Go: sin chunk final, chunk que no se autentica, último chunk vacío y datos tras el final;
- cada fallo es una `AgeException` con el texto de Go y su fase, la cabecera o el payload, para que la etapa 4 dé las razones fijas de `capsule.classify`. La `DateKeysException` de una identity pasa sin cambios.
- **`agewrap`** (`lib/src/agewrap.dart`): las reglas de stanzas de `OUTER_TIME_AGE`, `PAYLOAD_AGE` e `INNER_ACCESS_AGE`, la lectura de los stanzas sin secretos, `PayloadIdentity` y `AccessIdentity`, con los textos y los códigos de Go. `checkTimeStanzas` recibe la ronda, el chain hash y el id del perfil, que llegará con la etapa 4.
- **Vectores de Go** en `test/vectors/`, que escriben `tool/gen_primitive_vectors.go` y `tool/gen_age_vectors.go` 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:
- `primitives.json` y su copia en Dart, `primitives.g.dart`: RFC 5869, 7748, 7914, 8032 (por `sign.input` de Go) y 8439, PBKDF2 con el vector del §38.1, los puntos de orden pequeño, Base64 y Bech32. Incluye dos mensajes con los que una suma de productos de Poly1305 pasa de 2^32: un acarreo tomado con un desplazamiento fallaría en la web, y una prueba lo detecta en Node;
- `age.json`: ficheros 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 de Go en cada caso;
- `age_fixtures.json`: el `PAYLOAD_AGE` de los 24 fixtures con su `payload_identity`, y el `INNER_ACCESS_AGE` de los 6 `time_and_key`, sacado de `OUTER_TIME_AGE` con el release del fixture.
- **Pruebas.** 296 en la VM y una aplazada, 127 más que en la etapa 1; 83 en Node.js, 27 más. Las de las primitivas y las de `age` sin ficheros corren también compiladas a JavaScript, sin los casos largos (PBKDF2 a 600 000 iteraciones, scrypt con logN 16, X25519 iterada 1000 veces).
- **Fallos inyectados**, uno a uno y revertidos: 46 en las primitivas, `age` y `agewrap`. Las pruebas detectan todos los que cambian un resultado. Cuatro no lo cambian: la máscara de una mitad de rotación de SHA-256 cuyos bits altos solo llegan a sumas enmascaradas, el redondeo de `_car` cuando sus entradas nunca son negativas, el de un acarreo del producto del cuerpo, que conserva el valor, y el acarreo del limb 1 de Poly1305 tomado con desplazamiento, cuya suma no pasa de 2^32.
- **`tool/bench.dart`** mide las primitivas en la VM y compilado a JavaScript; las cifras, en el README.
### El gate con Node.js (05-10-2026)
- `tool/check.sh` corre también `dart test -p node`: las pruebas que no leen ficheros, compiladas a JavaScript, comprueban en cada commit que los enteros son exactos en la web. Lo decidió el autor.
### Etapa 1: errores, bytes, CBOR y DER (05-10-2026)
- **Errores normativos (§69).** `ErrorCode` con los 19 códigos en el orden del spec y `DateKeysException`, con el mensaje `contexto: CÓDIGO` de Go. `wrap` y `withContext` hacen lo que `fmt.Errorf("prefijo: %w")`, y `errorCode` lo que `datekeys.Code`. Una prueba compara el catálogo con las líneas `ERR_` del §69, leído de `datekeys-go` en el tag `spec-v0.11`.
- **Bytes.** Hexadecimal, comparación y concatenación.
- UTF-8 estricto: rechaza lo que rechaza `utf8.Valid` de Go y conserva un U+FEFF inicial. El `Utf8Decoder` de `dart:convert` lo descarta, en la VM y en la web, así que no se usa.
- Un `String` con un surrogate suelto se escribe en UTF-8 generalizado (WTF-8), que no es UTF-8 válido.
- `utf8.DecodeRune` y el `%q` de Go (`strconv.Quote`). La tabla de `strconv.IsPrint` de Go 1.26 se copia de `datekeys-ts`, y una prueba fija el SHA-256 del conjunto de runas.
- **CBOR (§58, §58.1).** Port de `codec/codec.go`: `CborEncoder`, `CborDecoder`, `unmarshalCbor`, `peekSchema`, `checkSchema` y `walkCbor`, con los mismos textos de error.
- Los enteros son exactos en la VM y en la web: un `int` hasta 2^53-1 y un `BigInt` por encima, también en las claves de los mapas y en los textos de error.
- El `Encoder` de Go rechaza el UTF-8 inválido; aquí el único texto inválido es un surrogate suelto, y el error lo cita como Go citaría sus bytes en UTF-8 generalizado.
- `CborEncoder.uint` exige 0..2^53-1, con un texto propio, como en `datekeys-ts`; `uint64` escribe hasta 2^64-1.
- **DER estricto.** Port de `internal/der/der.go` en `601e6d2`, ya del borrador v0.12: `check`, `split`, `content`, `setOfSorted` y `parseTime`. `parseTime` devuelve un `DerTime` con los campos y los segundos Unix, exacto al nanosegundo. Es interno: `lib/datekeys.dart` no lo exporta.
- **Pruebas.** Port de `errors_test.go`, `codec_test.go`, `internal_test.go`, `vectors_test.go` y `der_test.go`, de `cbor.test.ts` y de `bytes.test.ts`, con los textos de error que imprime Go.
- Los objetivos de fuzzing de Go son propiedades con semilla, contra un codificador y un decodificador de referencia escritos aparte, como `internal/cbortest`.
- `testdata/vectors/cbor.json`: los 36 `accept` y los 67 `reject`, con los límites de `walk` y los valores. Los 172 vectores de `schemas` se leen y se aplazan: necesitan los decodificadores de esquema de la etapa 4.
- 169 pruebas en la VM y una aplazada. Las 56 que no leen ficheros pasan también en Node.js (`dart test -p node`); las que leen ficheros llevan `@TestOn('vm')`.
### Etapa 0: el paquete (05-10-2026)
- Paquete `datekeys` en Dart puro, sin Flutter, para Dart 3.13 y sin publicar (`publish_to: none`).
- `testdata/` sincronizado con el tag `spec-v0.11` de `datekeys-go` (`ae33434`): 124 ficheros. Su `testdata/SOURCE.json` es el mismo, byte a byte, que escribe `datekeys-ts` para ese commit.
- `tool/sync_testdata.dart`, el equivalente de `scripts/sync-testdata.mjs`. `test/testdata_test.dart` comprueba la copia y que cada fichero nombre la versión de la especificación.
- `tool/check.sh`, el gate local.
- Dependencias: `package:crypto` en ejecución y `package:test` en desarrollo.
- Licencia Apache-2.0.

Powered by TurnKey Linux.