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.
 
 
Go to file
dev 0bd38f18cf
Initial implementation of the DateKeys Protocol v0.8.1
2 weeks ago
.github Initial implementation of the DateKeys Protocol v0.8.1 2 weeks ago
accesskey Initial implementation of the DateKeys Protocol v0.8.1 2 weeks ago
agewrap Initial implementation of the DateKeys Protocol v0.8.1 2 weeks ago
capsule Initial implementation of the DateKeys Protocol v0.8.1 2 weeks ago
cmd/datekeys Initial implementation of the DateKeys Protocol v0.8.1 2 weeks ago
codec Initial implementation of the DateKeys Protocol v0.8.1 2 weeks ago
datekey Initial implementation of the DateKeys Protocol v0.8.1 2 weeks ago
docs Initial implementation of the DateKeys Protocol v0.8.1 2 weeks ago
extension Initial implementation of the DateKeys Protocol v0.8.1 2 weeks ago
internal/testkit Initial implementation of the DateKeys Protocol v0.8.1 2 weeks ago
profile Initial implementation of the DateKeys Protocol v0.8.1 2 weeks ago
provider Initial implementation of the DateKeys Protocol v0.8.1 2 weeks ago
scripts Initial implementation of the DateKeys Protocol v0.8.1 2 weeks ago
spec Initial implementation of the DateKeys Protocol v0.8.1 2 weeks ago
testdata Initial implementation of the DateKeys Protocol v0.8.1 2 weeks ago
.gitattributes Initial implementation of the DateKeys Protocol v0.8.1 2 weeks ago
.gitignore Initial implementation of the DateKeys Protocol v0.8.1 2 weeks ago
.golangci.yml Initial implementation of the DateKeys Protocol v0.8.1 2 weeks ago
.goreleaser.yaml Initial implementation of the DateKeys Protocol v0.8.1 2 weeks ago
CHANGELOG.md Initial implementation of the DateKeys Protocol v0.8.1 2 weeks ago
CONTRIBUTING.md Initial implementation of the DateKeys Protocol v0.8.1 2 weeks ago
LICENSE Initial implementation of the DateKeys Protocol v0.8.1 2 weeks ago
README.es.md Initial implementation of the DateKeys Protocol v0.8.1 2 weeks ago
README.md Initial implementation of the DateKeys Protocol v0.8.1 2 weeks ago
SECURITY.md Initial implementation of the DateKeys Protocol v0.8.1 2 weeks ago
TRADEMARKS.md Initial implementation of the DateKeys Protocol v0.8.1 2 weeks ago
errors.go Initial implementation of the DateKeys Protocol v0.8.1 2 weeks ago
errors_test.go Initial implementation of the DateKeys Protocol v0.8.1 2 weeks ago
go.mod Initial implementation of the DateKeys Protocol v0.8.1 2 weeks ago
go.sum Initial implementation of the DateKeys Protocol v0.8.1 2 weeks ago

README.md

datekeys-go

Reference implementation in Go of the DateKeys Protocol Specification v0.8.1 (spec/). Versión en español.

DateKeys encrypts data so that it can only be opened after a chosen instant. The time condition comes from the drand Quicknet randomness beacon: data is sealed with timelock encryption to a future round, and the round's BLS signature, published by drand when the round arrives, is the key. Everything that can be verified locally is verified locally; relays, caches and APIs are untrusted transports.

Status: v0.x, pre-standard. The specification is a draft and the API may change before v1.0.0. The code has not had an external cryptographic review yet (spec §75). Do not rely on it for high-value secrets.

What it implements

Object Spec Package
DateKey: date → round, canonical dk1_… string §14–§19 datekey
Provider Profile, pinned Quicknet profile, profile_hash §10–§13 profile
Release sources, local BLS verification, drand relays §45–§52 provider, provider/drand
DateKeyCap .dkc: time_only and time_and_key §20–§39, §61–§63 capsule
DateKeys Access Key .dkk §40–§44 accesskey
Extensions §54 extension
Deterministic CBOR §58 codec
Normative errors §69 errors.go
CLI — cmd/datekeys

No cryptography is implemented here. Encryption is age (filippo.io/age); the timelock is tlock (its exported core only); BLS verification is drand's. This module adds framing, CBOR, bindings, verification rules and the flow, and it enforces the stanza rules of the protocol inside the age identities, so that a file is never accepted just because age could unwrap a key.

