pub struct Store { /* private fields */ }Expand description
Local encrypted keystore.
Private keys are encrypted with AES-256-GCM before writing to disk. The encryption key is derived from a machine-specific secret so key files are useless if copied to another machine.
v2 will delegate to OS credential stores (Secure Enclave / TPM 2.0).
Implementations§
Source§impl Store
impl Store
Sourcepub fn open(dir: impl AsRef<Path>) -> Result<Self, KeyError>
pub fn open(dir: impl AsRef<Path>) -> Result<Self, KeyError>
Opens or creates a keystore at dir.
Sourcepub fn generate(&self, set_default: bool) -> Result<KeyInfo, KeyError>
pub fn generate(&self, set_default: bool) -> Result<KeyInfo, KeyError>
Generates a new Ed25519 keypair, encrypts and stores it.
If set_default is true (or there is no current default), makes
this key the default signing key.
Sourcepub fn rotate(
&self,
predecessor_id: Option<&str>,
grace_period: Duration,
set_default: bool,
) -> Result<RotationResult, KeyError>
pub fn rotate( &self, predecessor_id: Option<&str>, grace_period: Duration, set_default: bool, ) -> Result<RotationResult, KeyError>
Rotate the current default key (or a specific key) to a freshly generated successor.
Mints a new Ed25519 keypair, links the predecessor to it via
successor_key_id, and stamps the predecessor with a valid_until
of now + grace_period. The grace window lets verifiers continue to
accept signatures from the predecessor while clients catch up to
the new public key.
If set_default is true (the typical case – you rotate because you
want to start signing with the new key immediately), the successor
becomes the default. Pass false to stage a rotation for review
without flipping the active signer.
predecessor_id may be None to rotate the current default. Pass
an explicit id to rotate a non-default key (e.g. a per-environment
secondary).
Note on threat model: this is a graceful rotation primitive, not a
revocation primitive. If the predecessor key is suspected compromised
the grace_period should be Duration::ZERO (or use a future
revoke() call once that lands) so the predecessor’s valid_until
is in the past and any verifier honoring the metadata refuses
further signatures from it.
Sourcepub fn successor_chain(&self, id: &str) -> Result<Vec<KeyId>, KeyError>
pub fn successor_chain(&self, id: &str) -> Result<Vec<KeyId>, KeyError>
Walk the rotation chain forward from id, returning the ordered
list of key ids: [id, successor_of_id, ...]. The first element is
always id itself. Stops at a key with no successor_key_id.
Sourcepub fn valid_keys_at(&self, at_unix_secs: u64) -> Result<Vec<KeyInfo>, KeyError>
pub fn valid_keys_at(&self, at_unix_secs: u64) -> Result<Vec<KeyInfo>, KeyError>
Returns the KeyInfo for every key whose valid_until is either
unset or strictly after at_unix_secs. The result includes both
rotated-but-still-in-grace predecessors and never-rotated keys.
Useful for building a verifier’s accept-set as of a given time.
Sourcepub fn default_signer(&self) -> Result<Box<dyn Signer>, KeyError>
pub fn default_signer(&self) -> Result<Box<dyn Signer>, KeyError>
Returns a boxed Signer for the current default key.
Sourcepub fn signer(&self, id: &str) -> Result<Box<dyn Signer>, KeyError>
pub fn signer(&self, id: &str) -> Result<Box<dyn Signer>, KeyError>
Returns a boxed Signer for a specific key ID.
Refuses to load if the on-disk key file has insecure permissions
(any group or world bits). This is the choke point for all
signing — public-key reads and successor lookups go through
read_entry / public_key and are not affected.
Bypass with TREESHIP_ALLOW_INSECURE_KEY_PERMS=1 for controlled
environments (CI sandboxes, recovery flows). The bypass should
not be set in normal operation.
Sourcepub fn default_key_id(&self) -> Result<KeyId, KeyError>
pub fn default_key_id(&self) -> Result<KeyId, KeyError>
Returns the default key ID.
Source§impl Store
impl Store
Sourcepub fn fix_perms(&self) -> Result<Vec<(PathBuf, u32, u32)>, KeyError>
pub fn fix_perms(&self) -> Result<Vec<(PathBuf, u32, u32)>, KeyError>
Repair file permissions on the keystore directory and every file
inside it: dir to 0700, key entry files and manifest to 0600.
Used by treeship doctor --fix. No-op on non-Unix.
Returns the list of (path, old_mode, new_mode) tuples for paths that were actually changed, so the caller can report what it did.