aeat.adapters.persistence.storage.master_key._recovery_facade module¶
Typed BIP-39 recovery facade for the per-bucket unlock pipeline.
The substrate’s BIP-39 mnemonic encoding, HKDF-derived recovery KEK, and AES-256-GCM wrap of the master DEK live in _recovery.py. This module exposes a typed boundary over those primitives so callers consume and produce the strict pydantic v2 records (RecoveryRecord for the on-disk envelope, BucketSession for the live in-memory state) without reaching into the substrate. The internals never leave _recovery.py.
mint_recovery_envelope is called at enrollment: it generates a fresh 24-word BIP-39 mnemonic, derives the recovery KEK from the entropy, wraps the supplied DEK under that KEK, and returns the RecoveryRecord + the plaintext mnemonic (the only in-memory copy; the caller arranges for the operator to copy it down).
unwrap_recovery_envelope is called at recovery: it accepts the mnemonic the operator typed, decodes the entropy, derives the recovery KEK, and decrypts the wrapped DEK from the RecoveryRecord. The plaintext mnemonic is never persisted.
open_session_from_recovery composes unwrap_recovery_envelope with BucketSession.open so the recovery-flow CLI verb yields a live session the wizard can re-wrap under a fresh passphrase-derived KEK.
- class MintedRecovery(**data)[source]¶
Bases:
BaseModelIn-memory result of a recovery enrollment.
The mnemonic is the only handle on the recovery KEK; the caller arranges for the operator to copy it before this record falls out of scope.
- Parameters:
envelope (RecoveryRecord)
mnemonic (str)
- envelope: RecoveryRecord¶
- mnemonic: str¶
- mint_recovery_envelope(*, dek, created_at)[source]¶
Mint a fresh
MintedRecoveryenvelope wrappingdek.Returns a
MintedRecoverycarrying the typedRecoveryRecordand the 24-word mnemonic the operator must record. The mnemonic is the only handle on the recovery KEK; this function does NOT persist it.- Return type:
- Parameters:
- unwrap_recovery_envelope(*, envelope, mnemonic, decoder=None)[source]¶
Decode
mnemonicand unwrapenvelopeto recover the 32-byte DEK.- Parameters:
envelope (
RecoveryRecord) – The persistedRecoveryRecordto unwrap.mnemonic (
str) – The 24-word BIP-39 mnemonic supplied by the operator.decoder (
Callable[[str],bytes] |None) – Optional override for mnemonic decoding; production callers omit it.
- Return type:
- Returns:
The recovered 32-byte data-encryption key.
- Raises:
RecoveryVerificationError – When the mnemonic does not decode or the AEAD tag check fails.
- verify_recovery_mnemonic(*, envelope, mnemonic)[source]¶
Return True iff the mnemonic correctly unwraps the envelope.
Used by the aeat config verify-recovery periodic-custody-test verb. Catches RecoveryVerificationError and surfaces a boolean so the CLI renders the outcome without leaking detail.
- Return type:
- Parameters:
envelope (RecoveryRecord)
mnemonic (str)
- save_recovery_envelope(envelope, path)[source]¶
Atomically persist a typed recovery envelope.
- Return type:
- Parameters:
envelope (RecoveryRecord)
path (Path)
- load_recovery_envelope(path)[source]¶
Read, validate, and return a
RecoveryRecordfrompath.- Return type:
- Parameters:
path (Path)
- open_session_from_recovery(*, bucket_id, envelope, mnemonic, kek, idle_minutes, opened_at)[source]¶
Compose mnemonic-unwrap with BucketSession.open and return a
BucketSession.The caller supplies the freshly-derived passphrase KEK (the operator’s new passphrase, run through Argon2id under a fresh salt); the function unwraps the DEK from the recovery envelope and yields a live session bound to bucket_id.
- Return type:
- Parameters: