pub struct KeyVault { /* private fields */ }Expand description
In-memory key vault.
The vault is the entry point for everything key-vault does. Application
code constructs one via KeyVaultBuilder, hands it RawKey values
to be fragmented, and (in later phases) receives
KeyHandles in return. The vault itself is cheap to
clone (it is Arc-backed internally) and safe to share across threads.
In Phase 0.3 the vault exposes KeyVault::fragment and
KeyVault::defragment convenience methods that route through the
configured normalizer and StandardFragmenter. The full named-key
registry arrives in Phase 0.9.
Implementations§
Source§impl KeyVault
impl KeyVault
Sourcepub fn is_locked_out(&self) -> bool
pub fn is_locked_out(&self) -> bool
Returns true if the vault is in lock-out state.
Lock-out is triggered by the threshold detector when
KeyVault::report_failure reports more failures than
VaultConfig::max_failures_before_lockout within
VaultConfig::failure_window. Once set, KeyVault::fragment
and KeyVault::defragment refuse to proceed and return
Error::LockedOut. Use
KeyVault::clear_lockout to reset.
Sourcepub fn clear_lockout(&self)
pub fn clear_lockout(&self)
Clear the lockout flag.
Use this after the operator has resolved the underlying cause — e.g. a rotated credential, an investigated alert. Also clears the failure tracker; subsequent failures start counting from zero.
Sourcepub fn report_failure(&self, key_name: &str, note: Option<&'static str>)
pub fn report_failure(&self, key_name: &str, note: Option<&'static str>)
Report a key-access failure to the configured monitor and the threshold detector.
key_name identifies which key the failure pertains to (used for
per-key threshold tracking and in the monitor event). note is
an optional caller-supplied free-text label; pass None if you
don’t have one. Do not include key bytes or other secrets in
the note — it is forwarded verbatim to every configured monitor.
If the per-key failure count within
VaultConfig::failure_window reaches
VaultConfig::max_failures_before_lockout, the vault transitions
to lock-out state and the monitor’s on_threshold_breach callback
fires. A max_failures of 0 disables threshold lockout — only
the per-failure callback runs in that case.
Sourcepub fn report_anomalous_access(
&self,
key_name: &str,
note: Option<&'static str>,
)
pub fn report_anomalous_access( &self, key_name: &str, note: Option<&'static str>, )
Report an anomalous (but successful) key access to the monitor.
Useful for “this access pattern looks weird, but we’re not going
to refuse it” cases — unusual time of day, geographic anomaly,
caller identity that hasn’t been seen before. The monitor receives
an AccessContext; the vault state is unaffected.
Sourcepub fn config(&self) -> &VaultConfig
pub fn config(&self) -> &VaultConfig
Snapshot of the vault’s configuration.
Sourcepub fn fragment(&self, key: &RawKey) -> Result<Fragments>
pub fn fragment(&self, key: &RawKey) -> Result<Fragments>
Fragment a raw key through the configured normalizer, codex, and fragmenter.
The returned Fragments is opaque; pass it back to
KeyVault::defragment to recover the (normalized + codex-encoded)
bytes inverse-transformed.
§Pipeline
key → blake3_normalize (optional) → codex.encode (optional) → fragmenter.fragment → Fragments§Errors
Returns whatever the underlying FragmentStrategy surfaces — in
practice an Error::Fragment for a
zero-length input.
Sourcepub fn defragment(&self, fragments: &Fragments) -> Result<RawKey>
pub fn defragment(&self, fragments: &Fragments) -> Result<RawKey>
Reassemble fragments produced by KeyVault::fragment.
Inverts the codex transformation (if configured) so the recovered
bytes are the normalized key (or the original raw key if
normalization is off). Defragmentation itself is delegated to the
configured FragmentStrategy.
§Errors
Returns Error::Defragment when the
supplied fragments do not match the configured fragmenter’s layout.
Sourcepub fn register(
&self,
name: impl Into<String>,
key: RawKey,
) -> Result<KeyHandle>
pub fn register( &self, name: impl Into<String>, key: RawKey, ) -> Result<KeyHandle>
Register a key under a name and return an opaque KeyHandle.
The key bytes are run through the configured normalizer + codex pipeline, fragmented, and inserted into the named registry. The returned handle is the only way to refer to the key from outside the crate; the underlying numeric id is not exposed.
§Errors
Error::LockedOutif the vault is currently locked out (threshold-driven).Error::InvalidConfigif a key with the same name is already registered.- Whatever the configured fragmenter surfaces (typically
Error::Fragmentfor empty input).
Sourcepub fn unregister(&self, handle: KeyHandle) -> Result<()>
pub fn unregister(&self, handle: KeyHandle) -> Result<()>
Remove a registered key from the registry. The key’s Fragments
(and their LockedBytes chunks) drop and zeroize when the last
reference goes away.
§Errors
Returns Error::KeyNotFound if no
key is registered under the given handle.
Sourcepub fn with_key<F, T>(&self, handle: KeyHandle, f: F) -> Result<T>
pub fn with_key<F, T>(&self, handle: KeyHandle, f: F) -> Result<T>
Briefly access the recovered key material inside a callback.
The vault defragments the named key into a temporary RawKey,
applies the codex decode if configured, and passes the bytes to
the user-supplied closure. When the closure returns, the
RawKey drops and its bytes are volatile-zeroed.
The byte slice handed to the closure does not outlive the call. Do not stash it in a longer-lived structure; do your cryptographic operation, return, and let the vault scrub the buffer.
§Errors
Error::LockedOutif the vault is currently locked out.Error::KeyNotFoundif no key is registered under the given handle.Error::Defragmenton internal inconsistency.
Sourcepub fn rotate(&self, handle: KeyHandle, new_key: RawKey) -> Result<()>
pub fn rotate(&self, handle: KeyHandle, new_key: RawKey) -> Result<()>
Rotate a registered key to new material.
The new key is fragmented and atomically swapped into the
registry slot. Concurrent KeyVault::with_key callers see
either the old or the new fragmentation (never a torn read);
the old Fragments drops once all in-flight readers release
their Arc clones.
The metadata is updated to record the new key length and a fresh registration timestamp.
§Errors
Error::LockedOutError::KeyNotFound- Fragmenter errors for the new key.
Sourcepub fn contains(&self, handle: KeyHandle) -> bool
pub fn contains(&self, handle: KeyHandle) -> bool
true if a key is registered under the given handle.
Sourcepub fn metadata(&self, handle: KeyHandle) -> Option<KeyMetadata>
pub fn metadata(&self, handle: KeyHandle) -> Option<KeyMetadata>
Clone the KeyMetadata for the given handle.
Returns None if the handle is not registered. Metadata is a
non-secret descriptor (length, registration time, algorithm
hint) — safe to log and pass around.
Sourcepub fn handle_for_name(&self, name: &str) -> Option<KeyHandle>
pub fn handle_for_name(&self, name: &str) -> Option<KeyHandle>
Find the handle registered under name, if any.
Sourcepub fn unlock_with_master(&self, attempt: &[u8]) -> Result<()>
pub fn unlock_with_master(&self, attempt: &[u8]) -> Result<()>
Attempt to clear the lockout flag using a master credential.
If the vault has a master key registered (via
KeyVaultBuilder::with_master_key) and the supplied bytes
match the stored BLAKE3 digest in constant time, the lockout is
cleared and the failure tracker is reset.
On mismatch, the failure is reported to the monitor under the
reserved key name "<master>" and the lockout (if any) remains
in place. The function never reveals whether the digest matched
through timing — comparison goes through
subtle::ConstantTimeEq.
§Errors
Error::InvalidConfigif no master credential is registered.Error::Acquisitionwith source"master"on mismatch.
Sourcepub fn has_master_key(&self) -> bool
pub fn has_master_key(&self) -> bool
true if a master credential was registered at build time.