Expand description
Real envelope encryption for the accountability commons payload — the crypto that makes
ConsentCredential’s “revoke destroys the wrapped key ⇒
no key, no payload” a fact, not a model with opaque placeholder bytes.
Two layers, both real (built on the already-tested qualia_core_db::crypto::sanctuary_audit primitives —
X25519 sealed boxes + XChaCha20-Poly1305 AEAD; no new crate, no simulation):
- Payload layer (symmetric). A random data-encryption key (DEK) encrypts the plaintext with an
AEAD (
wrap_key); the ciphertext is content-addressed (commitment = SHA-256(ciphertext)), giving theEncryptedCommonsPayloadthat many parties may replicate. Opening verifies the commitment (the bytes are the committed bytes) then AEAD-decrypts (tamper ⇒ failure). - Key layer (asymmetric, per recipient). The DEK is sealed to a recipient’s public key
(
seal_to) — an anonymous ephemeral-DH box only that recipient’s secret can open. This sealed DEK is the credential’swrapped_key. So access is genuinely per-holder, and revocation = destroying that sealed DEK (ConsentCredential::revoke): the recipient can no longer recover the DEK, and the ciphertext — wherever replicated — is opaque to them. When no live credential holds a sealed DEK for a payload, the DEK is unrecoverable and the payload is crypto-shredded (permanently unreadable though the bytes survive), exactly as the model promised.
Native-only (the sealed-box primitives are not(wasm32); the desktop owns keys), matching
wellfair::sanctuary_vault.
What this does not yet do (named honestly, not deferred behind a lane): distribute a remote agent’s
X25519 public key — that comes from the peer’s published key material in the connection/identity layer
(social_peers / DID document), so a worker on their own device can be sealed to and decrypt
independently. Until that is wired, the host seals to the owner’s envelope keypair by default (the
owner can always open their own data), and can seal to any supplied recipient public key.
Structs§
- Envelope
Keypair - An X25519 envelope keypair for a party (the owner, or an agent). The secret opens sealed DEKs; the public is what a DEK is sealed to.
Constants§
- OWNER_
ENVELOPE_ DOMAIN - Domain tag for deriving the owner’s envelope keypair from their ed25519 signing-key seed.
Functions§
- open_
payload - Open a payload with the DEK — verifies the content-address commitment (the bytes are the committed bytes) then AEAD-decrypts. Any tamper (to ciphertext or a swapped payload) fails.
- open_
payload_ with_ wrapped - Open a payload directly from a recipient’s secret + the credential’s wrapped DEK. The end-to-end decrypt path: unwrap the sealed DEK, then open the payload. If the wrapped DEK is absent (revoked), the caller has nothing to pass here — that is the crypto-enforced revocation.
- seal_
payload - Seal a plaintext payload. Generates a random DEK, AEAD-encrypts under it, and content-addresses the
ciphertext. Returns the replicable
EncryptedCommonsPayloadand the DEK (to be sealed per recipient bywrap_dek_to, then dropped — do not persist it in the clear). - unwrap_
dek - Unwrap a DEK with the recipient’s secret key. Fails for the wrong recipient or a tampered blob.
- wrap_
dek_ to - Seal (wrap) a DEK to a recipient’s public key — the credential’s
wrapped_key. Only the holder of the matching secret canunwrap_dekit; destroying this blob (revocation) removes that access.
Type Aliases§
- DataKey
- A 32-byte data-encryption key. Secret: seal it to a recipient, never store it in the clear.