Skip to main content

SoftwareKeyStore

Struct SoftwareKeyStore 

Source
pub struct SoftwareKeyStore { /* private fields */ }
Available on crate feature software only.
Expand description

A KeyStore over a file holding a JWK set of private keys.

The file is {"keys": [...]} (RFC 7517 §5) where every key is a private JWK with a kid, the key id, and an alg, the one algorithm it signs with. Signs EdDSA, ES256 and (feature secp256k1) ES256K; generates and deletes. RSA keys in the file are refused, since the crate never signs with RSA (docs/adr/0001-rsa-verification-only.md).

The whole file is read when the store is opened and every key is checked then: a key whose public members do not match its private scalar, whose alg does not fit, or whose kid is taken by another key fails SoftwareKeyStore::open with KeyStoreError::InvalidKeySet. Private material is zeroized when the store is dropped.

Writes (generate, delete, import) replace the file atomically: the new set is written to a temporary file in the same directory, created with mode 0600 on Unix, synced and renamed over the old one. A store opened on a file that other users can read is refused unless SoftwareKeyStoreOptions::allow_insecure_permissions is set. Nothing locks the file against other processes; one store per file.

The key id of a generated key is the spec’s label when set and the RFC 7638 thumbprint of the public key otherwise. xtask keys generate provisions a file from the command line.

§Examples

use identity_kit::jose::{JwsAlgorithm, KeyType};
use identity_kit::keys::{KeySpec, KeyStore, SoftwareKeyStore, SoftwareKeyStoreOptions};

let dir = tempfile::tempdir()?;
let path = dir.path().join("keys.json");
let store = SoftwareKeyStore::create(&path)?;
let key = store
    .generate(KeySpec::new(KeyType::P256, JwsAlgorithm::ES256).with_label("issuer"))
    .await?;
assert_eq!(key.as_str(), "issuer");

// The key is on disk and usable by the next store opened on the file.
let reopened = SoftwareKeyStore::open(&path)?;
assert!(reopened.exists(&key).await?);
assert_eq!(reopened.sign(&key, JwsAlgorithm::ES256, b"payload").await?.len(), 64);

Implementations§

Source§

impl SoftwareKeyStore

Source

pub fn open(path: impl Into<PathBuf>) -> Result<Self, KeyStoreError>

Opens the key set file at path with the default options.

§Errors

KeyStoreError::Io when the file cannot be read, KeyStoreError::InsecurePermissions when other users can read it and KeyStoreError::InvalidKeySet when it is not a JWK set of usable private keys.

Source

pub fn open_with( path: impl Into<PathBuf>, options: SoftwareKeyStoreOptions, ) -> Result<Self, KeyStoreError>

Opens the key set file at path as options say.

§Errors

As SoftwareKeyStore::open.

Source

pub fn create(path: impl Into<PathBuf>) -> Result<Self, KeyStoreError>

Creates an empty key set file at path, with mode 0600 on Unix.

§Errors

KeyStoreError::Io when the file exists already or cannot be written.

Source

pub fn path(&self) -> &Path

The key set file.

Source

pub fn key_ids(&self) -> Vec<KeyId>

The ids of the keys in the store, in file order.

Source

pub fn import(&self, jwk: Jwk) -> Result<KeyId, KeyStoreError>

Adds an existing private JWK to the store and writes the file.

The key id is the kid when set and the RFC 7638 thumbprint of the public key otherwise; alg must fit the key when set and defaults to the key type’s algorithm.

§Errors

KeyStoreError::InvalidKey when the JWK is not a usable private key of a supported type, KeyStoreError::AlreadyExists when its id is taken and KeyStoreError::Io when the file cannot be written.

Trait Implementations§

Source§

impl Debug for SoftwareKeyStore

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl KeyStore for SoftwareKeyStore

Source§

fn capabilities(&self) -> KeyStoreCapabilities

What this store can do.
Source§

fn public_jwk<'life0, 'life1, 'async_trait>( &'life0 self, key: &'life1 KeyId, ) -> Pin<Box<dyn Future<Output = Result<Jwk, KeyStoreError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

The public key of key, without private parameters. Read more
Source§

fn sign<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, key: &'life1 KeyId, alg: JwsAlgorithm, data: &'life2 [u8], ) -> Pin<Box<dyn Future<Output = Result<Vec<u8>, KeyStoreError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Signs data with key under alg, returning the signature in its JWS form. Read more
Source§

fn exists<'life0, 'life1, 'async_trait>( &'life0 self, key: &'life1 KeyId, ) -> Pin<Box<dyn Future<Output = Result<bool, KeyStoreError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Whether key exists. Read more
Source§

fn generate<'life0, 'async_trait>( &'life0 self, spec: KeySpec, ) -> Pin<Box<dyn Future<Output = Result<KeyId, KeyStoreError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Generates a key as spec describes and returns its id. Read more
Source§

fn delete<'life0, 'life1, 'async_trait>( &'life0 self, key: &'life1 KeyId, ) -> Pin<Box<dyn Future<Output = Result<(), KeyStoreError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Deletes key. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more