Initial implementation of the DateKeys Protocol v0.8.1
Reference implementation in Go, built from the implementation plan
(milestones M0 to M5): datekey, profile, provider, codec, agewrap,
extension, capsule, accesskey, the datekeys CLI, official vectors and
fixtures, the mutation corpus, fuzz targets, interop and live tests,
CI workflows, traceability and policy documents.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2 weeks ago
|
|
|
|
# datekeys-go
|
|
|
|
|
|
|
|
|
|
|
|
Implementación de referencia en Go de la **DateKeys Protocol Specification
|
|
|
|
|
|
v0.8.2** ([`spec/`](spec/DateKeys_Protocol_Specification_v0.8.2.md)).
|
Initial implementation of the DateKeys Protocol v0.8.1
Reference implementation in Go, built from the implementation plan
(milestones M0 to M5): datekey, profile, provider, codec, agewrap,
extension, capsule, accesskey, the datekeys CLI, official vectors and
fixtures, the mutation corpus, fuzz targets, interop and live tests,
CI workflows, traceability and policy documents.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2 weeks ago
|
|
|
|
[English version](README.md).
|
|
|
|
|
|
|
|
|
|
|
|
DateKeys cifra datos de forma que solo puedan abrirse a partir de un instante
|
|
|
|
|
|
elegido. La condición temporal procede del beacon de aleatoriedad **Quicknet**
|
|
|
|
|
|
de drand: los datos se sellan con cifrado timelock hacia una ronda futura, y la
|
|
|
|
|
|
firma BLS de esa ronda, que drand publica cuando llega, es la llave. Todo lo que
|
|
|
|
|
|
se puede verificar localmente se verifica localmente; relays, cachés y APIs son
|
|
|
|
|
|
transportes no confiables.
|
|
|
|
|
|
|
|
|
|
|
|
> **Estado: v0.x, pre-estándar.** La especificación es un borrador y la API
|
|
|
|
|
|
> puede cambiar antes de v1.0.0. El código aún no ha pasado una revisión
|
|
|
|
|
|
> criptográfica externa (spec §75). No lo uses para secretos de alto valor.
|
|
|
|
|
|
|
|
|
|
|
|
## Qué implementa
|
|
|
|
|
|
|
|
|
|
|
|
| Objeto | Spec | Paquete |
|
|
|
|
|
|
|---|---|---|
|
|
|
|
|
|
| DateKey: fecha → ronda, cadena canónica `dk1_…` | §14–§19 | [`datekey`](datekey) |
|
|
|
|
|
|
| Provider Profile, perfil Quicknet pinneado, `profile_hash` | §10–§13 | [`profile`](profile) |
|
|
|
|
|
|
| Fuentes de releases, verificación BLS local, relays drand | §45–§52 | [`provider`](provider), [`provider/drand`](provider/drand) |
|
|
|
|
|
|
| DateKeyCap `.dkc`: `time_only` y `time_and_key` | §20–§39, §61–§63 | [`capsule`](capsule) |
|
|
|
|
|
|
| DateKeys Access Key `.dkk` | §40–§44 | [`accesskey`](accesskey) |
|
|
|
|
|
|
| Extensiones | §54 | [`extension`](extension) |
|
|
|
|
|
|
| CBOR determinista | §58 | [`codec`](codec) |
|
|
|
|
|
|
| Errores normativos | §69 | [`errors.go`](errors.go) |
|
|
|
|
|
|
| CLI | — | [`cmd/datekeys`](cmd/datekeys) |
|
|
|
|
|
|
|
|
|
|
|
|
Aquí no se implementa criptografía. El cifrado es [age](https://age-encryption.org)
|
|
|
|
|
|
(`filippo.io/age`); el timelock es [tlock](https://github.com/drand/tlock)
|
|
|
|
|
|
(solo su núcleo exportado); la verificación BLS es la de drand. Este módulo
|
|
|
|
|
|
aporta framing, CBOR, bindings, reglas de verificación y flujo, y aplica las
|
|
|
|
|
|
reglas de stanzas del protocolo dentro de las identities de age, para que un
|
|
|
|
|
|
fichero nunca se acepte solo porque age haya podido desenvolver una clave.
|
|
|
|
|
|
|
|
|
|
|
|
No implementa, a propósito: el servidor y la cola de la Release API, el
|
|
|
|
|
|
almacenamiento y la entrega, extensiones concretas ni el cliente TypeScript
|
|
|
|
|
|
(plan §2).
|
|
|
|
|
|
|
|
|
|
|
|
## Una cápsula, en un dibujo
|
|
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
|
.dkc = PRELUDE (16 B) || PUBLIC_HEADER (CBOR) || SEALED_CONTROL (age) || PAYLOAD_AGE (age, hasta EOF)
|
|
|
|
|
|
|
|
|
|
|
|
time_only: SEALED_CONTROL = age(tlock ronda R → CONTROL_CBOR)
|
|
|
|
|
|
time_and_key: SEALED_CONTROL = age(tlock ronda R → age(recipients X25519 → CONTROL_CBOR))
|
|
|
|
|
|
CONTROL_CBOR = { header_binding = SHA-256(PRELUDE || PUBLIC_HEADER), I_PAYLOAD, extensiones }
|
|
|
|
|
|
PAYLOAD_AGE = age(X25519 R_PAYLOAD → tus datos), en streaming
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## CLI
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
go install g.activething.com/go/DateKeys/cmd/datekeys@latest
|
Initial implementation of the DateKeys Protocol v0.8.1
Reference implementation in Go, built from the implementation plan
(milestones M0 to M5): datekey, profile, provider, codec, agewrap,
extension, capsule, accesskey, the datekeys CLI, official vectors and
fixtures, the mutation corpus, fuzz targets, interop and live tests,
CI workflows, traceability and policy documents.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2 weeks ago
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
El módulo se sirve desde el Gitea del proyecto, cuyo certificado Go no
|
|
|
|
|
|
reconoce por defecto. Define `GOPRIVATE=g.activething.com` para que el proxy y
|
|
|
|
|
|
la base de datos de sumas de Go no intervengan, e instala el certificado del
|
|
|
|
|
|
servidor o, en una red de confianza, define `GOINSECURE=g.activething.com`.
|
|
|
|
|
|
|
Initial implementation of the DateKeys Protocol v0.8.1
Reference implementation in Go, built from the implementation plan
(milestones M0 to M5): datekey, profile, provider, codec, agewrap,
extension, capsule, accesskey, the datekeys CLI, official vectors and
fixtures, the mutation corpus, fuzz targets, interop and live tests,
CI workflows, traceability and policy documents.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2 weeks ago
|
|
|
|
```bash
|
|
|
|
|
|
datekeys datekey resolve -at 2030-01-01T00:00:00Z
|
|
|
|
|
|
datekeys encrypt -at 2030-01-01T00:00:00Z -in carta.txt -out carta.dkc
|
|
|
|
|
|
datekeys encrypt -at 2030-01-01T00:00:00Z -policy time_and_key -dkk carta.dkk -in carta.txt -out carta.dkc
|
|
|
|
|
|
datekeys inspect -in carta.dkc
|
|
|
|
|
|
datekeys decrypt -in carta.dkc -out carta.txt -dkk carta.dkk
|
|
|
|
|
|
datekeys profile hash
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
`encrypt` nunca usa la red. `inspect` ejecuta solo las comprobaciones previas
|
|
|
|
|
|
al desbloqueo (spec §63, pasos 1 a 8): nunca pide un release ni usa secretos.
|
|
|
|
|
|
`decrypt` obtiene el release de relays públicos de drand, lo verifica
|
|
|
|
|
|
localmente y publica el plaintext solo cuando age lo ha autenticado entero.
|
|
|
|
|
|
Nunca se sobrescriben ficheros de salida.
|
|
|
|
|
|
|
|
|
|
|
|
## Librería
|
|
|
|
|
|
|
|
|
|
|
|
```go
|
|
|
|
|
|
reg, err := profile.Default() // perfil Quicknet pinneado, comprobado contra su profile_hash
|
|
|
|
|
|
|
|
|
|
|
|
// Cifrar: sin red, la ronda se resuelve localmente.
|
|
|
|
|
|
res, err := capsule.Encrypt(dst, src, capsule.EncryptOptions{
|
|
|
|
|
|
Profile: profile.Quicknet(),
|
|
|
|
|
|
UnlockAt: time.Date(2030, 1, 1, 0, 0, 0, 0, time.UTC),
|
|
|
|
|
|
Policy: capsule.TimeAndKey,
|
|
|
|
|
|
NewPortableKey: true, // res.PortableKey es la .dkk; se codifica con accesskey.Encode
|
|
|
|
|
|
Now: time.Now,
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
// Inspeccionar: pasos 1 a 8, sin red ni secretos.
|
|
|
|
|
|
in, err := capsule.Inspect(f, capsule.InspectOptions{Registry: reg})
|
|
|
|
|
|
|
|
|
|
|
|
// Abrir: pasos 1 a 18; el release se verifica localmente.
|
|
|
|
|
|
opened, err := capsule.Open(ctx, tmp, f, capsule.OpenOptions{
|
|
|
|
|
|
Registry: reg,
|
|
|
|
|
|
Source: drand.New(),
|
|
|
|
|
|
AccessKey: key, // o Identities: []age.Identity{...}
|
|
|
|
|
|
Now: time.Now,
|
|
|
|
|
|
})
|
|
|
|
|
|
if errors.Is(err, datekeys.ErrReleaseUnavailable) { /* todavía no */ }
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
`Open` escribe el plaintext en streaming; si falla, descarta lo escrito (spec
|
|
|
|
|
|
§56). Todo fallo del protocolo envuelve uno de los 17 errores normativos del
|
|
|
|
|
|
§69, así que `errors.Is` y `datekeys.Code(err)` lo identifican.
|
|
|
|
|
|
|
|
|
|
|
|
## Propiedades de seguridad y límites
|
|
|
|
|
|
|
|
|
|
|
|
- **Confidencialidad temporal** bajo el supuesto de umbral de drand. El
|
|
|
|
|
|
timelock de Quicknet **no es post-cuántico**: los ciphertexts guardados
|
|
|
|
|
|
durante años quedan expuestos a *harvest now, decrypt later* (spec §7.7, §53).
|
|
|
|
|
|
- **Sin confianza en servidores**: el perfil va pinneado en el binario, la ronda
|
|
|
|
|
|
se calcula localmente, los releases se verifican con BLS localmente y una
|
|
|
|
|
|
firma válida de otra ronda se rechaza (spec §13, §17, §51).
|
|
|
|
|
|
- **Integridad**: framing, cabecera, control y payload están autenticados;
|
|
|
|
|
|
cualquier cambio hace fallar la apertura (fixtures y corpus de mutaciones).
|
|
|
|
|
|
- **Sin autoría**: `time_only` da coherencia interna, no prueba de quién creó
|
|
|
|
|
|
la cápsula, ni antes ni después de madurar; `time_and_key` añade una barrera
|
|
|
|
|
|
de acceso, no una firma (spec §36.1).
|
|
|
|
|
|
- **Recuperar años después** exige el release histórico: de un relay drand que
|
|
|
|
|
|
aún lo sirva o de cualquier caché, verificado de nuevo localmente (spec §50).
|
|
|
|
|
|
|
|
|
|
|
|
Ver [SECURITY.md](SECURITY.md).
|
|
|
|
|
|
|
|
|
|
|
|
## Conformidad y tests
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
go test ./... # unitarios, vectores golden, fixtures, mutaciones
|
|
|
|
|
|
go test -race -cover ./...
|
|
|
|
|
|
go test -fuzz=FuzzInspect ./capsule # un objetivo de fuzzing cada vez
|
|
|
|
|
|
go test -tags interop ./capsule # las CLI oficiales age y tle abren nuestros ficheros
|
|
|
|
|
|
go test -tags integration ./capsule ./provider/drand # Quicknet en vivo
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
- `testdata/vectors`: vectores de `profile_hash`, fecha→ronda y `dk1_` (spec §65, §66).
|
|
|
|
|
|
- `testdata/fixtures`: fixtures oficiales `.dkc`/`.dkk` sobre rondas ya
|
|
|
|
|
|
publicadas, con la firma BLS embebida y todos los valores intermedios (spec
|
|
|
|
|
|
§67, §68); se descifran sin red.
|
|
|
|
|
|
- `capsule/mutation_test.go`: las 23 mutaciones del §64 y 30 más, cada una con
|
Initial implementation of the DateKeys Protocol v0.8.1
Reference implementation in Go, built from the implementation plan
(milestones M0 to M5): datekey, profile, provider, codec, agewrap,
extension, capsule, accesskey, the datekeys CLI, official vectors and
fixtures, the mutation corpus, fuzz targets, interop and live tests,
CI workflows, traceability and policy documents.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2 weeks ago
|
|
|
|
su error y su paso exactos, comprobando además que los fallos previos al
|
|
|
|
|
|
desbloqueo nunca provocan una petición de release.
|
|
|
|
|
|
- [`docs/traceability.md`](docs/traceability.md): sección del spec → código → test.
|
|
|
|
|
|
- [`spec/datekeys.cddl`](spec/datekeys.cddl): schemas CBOR.
|
|
|
|
|
|
|
|
|
|
|
|
## Licencia
|
|
|
|
|
|
|
|
|
|
|
|
Código: Apache-2.0 ([LICENSE](LICENSE)). Especificación: CC-BY-4.0
|
|
|
|
|
|
([spec/README.md](spec/README.md)). `codec/bech32` se copia de age bajo su
|
|
|
|
|
|
propia licencia. "DateKeys" es un nombre reservado: ver [TRADEMARKS.md](TRADEMARKS.md).
|