Expand description
DID resolution and production: the DidResolver and DidProducer traits a DID method
implements, the Resolver registry that routes a DID to the resolver of its method, an
optional TTL DocumentCache, and DID URL dereferencing.
The module ships no DID method. Each method is a type implementing DidResolver and/or
DidProducer, registered with ResolverBuilder::with; adding one needs no change here.
§Resolution
Resolver::resolve implements the DID Resolution algorithm around the method’s resolver:
it reports ResolutionError::MethodNotSupported for a method nobody registered, turns a
result whose metadata reports an error into Err, refuses a document whose id is not the
DID being resolved (nor its canonicalId), and serves repeated resolutions from the cache
when one is configured. Resolver::resolve_document is the shortcut to the document.
§Dereferencing
Resolver::dereference resolves the DID of a DID URL and then selects the resource the URL
names: the document itself, or the verification method or service whose id is the URL
(Dereferenced). The versionId and versionTime DID parameters are passed to the
method’s resolver as resolution options; a path, any other query parameter and the
service/relativeRef parameters are method-specific and reported as
DereferenceError::MethodSpecific. Resolver::resolve_public_key goes one step further
and returns the Jwk of a verification method, optionally checked to be
usable for a verification relationship, decoding publicKeyMultibase material as a Multikey,
which is what a JWS verifier needs.
§Examples
A method is a type implementing DidResolver; here one that serves documents from memory.
use std::collections::HashMap;
use identity_kit::did::{
Did, DidDocument, DidUrl, ResolutionError, ResolutionOptions, ResolutionResult,
};
use identity_kit::resolver::{Dereferenced, DidResolver, Resolver};
struct Static(HashMap<Did, DidDocument>);
#[async_trait::async_trait]
impl DidResolver for Static {
fn method(&self) -> &'static str {
"example"
}
async fn resolve(
&self,
did: &Did,
_: &ResolutionOptions,
) -> Result<ResolutionResult, ResolutionError> {
self.0
.get(did)
.cloned()
.map(ResolutionResult::new)
.ok_or(ResolutionError::NotFound)
}
}
let document: DidDocument = serde_json::from_str(r##"{
"id": "did:example:123",
"verificationMethod": [{
"id": "did:example:123#key-1",
"type": "JsonWebKey2020",
"controller": "did:example:123",
"publicKeyJwk": {
"kty": "OKP", "crv": "Ed25519", "x": "11qYAYKxCrfVS_7TyWQHOg7hcvPapiMlrwIaaPcHURo"
}
}],
"authentication": ["#key-1"]
}"##)?;
let did = document.id.clone();
let resolver = Resolver::builder()
.with(Static(HashMap::from([(did.clone(), document)])))
.cache(std::time::Duration::from_secs(60))
.build();
assert_eq!(resolver.resolve_document(&did).await?.id, did);
let key = DidUrl::parse("did:example:123#key-1")?;
let jwk = resolver.resolve_public_key(&key, None).await?;
assert_eq!(jwk.crv(), Some("Ed25519"));
assert!(matches!(resolver.dereference(&key).await?, Dereferenced::VerificationMethod(_)));
let unknown = Did::parse("did:other:123")?;
assert_eq!(
resolver.resolve(&unknown).await.unwrap_err(),
ResolutionError::MethodNotSupported
);Structs§
- Document
Cache - A bounded cache of resolution results, keyed by DID, where every entry expires after the same time to live.
- Method
Capabilities - What a DID method can do, declared by its
DidProducerso an application can pick a method without knowing it. - Resolver
- Routes each DID to the
DidResolverregistered for its method, with an optionalDocumentCachein front. - Resolver
Builder - Builds a
Resolver.
Enums§
- Dereference
Error - Why a DID URL could not be dereferenced.
- Dereferenced
- The resource a DID URL names, as
Resolver::dereferencereturns it. - Hosting
- Where the documents of a DID method live, which decides what creating one involves.
- Produce
Error - Why a
DidProducercould not produce a document.
Traits§
- DidProducer
- Produces the DID document of one method from public keys.
- DidResolver
- Resolves the DIDs of one method (DID Resolution “DID Resolution Algorithm”).