Bucket Keys
This page focuses on bucket DEKs and bucket-key lifecycle. For the full key inventory, including user keys, node keys, record DEKs, and envelopes, see Key Model.
NOOSChain supports two bucket encryption modes.
per_record_key: every encrypted record uses a fresh random DEK. The record stores encrypted key envelopes for that record DEK.per_bucket_key: the bucket has one active encrypted bucket DEK reference. Records are encrypted with the active bucket key and storebucketKeyId/bucketKeyVersion; record-level key envelopes are normally empty.
Bucket keys are consensus state. CREATE_BUCKET_KEY creates version 1 for a per_bucket_key bucket. ROTATE_BUCKET_KEY creates the next version and marks the previous active key as rotated. Old records stay pinned to the key version used when they were created; NOOSChain does not re-encrypt historical records in this MVP.
Plaintext DEKs are never persisted. bucket_keys.key_envelopes stores encrypted DEK envelopes for authorized recipients. The development server helper may accept bucketDekBase64 to create envelopes or encrypt a payload, but that is disabled in production-mode flows and exists only for MVP/dev testing. Production deployments should use client-side encryption or KMS/HSM-backed key operations.
Bucket-key transactions require bucket:admin, and signer creator fields must match the signer identity unless the actor is system. Record writes still require bucket:write.
Bucket-key envelope recipients are validated during CREATE_BUCKET_KEY and ROTATE_BUCKET_KEY. User envelopes must target the creator user or a principal with bucket:read_encrypted or bucket:admin. Organization envelopes follow the bucket replication strategy:
metadata_onlyrejects organization key sharing for node replication;replicate_encrypted_to_authorized_nodesallows the creator organization and organizations withbucket:read_encryptedorbucket:admin;replicate_encrypted_to_all_nodesallows organizations that own active registered nodes.
Bucket-key state hashes include key id, bucket id, version, status, algorithm, normalized encrypted key envelopes, creator identity, and transaction hash. They never include plaintext key material.
Key envelopes for bucket keys expose recipient ids and recipient public keys as metadata. They do not expose the plaintext bucket DEK; only a holder of the matching private key can unwrap the encrypted DEK. Because envelope metadata is consensus state, all synced nodes can replay and see the encrypted envelope list, but replication APIs only provide ciphertext and bucket-key material to nodes whose verified organization is allowed by the bucket replication policy.
Removing access from an organization prevents that organization from appearing in new bucket-key versions, but existing key versions can remain decryptable by old envelope recipients. To cryptographically remove future decryptability for a per_bucket_key bucket, remove the access rule and rotate the bucket key with envelopes that exclude the removed organization.
The integration test environments assert the key-mode boundaries directly. Per-record-key records must not reference bucket_key_id / bucket_key_version; record-level key envelopes are the normal production shape, but the current transaction schema still permits an empty array for compatibility with older/dev fixtures. Per-bucket-key records must have a bucket key reference and normally use empty record-level key envelopes. Rotation must mark the old bucket key as rotated, make the new version active, keep old records decryptable with the old key envelope, and encrypt new records with the new key envelope. The tests also probe API responses, canonical transaction envelopes, bucket_keys, and encrypted_records rows to ensure the raw bucket DEK supplied to dev helpers is not stored or returned.
TODO: add an explicit historical rekey/re-encryption workflow for per_bucket_key buckets. Current ROTATE_BUCKET_KEY is forward-only: it changes the active DEK for future records but does not rewrite existing ciphertext. A future workflow should authorize a bucket admin to decrypt old records client-side or via KMS/HSM, re-encrypt them under the new active bucket DEK, write deterministic rekey transactions, preserve audit history, and verify that plaintext key material still never enters consensus state or ordinary database storage.