pub struct KeyStoreIdentity { /* private fields */ }Expand description
An Identity over the keys of a KeyStore, vendor-agnostic: a KMS or HSM backend that
implements KeyStore works without glue.
A key of the store is bound to a (kind, alg) pair with bind, which derives
the identifier: the thumbprint of the key for IdentityKind::JwkThumbprint, and for
IdentityKind::Did the DID of the document that the producer registered for the method
(see with_producer) makes for the key, with its first verification
method as the kid. A DID that no registered producer can make, such as a did:web whose
producer needs an origin, is bound with bind_did_url.
§Key generation is opt-in
By default an unbound pair is an error, so that a production deployment never mints keys
silently. With generate_missing(true) the identity asks the store
for a new key the first time an unbound pair is used, binds it, and reuses it from then on.
Bindings live in memory only: an application that generates keys this way stores
bindings and binds them again on the next start.
§Examples
use std::sync::Arc;
use identity_kit::did::DidMethod;
use identity_kit::identity::{Identity, IdentityKind, KeyStoreIdentity};
use identity_kit::jose::JwsAlgorithm;
use identity_kit::keys::InMemoryKeyStore;
use identity_kit::methods::{DidJwk, DidKey};
let identity = KeyStoreIdentity::new(Arc::new(InMemoryKeyStore::new()))
.with_producer(DidKey::default())
.with_producer(DidJwk)
.generate_missing(true);
let kind = IdentityKind::Did(DidMethod::new("jwk")?);
let did = identity.identifier(&kind, JwsAlgorithm::ES256).await?;
assert!(did.to_string().starts_with("did:jwk:"));
// The key was generated once and is reused.
assert_eq!(identity.identifier(&kind, JwsAlgorithm::ES256).await?, did);
assert_eq!(identity.bindings().len(), 1);Implementations§
Source§impl KeyStoreIdentity
impl KeyStoreIdentity
Sourcepub fn new(store: Arc<dyn KeyStore>) -> Self
pub fn new(store: Arc<dyn KeyStore>) -> Self
An identity over store, with no producer, no binding and key generation off.
Sourcepub fn with_producer(
self,
producer: impl DidProducer<Params = ()> + 'static,
) -> Self
pub fn with_producer( self, producer: impl DidProducer<Params = ()> + 'static, ) -> Self
This identity with producer making the DIDs of its method, replacing a producer
registered for the same method before.
Only producers that need no parameters (Params = ()) are registered: those whose DID
follows from the key, such as did:key and did:jwk. A DID made with parameters, such as
a did:web from its origin, is bound with bind_did_url.
Sourcepub fn generate_missing(self, enabled: bool) -> Self
pub fn generate_missing(self, enabled: bool) -> Self
This identity generating a key the first time an unbound pair is used, when enabled
and the store can generate keys for the algorithm. Off by default; see the
type documentation.
Sourcepub async fn bind(
&self,
kind: IdentityKind,
alg: JwsAlgorithm,
key: KeyId,
) -> Result<Identifier, IdentityError>
pub async fn bind( &self, kind: IdentityKind, alg: JwsAlgorithm, key: KeyId, ) -> Result<Identifier, IdentityError>
Binds key of the store to (kind, alg), replacing a key bound to the pair before, and
returns the identifier derived from it.
§Errors
IdentityError::UnsupportedAlgorithmwhen the store does not sign withalg;IdentityError::KeyStorewhen the key does not exist or is not a key foralg;IdentityError::UnsupportedKindwhen no registered producer makes DIDs of the method, or the DID it made is not in the namespace ofkind;IdentityError::Producewhen the producer refuses the key;IdentityError::NoVerificationMethodwhen its document has no verification method.
Sourcepub async fn bind_did_url(
&self,
kind: IdentityKind,
alg: JwsAlgorithm,
key: KeyId,
url: DidUrl,
) -> Result<Identifier, IdentityError>
pub async fn bind_did_url( &self, kind: IdentityKind, alg: JwsAlgorithm, key: KeyId, url: DidUrl, ) -> Result<Identifier, IdentityError>
Binds key of the store to (kind, alg) as the verification method url, replacing a
key bound to the pair before, and returns the DID of url.
This is how a DID that no registered producer makes is used: a did:web, or a DID of a
registry method that the application created. The caller vouches that the published
document of the DID has url as a verification method with the public key of key;
the identity cannot tell without resolving it.
§Errors
IdentityError::UnsupportedKind when kind is not a DID kind that the DID of url
matches, and as bind for the key.
Sourcepub fn bindings(&self) -> Vec<(IdentityKind, JwsAlgorithm, KeyId)>
pub fn bindings(&self) -> Vec<(IdentityKind, JwsAlgorithm, KeyId)>
The bound pairs and their keys, in the order they were bound, for an application to store and bind again on the next start.
Trait Implementations§
Source§impl Debug for KeyStoreIdentity
impl Debug for KeyStoreIdentity
Source§impl Identity for KeyStoreIdentity
impl Identity for KeyStoreIdentity
Source§fn capabilities(&self) -> Vec<(IdentityKind, JwsAlgorithm)>
fn capabilities(&self) -> Vec<(IdentityKind, JwsAlgorithm)>
The bound pairs, then, when key generation is on and the store can generate, every pair of a registered producer’s method or the thumbprint with an algorithm the store generates keys for. A generated pair can still fail when the producer refuses the key type.
Source§fn identifier<'life0, 'life1, 'async_trait>(
&'life0 self,
kind: &'life1 IdentityKind,
alg: JwsAlgorithm,
) -> Pin<Box<dyn Future<Output = Result<Identifier, IdentityError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn identifier<'life0, 'life1, 'async_trait>(
&'life0 self,
kind: &'life1 IdentityKind,
alg: JwsAlgorithm,
) -> Pin<Box<dyn Future<Output = Result<Identifier, IdentityError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
(kind, alg). A thumbprint, a did:key or a did:jwk is derived from
the key bound to the pair, so it names the same key as
public_jwk and signer only for the same
pair. Read moreSource§fn public_jwk<'life0, 'life1, 'async_trait>(
&'life0 self,
kind: &'life1 IdentityKind,
alg: JwsAlgorithm,
) -> Pin<Box<dyn Future<Output = Result<Jwk, IdentityError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn public_jwk<'life0, 'life1, 'async_trait>(
&'life0 self,
kind: &'life1 IdentityKind,
alg: JwsAlgorithm,
) -> Pin<Box<dyn Future<Output = Result<Jwk, IdentityError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Source§fn signer<'life0, 'life1, 'async_trait>(
&'life0 self,
kind: &'life1 IdentityKind,
alg: JwsAlgorithm,
) -> Pin<Box<dyn Future<Output = Result<Box<dyn Signer + '_>, IdentityError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn signer<'life0, 'life1, 'async_trait>(
&'life0 self,
kind: &'life1 IdentityKind,
alg: JwsAlgorithm,
) -> Pin<Box<dyn Future<Output = Result<Box<dyn Signer + '_>, IdentityError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
(kind, alg). For IdentityKind::Did, Signer::kid is the absolute
DID URL of the verification method; for IdentityKind::JwkThumbprint it is None and
the caller puts public_jwk in the header. Read more