|
|
|
|
|
# DateKeys v0.14: threat model, goals and non-goals
|
|
|
|
|
|
|
|
|
|
|
|
*Informative English summary of spec §3, §4, §5, §7, §36.1, §55, §55.1 and §55.2 of `DateKeys_Protocol_Specification_v0.14.md`. The Spanish text is the reference. Additions of v0.14 are marked **(v0.14)**.*
|
|
|
|
|
|
|
|
|
|
|
|
## 1. Guiding principle (§3)
|
|
|
|
|
|
|
|
|
|
|
|
Never trust the server when the same property can be verified cryptographically on the client:
|
|
|
|
|
|
|
|
|
|
|
|
- date → condition is computed locally;
|
|
|
|
|
|
- provider profiles are pinned locally;
|
|
|
|
|
|
- releases are verified locally;
|
|
|
|
|
|
- `.dkc`, `.dkk`, APIs and relays are untrusted inputs;
|
|
|
|
|
|
- DateKeys must not need the plaintext or final access secrets.
|
|
|
|
|
|
|
|
|
|
|
|
## 2. Security goals (§4)
|
|
|
|
|
|
|
|
|
|
|
|
1. **Time confidentiality.** Under the provider's assumptions, a time condition cannot be satisfied before the chosen moment.
|
|
|
|
|
|
2. **Confidentiality from the operator.** DateKeys does not need the plaintext or the final access credential.
|
|
|
|
|
|
3. **Local verifiability.** The SDK detects tampered conditions, profiles and releases.
|
|
|
|
|
|
4. **Integrity.** Changes to the framing, header, control or payload cause failure.
|
|
|
|
|
|
5. **Interoperability.** Independent implementations produce and consume compatible objects.
|
|
|
|
|
|
6. **Independent recovery.** If the provider keeps or can serve the release, the ciphertext is still available and the credentials exist, a mature object should open without the DateKeys API.
|
|
|
|
|
|
7. **Extensibility.** New providers and extensions do not redefine old objects.
|
|
|
|
|
|
8. **Metadata privacy.** Before the date, a format 2 or 3 capsule does not reveal the exact content length or the number of credentials. Format 3 also hides paths, sizes, hashes, dates, comment, declared author and the number of files beyond the bound given by the padding (§55.2).
|
|
|
|
|
|
9. **Optional authenticity.** A format 3 capsule may carry signatures from one or more signers and a time seal. The opener can check that those signers signed this content for this control and, with a seal, that the signature existed before the capsule could be opened (§29.8 to §29.11). Without a signature, a capsule proves no authorship (§36.1).
|
|
|
|
|
|
|
|
|
|
|
|
The completeness review of 29 September 2026 noted that these goals are informal; there is no formal security model or proof (see `scope_and_questions.md`).
|
|
|
|
|
|
|
|
|
|
|
|
## 3. Non-goals (§5)
|
|
|
|
|
|
|
|
|
|
|
|
The base protocol does not guarantee:
|
|
|
|
|
|
|
|
|
|
|
|
- the perpetual existence of Quicknet;
|
|
|
|
|
|
- the perpetual preservation of the release history;
|
|
|
|
|
|
- post-quantum resistance of the V1 timelock;
|
|
|
|
|
|
- revocation of a copy already distributed;
|
|
|
|
|
|
- absolute anonymity;
|
|
|
|
|
|
- hiding the unlock date, the access policy, `capsule_id` or the padded content size (§55.2);
|
|
|
|
|
|
- legal authorship through metadata;
|
|
|
|
|
|
- evidential creation date, except existence before an instant proven by a time seal (§29.11);
|
|
|
|
|
|
- legal validity of a certificate signature: trust in its chain, revocation and qualification are for an external validator (§29.10);
|
|
|
|
|
|
- protection against an already compromised device;
|
|
|
|
|
|
- control of the plaintext after a legitimate decryption;
|
|
|
|
|
|
- **(v0.14)** that a capsule will open: before the date nobody, the recipient included, can check that its content is what is claimed, that a credential opens it, or that it was written so that it can open (§36.1). A capsule alone cannot prove a bid, a prediction or a commitment before the date;
|
|
|
|
|
|
- **(v0.14)** expiry: an opened capsule does not close, and its content is not erased after the date;
|
|
|
|
|
|
- **(v0.14)** conditions other than a round: an event, a vote or the absence of a signal;
|
|
|
|
|
|
- **(v0.14)** cancellation: the creator cannot prevent or delay opening at the date.
|
|
|
|
|
|
|
|
|
|
|
|
Out of scope (§6): where a `.dkc` is stored, how it is discovered or distributed, availability policies, external naming, delivery of a `.dkk`, the `.dkc` file name and its file-system dates.
|
|
|
|
|
|
|
|
|
|
|
|
## 4. Adversaries (§7)
|
|
|
|
|
|
|
|
|
|
|
|
### 4.1 DateKeys server (§7.1)
|
|
|
|
|
|
|
|
|
|
|
|
May try to return a past round, a fake profile or invalid releases; correlate queries; serve stale data; keep copies of the ciphertext. Defences: local round resolution and the past-round check (§15, §17), the pinned profile (§12, §13), local BLS verification (§51), the Release API being keyed by round and not by capsule (§45).
|
|
|
|
|
|
|
|
|
|
|
|
### 4.2 Relay, MITM, DNS (§7.2, §52)
|
|
|
|
|
|
|
|
|
|
|
|
May spoof endpoints, modify, delay or deny responses. Controlling DNS, TLS termination or a relay must not allow a valid release to be forged while the root of trust is pinned, the expected condition is computed locally and the signature is verified (§52). Availability is not protected; the implementation SHOULD support several independent relays (§48).
|
|
|
|
|
|
|
|
|
|
|
|
### 4.3 Holder of a `.dkc` (§7.3)
|
|
|
|
|
|
|
|
|
|
|
|
May modify, truncate or reorder bytes; swap headers, controls or payloads; change the declared policy; attempt downgrade; build a format 3 capsule with paths that escape the reader's folder or collide on extraction, confusable names, a head that exhausts memory, or a comment that imitates a verdict; put in the public note a text that imitates a verdict, an author or a warning, or change it after writing. Defences: header_binding (§26), the I_PAYLOAD binding (§30.1), the stanza cardinality rules (§27), the version of CONTROL_CBOR against the format (§31, §70), the path and text rules (§29.5, §29.6), presentation rules (§29.7, §24.1), the mutation corpus (§64).
|
|
|
|
|
|
|
|
|
|
|
|
### 4.4 Holder of a `.dkk` (§7.4)
|
|
|
|
|
|
|
|
|
|
|
|
Must be treated as holding a sensitive capability. The `.dkk` is 32 raw bytes with no MAC or signature (§38, §55.1).
|
|
|
|
|
|
|
|
|
|
|
|
### 4.5 Supply chain (§7.5, §59)
|
|
|
|
|
|
|
|
|
|
|
|
A compromised SDK or dependency can replace the root of trust, accept false conditions, exfiltrate secrets or weaken the cryptography. §59 lists SHOULD measures: pinned crypto dependencies, SBOM, signed releases, published hashes, signed profiles, reproducible builds, fuzzing, published vectors, and an external cryptographic review of v1.0.
|
|
|
|
|
|
|
|
|
|
|
|
### 4.6 Provider (§7.6) (v0.14)
|
|
|
|
|
|
|
|
|
|
|
|
A `time_only` capsule depends on a single provider (Quicknet in V1) and has no other way to open: no DateKeys key, recovery or service opens it before or after the date. Two separate things depend on the provider:
|
|
|
|
|
|
|
|
|
|
|
|
- **Confidentiality until the date.** If as many drand members as the threshold requires collude, or their key shares end up in the same hands, a future round can be signed early, and with it every capsule of that round or earlier can be opened before the date.
|
|
|
|
|
|
- **Opening after the date.** If the network stops signing before a capsule's round, nobody can ever open it. If it signs the round but nobody keeps the release, opening depends on finding it (§50).
|
|
|
|
|
|
|
|
|
|
|
|
A `time_and_key` capsule adds a credential the provider does not have: an early signature of the round is not enough, but a missing round leaves it just as closed (§36.1). The official SDK SHOULD recommend it for long horizons or valuable content. A pinned profile is identified by its `profile_hash`; a provider that changes key, period or chain is another profile, and existing capsules still depend on the old one.
|
|
|
|
|
|
|
|
|
|
|
|
Profile registry states (§71, v0.14): `activo` (write and open); `solo lectura` (no new capsules; existing ones still open); `comprometido` (evidence that confidentiality failed; existing capsules still open; the SDK SHOULD warn that the content may have been read before the date). A published entry is never removed.
|
|
|
|
|
|
|
|
|
|
|
|
### 4.7 Future quantum adversary (§7.7, §53) (v0.14 extended)
|
|
|
|
|
|
|
|
|
|
|
|
- The Quicknet V1 timelock is not post-quantum; there is a harvest-now, decrypt-later risk for long-lived ciphertexts.
|
|
|
|
|
|
- **(v0.14)** Neither are the X25519 recipients (§37), the Ed25519, ECDSA and RSA author signatures (§29.9, §29.10), or the signatures of time-stamping authorities (§29.11). Over a long horizon, a quantum adversary could forge after the date a signature and a seal that verify, with a time before the round: a verdict F3, F4, F6 or S4 read decades later proves less than the same verdict read soon. Archive re-seals (RFC 4998) are outside the capsule.
|
|
|
|
|
|
- §55.2: decoy indistinguishability rests on Diffie–Hellman in X25519 and does not resist a future quantum adversary, who could recover ephemeral scalars and test candidate public keys.
|
|
|
|
|
|
- The official SDK SHOULD warn about long horizons (§53). A post-quantum access type is future work (§74).
|
|
|
|
|
|
|
|
|
|
|
|
### 4.8 Creator's device (§7.8)
|
|
|
|
|
|
|
|
|
|
|
|
If compromised before or during encryption, the protocol cannot prevent copying of the plaintext or secrets. §55.2 adds that nobody can check that a writer discarded decoy private keys: a compromised SDK or device could keep one as a hidden credential.
|
|
|
|
|
|
|
|
|
|
|
|
### 4.9 Signers and time-stamping authorities (§7.9)
|
|
|
|
|
|
|
|
|
|
|
|
With a signature or seal in format 3:
|
|
|
|
|
|
|
|
|
|
|
|
- whoever steals a signer's secret key can sign in their name; a signature with a key of one's own does not prove who holds the key;
|
|
|
|
|
|
- a writer can create two different capsules with the same `capsule_id`, both signed (equivocation); the creator can publish `capsule_digest` before the date against it (§43);
|
|
|
|
|
|
- whoever can open a capsule can remake it after the date with another area, without a signature or with another; only a seal earlier than the round proves a signature existed before the date;
|
|
|
|
|
|
- a dishonest or compromised TSA can misdate its seals; the protocol does not audit it, and the verdict names it;
|
|
|
|
|
|
- the external signing application receives AUTHOR_MESSAGE, which does not reveal the content; a compromised page or fake signing application can obtain a signature for a capsule the signer has not seen; a co-signing organisation that signs only AUTHOR_MESSAGE never sees the content. The AUTHOR_MESSAGE code lets the signer compare what is signed with what DateKeys shows;
|
|
|
|
|
|
- a signer may sign under coercion, and the signature does not show it;
|
|
|
|
|
|
- a stolen author key cannot be revoked: a reader that saved it keeps showing its label;
|
|
|
|
|
|
- DateKeys does not check who issued a certificate or a seal: anyone can make a certificate in another's name or a seal with any date; an official validator checks them with the evidence the capsule keeps.
|
|
|
|
|
|
|
|
|
|
|
|
### 4.10 Web client (§7.10, §59) (v0.14)
|
|
|
|
|
|
|
|
|
|
|
|
A client the browser downloads on each visit, such as a page that encrypts or opens capsules, can be replaced by whoever serves the page, controls its domain or compromises its build. A replaced client can copy the content, the credentials and the words of a key before encrypting or after opening, or write a capsule that will not open. No format rule detects it: the capsule it writes is valid. §59 asks (SHOULD) for reproducible builds with published hashes, Subresource Integrity on every script, a content policy that loads no code from another origin, and the same client usable offline.
|
|
|
|
|
|
|
|
|
|
|
|
## 5. Authenticity semantics (§36.1)
|
|
|
|
|
|
|
|
|
|
|
|
- `time_only` provides **no creator authenticity**, before or after maturity, unless an author signature (§29.8) or a signature extension adds it.
|
|
|
|
|
|
- Forgery is possible from creation time: encrypting to a future round needs only the profile's public key and the public condition. header_binding is computed from public bytes only. A third party can build another CONTROL_CBOR with a correct header_binding, its own I_PAYLOAD and PAYLOAD_AGE, and seal it to the same DateKey without waiting.
|
|
|
|
|
|
- So `capsule_id`, the DateKey and header_binding give **internal coherence**, not authorship.
|
|
|
|
|
|
- `time_and_key` adds an access barrier: a third party without the required identity cannot open INNER_ACCESS_AGE, even with an early round signature from a compromised provider (§7.6). It does **not** replace a creator signature.
|
|
|
|
|
|
- Decoys add no access barrier and no authenticity.
|
|
|
|
|
|
- In format 3, the declared author is creator text. A valid signature proves that its signers signed this content for this control, not who created the `.dkc`: after the date, whoever can open the capsule can remake it without the signature or with another. Only a seal earlier than the round proves the signature existed before the date.
|
|
|
|
|
|
|
|
|
|
|
|
## 6. Auxiliary integrity and trust per section (§55, §55.1)
|
|
|
|
|
|
|
|
|
|
|
|
Public hashes MAY be used for identification, caching, deduplication, audit and UX; they do not replace the age header MAC, X25519 wrapping, tlock, STREAM authentication or header_binding (§55).
|
|
|
|
|
|
|
|
|
|
|
|
§55.1 is normative: an implementation MUST NOT present a section as proof of something its "never proves" column excludes, unless a valid signature or seal of `security`, or a signature extension, covers it.
|
|
|
|
|
|
|
|
|
|
|
|
| Section | Who can write it | Bound from step, by | Never proves |
|
|
|
|
|
|
|---|---|---|---|
|
|
|
|
|
|
| PRELUDE and PUBLIC_HEADER | Anyone with the `.dkc`: in clear, no key protects them | Step 15: header_binding inside CONTROL_CBOR covers their exact bytes. Steps 1–8 check only structure | Authorship or creation date. Before step 15, not even coherence with the control |
|
|
|
|
|
|
| CONTROL_CBOR | Anyone can seal a control to the DateKey (only the profile's public key is needed). In `time_and_key`, one that a given credential opens only someone who knows its recipient's public key | Step 11: age MAC and STREAM of OUTER_TIME_AGE (and INNER at step 13) against whoever does not know the file key. Step 15: header_binding | That the creator of PUBLIC_HEADER wrote it. After opening, whoever knows FK_TIME or FK_ACCESS can rewrite it |
|
|
|
|
|
|
| PAYLOAD_AGE | Whoever knows R_PAYLOAD: before opening, only the sealer of the control; after, anyone who obtained I_PAYLOAD | Step 17: I_PAYLOAD unwraps FK_PAYLOAD; MAC and STREAM authenticate every byte. Formats 2 and 3: L and the code fix length and padding | Authorship; that it is still the original payload after someone opened the capsule; that L is the original length (another L of the same P can be declared) |
|
|
|
|
|
|
| Format 3 content: security, head, files | Whoever writes PAYLOAD_AGE | Step 17: MAC and STREAM of PAYLOAD_AGE; the head fixes size and SHA-256 per file | Authorship or date: declared author, comment, paths and mtimes are creator text. `security` proves only what its verdicts say |
|
|
|
|
|
|
| `.dkk` body | Anyone with the `.dkk`: no MAC or signature | Step 9.a: its `capsule_id` must equal the header's (a public value); its `capsule_digest`, if present and checked, binds it to exact `.dkc` bytes. Step 13: `access_material` opens INNER only if it is one of its recipients | That the capsule creator issued it. Its extension data is bound to nothing |
|
|
|
|
|
|
|
|
|
|
|
|
A security decision of the reader (authorisation, identity, integrity or date) cannot rest on PUBLIC_HEADER or a `.dkk` without a signature covering them.
|
|
|
|
|
|
|
|
|
|
|
|
## 7. Privacy (§55.2)
|
|
|
|
|
|
|
|
|
|
|
|
Formats 2 and 3 (format 1 reveals more):
|
|
|
|
|
|
|
|
|
|
|
|
- **Visible to any holder, before and after the date:** VERSION, PUBLIC_HEADER_LEN, SEALED_CONTROL_LEN; `capsule_id`; the DateKey (profile, round, unlock instant); `access_policy`; PUBLIC_HEADER extensions with their data, the public note included; the tlock stanza (round and chain hash); the PAYLOAD_AGE header and its length, which gives P exactly; the length of CONTROL_CBOR (103 bytes plus extensions), which does not depend on L or the number of credentials. In format 3 with a 32 KiB area and few files, P also bounds the number of files: n ≤ (P − 32835)/45, at most 44 files with P = 34 816. P sometimes reveals the `bloque256` code.
|
|
|
|
|
|
- **Hidden until the date:** the content and its exact length L; the padding code (except what P reveals); I_PAYLOAD and all of CONTROL_CBOR; in format 3, `security`, the head and the files; in `time_and_key`, the number of credentials and the INNER header.
|
|
|
|
|
|
- **After the date:** `time_only`: anyone reads everything. `time_and_key`: anyone sees the INNER header with 16 stanzas; CONTROL_CBOR and the content stay hidden from those without a credential; a credential holder learns which stanza is theirs but not which of the other 15 are decoys; several credential holders together learn only a lower bound on the number of credentials.
|
|
|
|
|
|
- **Never visible** (under Diffie–Hellman in X25519): the recipients; whether a stanza is a decoy; whether a portable `.dkk` exists; the number of credentials beyond the lower bound above.
|
|
|
|
|
|
- **Signature and seal:** before the date, whether a capsule is signed is hidden while it uses the common 32 KiB area; a 64 KiB area reveals it; a v0.10 capsule with a 512-byte area reveals it carries no seal when P is small. Signers and TSA names are visible after the date (to anyone in `time_only`), including a signer's national identifier in the certificate. OCSP requests, often over unencrypted HTTP, reveal the certificate serial number; a writer that uses an intermediary for OCSP or the seal MUST declare it.
|
|
|
|
|
|
- **Outside the `.dkc`:** a `.dkk` carries the credential in clear, plus `capsule_id`, `credential_id`, the optional `capsule_digest` and extension data; `datekeys.capsule` carries the note and the date in clear and the locator encrypted to the date; the host of an envelope rest sees random bytes and their size; fetching a release reveals the profile, round and requester address to the API and relays, not `capsule_id`.
|
|
|
|
|
|
- **Format 1:** SEALED_CONTROL_LEN grows 98 bytes per INNER stanza, and the PAYLOAD_AGE length gives L exactly.
|
|
|
|
|
|
|
|
|
|
|
|
## 8. Things the specification already says are not checked
|
|
|
|
|
|
|
|
|
|
|
|
These are stated limits, not findings:
|
|
|
|
|
|
|
|
|
|
|
|
- Before the date nobody can check that a capsule will open (§5, v0.14).
|
|
|
|
|
|
- Nobody can check that decoy private keys were discarded (§55.2).
|
|
|
|
|
|
- The locator is not authenticated against whoever wrote the `.dkk` (§44.1).
|
|
|
|
|
|
- A writer with a clock running late can seal to an already published round; comparing with the last published round is only a MAY (§62.1 rule 2).
|
|
|
|
|
|
- The `.dkk` has no integrity check of its own (§55.1).
|
|
|
|
|
|
- DateKeys never checks who issued a certificate or a seal (§29.10, §29.11).
|