Not implemented on purpose: the Release API server and queue, storage and delivery, concrete extensions, and the TypeScript client (plan §2).

A capsule, in one picture

.dkc = PRELUDE (16 B) || PUBLIC_HEADER (CBOR) || SEALED_CONTROL (age) || PAYLOAD_AGE (age, to EOF)

time_only:     SEALED_CONTROL = age(tlock round R → CONTROL_CBOR)
time_and_key:  SEALED_CONTROL = age(tlock round R → age(X25519 recipients → CONTROL_CBOR))
CONTROL_CBOR = { header_binding = SHA-256(PRELUDE || PUBLIC_HEADER), I_PAYLOAD, extensions }
PAYLOAD_AGE  = age(X25519 R_PAYLOAD → your data), streamed

CLI

go install github.com/datekeys/datekeys-go/cmd/datekeys@latest
datekeys datekey resolve -at 2030-01-01T00:00:00Z
datekeys encrypt -at 2030-01-01T00:00:00Z -in letter.txt -out letter.dkc
datekeys encrypt -at 2030-01-01T00:00:00Z -policy time_and_key -dkk letter.dkk -in letter.txt -out letter.dkc
datekeys inspect -in letter.dkc
datekeys decrypt -in letter.dkc -out letter.txt -dkk letter.dkk
datekeys profile hash

encrypt never touches the network. inspect runs only the pre-unlock checks (spec §63 steps 1–8): it never requests a release and never uses a secret. decrypt fetches the release from public drand relays, verifies it locally and publishes the plaintext only after age authenticated all of it. Outputs are never overwritten.

Library

reg, err := profile.Default() // pinned Quicknet profile, checked against its profile_hash

// Encrypt: no network, the round is resolved locally.
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 is the .dkk; encode it with accesskey.Encode
	Now:            time.Now,
})

// Inspect: steps 1–8, no network, no secrets.
in, err := capsule.Inspect(f, capsule.InspectOptions{Registry: reg})

// Open: steps 1–18; the release is verified locally.
opened, err := capsule.Open(ctx, tmp, f, capsule.OpenOptions{
	Registry:  reg,
	Source:    drand.New(),
	AccessKey: key, // or Identities: []age.Identity{...}
	Now:       time.Now,
})
if errors.Is(err, datekeys.ErrReleaseUnavailable) { /* not yet */ }

Open streams the plaintext; on error, discard what was written (spec §56). Every protocol failure wraps one of the 17 normative errors of spec §69, so errors.Is and datekeys.Code(err) identify it.

Security properties and limits

  • Time confidentiality holds under drand's threshold assumption. The Quicknet timelock is not post-quantum: ciphertexts kept for years are exposed to harvest-now, decrypt-later (spec §7.7, §53).
  • No trust in servers: the profile is pinned in the binary, the round is computed locally, releases are BLS-verified locally, and a valid signature of another round is rejected (spec §13, §17, §51).
  • Integrity: framing, header, control and payload are all authenticated; any change makes opening fail (fixtures and the mutation corpus).
  • No authorship: time_only gives internal coherence, not proof of who created a capsule, before or after it matures; time_and_key adds an access barrier, not a signature (spec §36.1).
  • Recovery years later needs the historical release: from a drand relay that still serves it or from any cache, re-verified locally (spec §50).

See SECURITY.md.

Conformance and tests

go test ./...                               # unit, golden vectors, fixtures, mutation corpus
go test -race -cover ./...
go test -fuzz=FuzzInspect ./capsule         # one fuzz target at a time
go test -tags interop ./capsule             # official age and tle CLIs open our files
go test -tags integration ./capsule ./provider/drand   # live Quicknet
  • testdata/vectors: profile hash, date→round and dk1_ vectors (spec §65, §66).
  • testdata/fixtures: official .dkc/.dkk fixtures over published rounds, with the BLS signature embedded and every intermediate value (spec §67, §68); they decrypt offline.
  • capsule/mutation_test.go: the 20 mutations of spec §64 and 25 more, each with its exact error and step, and a check that pre-unlock failures never cause a release request.
  • docs/traceability.md: spec section → code → test.
  • spec/datekeys.cddl: CBOR schemas.

License

Code: Apache-2.0 (LICENSE). Specification: CC-BY-4.0 (spec/README.md). codec/bech32 is copied from age under its own license. "DateKeys" is a reserved name: see TRADEMARKS.md.

Powered by TurnKey Linux.