aeat.adapters.persistence.storage.master_key._dek_wrap module

AES-256-GCM wrap and unwrap of the per-bucket data-encryption key.

The substrate wraps a freshly-generated 32-byte data-encryption key (DEK) under a passphrase-derived 32-byte key-encryption key (KEK) using AES-256-GCM. The wrap binds to the bucket id through AEAD additional-authenticated-data (AAD), so the wrapped DEK from one bucket cannot be silently swapped under another bucket’s manifest at unlock.

The on-wire shape is the typed WrappedDek record carrying:

  • nonce 12 random bytes produced afresh at every wrap.

  • ciphertext 32 bytes of AES-256-GCM ciphertext.

  • tag 16 bytes of AES-256-GCM authentication tag.

unwrap_dek raises a typed storage DecryptionError on AEAD failure.

class WrappedDek(**data)[source]

Bases: BaseModel

Frozen AES-256-GCM envelope around one bucket’s data-encryption key.

Parameters:
nonce: bytes
ciphertext: bytes
tag: bytes
wrap_dek(*, kek, dek, bucket_id)[source]

Wrap dek under kek using AES-256-GCM keyed to bucket_id.

Parameters:
  • kek (bytes) – 32-byte key-encryption key derived from the operator’s passphrase via Argon2id.

  • dek (bytes) – 32-byte data-encryption key minted afresh at enrollment.

  • bucket_id (str) – Non-empty bucket identifier; bound into the AEAD AAD so the wrapped DEK cannot be re-mounted under a different bucket.

Return type:

WrappedDek

Returns:

A frozen WrappedDek record carrying nonce, ciphertext, and tag.

Raises:

EncryptionError – If kek or dek is not 32 bytes, or bucket_id is empty.

unwrap_dek(*, kek, wrapped, bucket_id)[source]

Recover the 32-byte DEK from wrapped under kek and bucket_id.

Parameters:
  • kek (bytes) – 32-byte key-encryption key.

  • wrapped (WrappedDek) – Typed envelope produced by wrap_dek.

  • bucket_id (str) – Non-empty bucket identifier; must match the value bound at wrap time.

Return type:

bytes

Returns:

The 32-byte data-encryption key.

Raises: