1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
//! 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. Beside DIDs, finding the key a
//! token was signed with: [`KeyReference`] and [`KeyResolver`].
//!
//! 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 [`ResolutionErrorKind::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`](crate::jose::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.
//!
//! # Key references
//!
//! A JWT names the key that signed it in one of several ways (ADR 0006), and
//! [`KeyReference::from_jws`] reads which, in this order: a `kid` that is a DID URL
//! (`did:…#fragment`, without a path or DID parameters); a `kid` that is a `#fragment`, joined
//! with a DID `iss`; another `kid` with an HTTPS `iss`, naming a key of the issuer's key set; the
//! key itself in a `jwk` header; an `x5c` certificate chain; a `jku` key set URL. A
//! [`KeyResolver`] turns the reference into a key for a [`KeyRole`], the issuer's
//! (`assertionMethod` in a DID document) or the subject's (`authentication`):
//!
//! | Reference | Resolved by |
//! |---|---|
//! | [`KeyReference::DidUrl`] | [`Resolver`], dereferencing the verification method |
//! | [`KeyReference::Jwk`] | [`JwkResolver`], the key itself |
//! | [`KeyReference::Jwks`] | `JwksResolver` (feature `jwks`), the JWT VC issuer metadata of the issuer |
//! | [`KeyReference::X509Chain`], [`KeyReference::Jku`] | nothing in the crate yet; an application's own [`KeyResolver`] |
//!
//! [`CompositeKeyResolver`] tries several in order. Resolving says nothing about trust: after
//! the signature verifies, [`KeyReference::binds_to`] checks that the key belongs to the party
//! the token claims, which the validators of the upper layer do.
//!
//! # 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, ResolutionErrorKind, 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_else(|| {
//! ResolutionError::new(ResolutionErrorKind::NotFound)
//! .with_detail(format!("no document is stored for `{did}`"))
//! })
//! }
//! }
//!
//! # tokio::runtime::Builder::new_current_thread().build()?.block_on(async {
//! 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")?;
//! let error = resolver.resolve(&unknown).await.unwrap_err();
//! assert_eq!(error, ResolutionErrorKind::MethodNotSupported);
//! assert_eq!(error.detail(), Some("no resolver is registered for `did:other`"));
//! # Ok::<(), Box<dyn std::error::Error>>(())
//! # })?;
//! # Ok::<(), Box<dyn std::error::Error>>(())
//! ```
use Arc;
use crateResolutionErrorKind;
use crate;
pub use DocumentCache;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
/// Resolves the DIDs of one method (DID Resolution "DID Resolution Algorithm").
///
/// A resolver is registered with a [`Resolver`] under [`method`](Self::method) and receives
/// only DIDs of that method. It is `Send + Sync` and resolution is `async` because most methods
/// fetch the document over the network or from a registry.
///
/// A failed resolution may be reported either as `Err`, or as an `Ok` result whose resolution
/// metadata carries the error, which is the shape a method that builds a full
/// [`ResolutionResult`] (a client of a remote resolver, say) produces anyway. The [`Resolver`]
/// normalizes both to `Err`.
forward_did_resolver!;