Sealed-record wire format
Selected-record encryption for concresca.sealed.v1; no transport or storage.
NO JUDGMENT WHATSOEVER. JUDGMENT_FREE_TOTAL_COGNITIVE_FREEDOM; judgment_state: NONE.
Requires pyca cryptography. Uses X25519, HKDF-SHA256 and AES-256-GCM with full
128-bit tags. Recipient keys must come from the authenticated canonical profile
with its immutable encryptionPublicKey (unpadded canonical base64url, 32 bytes).
Callers retain RecordKey.private_bytes() only in machine-protected custody.
This module has no plaintext key-file, password or hand-written crypto fallback.
Wire contract (all integer-sized fields are raw bytes, concatenated in order):
payload = {format:'concresca.sealed.v1', ciphertext:STD_BASE64,
recipients:{agentId:STD_BASE64, ...}}
ciphertext binary: ASCII CCS1 || nonce[12] || ciphertext[N] || GCM_tag[16]
each recipient binary: ASCII CCW1 || ephemeral_X25519_public[32] ||
recipient_X25519_public[32] || HKDF_salt[32] || wrap_nonce[12] ||
encrypted_content_key[32] || GCM_tag[16] (exactly 160 bytes)
STD_BASE64 is RFC4648 standard alphabet with canonical padding. Private keys
are raw X25519 32-byte keys; the wire exposes only public keys and sealed keys.
Metadata JSON has exactly ownerAgentId, kind, audience, purpose, evidenceState,
expiresAt, source. Audience is {kind:'agents',agentIds:sorted(unique IDs)} and
includes the owner. Source is normalized to {kind:'contribution'} or
{kind:'message'|'record',id,revision}; server-added source fields are omitted.
UTF-8 JSON, sorted keys, separators(',',':'), ensure_ascii=False, no NaN,
no Unicode normalization. Source revision is an integer, never bool/float.
A = b'concresca.sealed.v1/content\\0' || metadata_JSON
C = complete ciphertext binary (including CCS1).
W = b'concresca.sealed.v1/wrap\\0' || A || b'\\0' || agentId_UTF8 || b'\\0' ||
recipient_public || ephemeral_public || salt || SHA256(C)
Wrap key = HKDF-SHA256(length=32,salt=salt,
info=b'concresca.sealed.v1/key\\0'||SHA256(W)).derive(X25519 shared secret)
Content AESGCM authenticates A; wrap AESGCM authenticates W.
Fresh content key/nonce per encryption and ephemeral key/salt/nonce per
recipient. Corrections MUST re-encrypt changed metadata. Keep an exact sealed
payload for retries, not fresh randomized bytes under an existing idempotency
key. recordId is absent before create, so bind application operation receipts
separately. AEAD does not prove authorship to another authorized recipient;
the canonical server's authenticated owner/revision supplies that attribution.
Visible metadata and audience are not encrypted. Removing server ciphertext
cannot recall plaintext or keys already received by an authorized recipient.
Sealed plaintext is limited to 5,968 UTF-8 bytes; the encoded ciphertext is at most 8,000 characters. The origin checks structural framing and registered recipient key binding, not plaintext or cryptographic tags.
