credibil_did/document.rs
1//! # DID Document
2//!
3//! A DID Document is a JSON-LD document that contains information related to a
4//! DID.
5
6use std::collections::HashMap;
7use std::fmt::{self, Display, Formatter};
8
9use chrono::{DateTime, Utc};
10use credibil_infosec::jose::jwk::PublicKeyJwk;
11use serde::{Deserialize, Serialize};
12use serde_json::Value;
13
14use crate::core::{Kind, Quota};
15use crate::error::Error;
16
17/// DID Document
18#[derive(Clone, Debug, Default, Deserialize, Serialize, PartialEq, Eq)]
19#[serde(rename_all = "camelCase")]
20pub struct Document {
21 /// The context of the DID document.
22 #[serde(rename = "@context")]
23 pub context: Vec<Kind<Value>>,
24
25 /// The DID for a particular DID subject.
26 ///
27 /// The subject is defined as the entity identified by the DID and described
28 /// by the DID document. Anything can be a DID subject: person, group,
29 /// organization, physical thing, digital thing, logical thing, etc.
30 pub id: String,
31
32 /// A set of URIs taht are other identifiers for the subject of the above
33 /// DID.
34 #[serde(skip_serializing_if = "Option::is_none")]
35 pub also_known_as: Option<Vec<String>>,
36
37 /// One or more strings that conform to the rules DID Syntax. The
38 /// corresponding DID document(s) SHOULD contain verification
39 /// relationships that explicitly permit the use of certain verification
40 /// methods for specific purposes.
41 ///
42 /// Any verification methods contained in the related DID documents
43 /// SHOULD be accepted as authoritative, such that proofs that satisfy those
44 /// verification methods are to be considered equivalent to proofs provided
45 /// by the DID subject.
46 #[serde(skip_serializing_if = "Option::is_none")]
47 pub controller: Option<Quota<String>>,
48
49 /// A set of services, that express ways of communicating with the DID
50 /// subject or related entities.
51 #[serde(skip_serializing_if = "Option::is_none")]
52 pub service: Option<Vec<Service>>,
53
54 /// If set, MUST be a set of verification methods for the DID subject.
55 #[serde(skip_serializing_if = "Option::is_none")]
56 pub verification_method: Option<Vec<VerificationMethod>>,
57
58 /// The `authentication` verification relationship is used to specify how
59 /// the DID subject is expected to be authenticated, for purposes such
60 /// as logging into a website or in any sort of challenge-response
61 /// protocol.
62 ///
63 /// <https://www.w3.org/TR/did-core/#authentication>
64 #[serde(skip_serializing_if = "Option::is_none")]
65 pub authentication: Option<Vec<Kind<VerificationMethod>>>,
66
67 /// The `assertion_method` verification relationship is used to specify how
68 /// the DID subject is expected to express claims, such as for the
69 /// purposes of issuing a Verifiable Credential.
70 ///
71 /// <https://www.w3.org/TR/did-core/#assertion>
72 #[serde(skip_serializing_if = "Option::is_none")]
73 pub assertion_method: Option<Vec<Kind<VerificationMethod>>>,
74
75 /// The `key_agreement` verification relationship is used to specify how an
76 /// entity can generate encryption material in order to transmit
77 /// confidential information intended for the DID subject, such as for
78 /// the purposes of establishing a secure communication channel with the
79 /// recipient.
80 ///
81 /// <https://www.w3.org/TR/did-core/#key-agreement>
82 #[serde(skip_serializing_if = "Option::is_none")]
83 pub key_agreement: Option<Vec<Kind<VerificationMethod>>>,
84
85 /// The `capability_invocation` verification relationship is used to specify
86 /// a verification method that might be used by the DID subject to
87 /// invoke a cryptographic capability, such as the authorization to
88 /// update the DID Document.
89 ///
90 /// <https://www.w3.org/TR/did-core/#capability-invocation>
91 #[serde(skip_serializing_if = "Option::is_none")]
92 pub capability_invocation: Option<Vec<Kind<VerificationMethod>>>,
93
94 /// The `capability_delegation` verification relationship is used to specify
95 /// a mechanism that might be used by the DID subject to delegate a
96 /// cryptographic capability to another party, such as delegating the
97 /// authority to access a specific HTTP API to a subordinate.
98 ///
99 /// <https://www.w3.org/TR/did-core/#capability-delegation>
100 #[serde(skip_serializing_if = "Option::is_none")]
101 pub capability_delegation: Option<Vec<Kind<VerificationMethod>>>,
102
103 /// If resolution is successful, this MUST be metadata about the DID
104 /// document. This typically does not change between invocations of the
105 /// resolve and resolveRepresentation functions unless the DID document
106 /// changes. If resolution is unsuccessful, this output MUST be an
107 /// empty.
108 ///
109 /// <https://w3c.github.io/did-core/#dfn-diddocumentmetadata>
110 #[serde(skip_serializing_if = "Option::is_none")]
111 pub did_document_metadata: Option<DocumentMetadata>,
112}
113
114/// Services are used to express ways of communicating with the DID subject or
115/// associated entities. They can be any type of service the DID subject wants
116/// to advertise, including decentralized identity management services for
117/// further discovery, authentication, authorization, or interaction.
118///
119/// Service information is often service specific. For example, a reference to
120/// an encrypted messaging service can detail how to initiate the encrypted link
121/// before messaging begins.
122///
123/// Due to privacy concerns, revealing public information through services, such
124/// as social media accounts, personal websites, and email addresses, is
125/// discouraged.
126#[derive(Clone, Debug, Default, Deserialize, Serialize, PartialEq, Eq)]
127#[serde(rename_all = "camelCase")]
128pub struct Service {
129 /// A URI unique to the service.
130 pub id: String,
131
132 /// The service type. SHOULD be registered in the DID Specification
133 /// Registries.
134 #[serde(rename = "type")]
135 pub type_: String,
136
137 /// One or more endpoints for the service.
138 #[allow(clippy::struct_field_names)]
139 pub service_endpoint: Quota<Kind<Value>>,
140}
141
142/// A DID document can express verification methods, such as cryptographic
143/// public keys, which can be used to authenticate or authorize interactions
144/// with the DID subject or associated parties. For example, a cryptographic
145/// public key can be used as a verification method with respect to a digital
146/// signature; in such usage, it verifies that the signer could use the
147/// associated cryptographic private key. Verification methods might take many
148/// parameters. An example of this is a set of five cryptographic keys from
149/// which any three are required to contribute to a cryptographic threshold
150/// signature.
151///
152/// MAY include additional properties which can be determined from the
153/// verification method as registered in the
154/// [DID Specification Registries](https://www.w3.org/TR/did-spec-registries/).
155#[derive(Clone, Debug, Default, Deserialize, Serialize, PartialEq, Eq)]
156#[serde(rename_all = "camelCase")]
157pub struct VerificationMethod {
158 /// Only used when the verification method uses terms not defined in the
159 /// containing document.
160 #[serde(rename = "@context")]
161 #[serde(skip_serializing_if = "Option::is_none")]
162 pub context: Option<Kind<Value>>,
163
164 /// A DID that identifies the verification method.
165 pub id: String,
166
167 /// The DID of the controller of the verification method.
168 pub controller: String,
169
170 /// The verification method type. SHOULD be a registered type (in DID
171 /// Specification Registries).
172 #[serde(flatten)]
173 pub method_type: MethodType,
174}
175
176/// Verification method types. SHOULD be registered in the [DID Specification
177/// Registries](https://www.w3.org/TR/did-spec-registries).
178#[derive(Clone, Debug, Deserialize, Serialize, Eq, PartialEq)]
179#[serde(tag = "type")]
180#[serde(rename_all_fields = "camelCase")]
181pub enum MethodType {
182 /// Key is encoded as a Multibase. The Multikey data model is a specific
183 /// type of verification method that encodes key types into a single
184 /// binary stream that is then encoded as a Multibase value.
185 ///
186 /// <https://w3c.github.io/controller-document/#multikey>
187 #[serde(alias = "Ed25519VerificationKey2020")]
188 Multikey {
189 /// The public key encoded as a Multibase.
190 public_key_multibase: String,
191 },
192
193 /// Key is JWK. The JSON Web Key (JWK) data model is a specific type of
194 /// verification method that uses the JWK specification [RFC7517] to encode
195 /// key types into a set of parameters.
196 ///
197 /// <https://w3c.github.io/controller-document/#jsonwebkey>
198 #[serde(alias = "JsonWebKey2020")]
199 #[serde(alias = "EcdsaSecp256k1VerificationKey2019")]
200 JsonWebKey {
201 /// The public key encoded as a JWK.
202 public_key_jwk: PublicKeyJwk,
203 },
204 //
205 // #[serde(alias = "Ed25519VerificationKey2018")]
206 // Base58 { public_key_base58: String },
207}
208
209impl Default for MethodType {
210 fn default() -> Self {
211 Self::Multikey {
212 public_key_multibase: String::new(),
213 }
214 }
215}
216
217impl MethodType {
218 /// Converts a Multibase public key to JWK format.
219 ///
220 /// # Errors
221 pub fn jwk(&self) -> crate::Result<PublicKeyJwk> {
222 match self {
223 Self::JsonWebKey { public_key_jwk } => Ok(public_key_jwk.clone()),
224 Self::Multikey { public_key_multibase } => {
225 PublicKeyJwk::from_multibase(public_key_multibase)
226 .map_err(|e| Error::InvalidPublicKey(e.to_string()))
227 }
228 }
229 }
230}
231
232/// Verification method types. SHOULD be registered in the [DID Specification
233/// Registries](https://www.w3.org/TR/did-spec-registries).
234#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
235pub enum PublicKeyFormat {
236 /// Key is encoded as a Multibase. The Multikey data model is a specific
237 /// type of verification method that encodes key types into a single
238 /// binary stream that is then encoded as a Multibase value.
239 ///
240 /// <https://w3c.github.io/controller-document/#multikey>
241 #[default]
242 Multikey,
243
244 /// Key is JWK. The JSON Web Key (JWK) data model is a specific type of
245 /// verification method that uses the JWK specification [RFC7517] to encode
246 /// key types into a set of parameters.
247 ///
248 /// <https://w3c.github.io/controller-document/#jsonwebkey>
249 JsonWebKey,
250
251 /// Key is ED2559 Verification Key.
252 ///
253 /// <https://w3id.org/security/suites/ed25519-2020/v1>
254 Ed25519VerificationKey2020,
255
256 /// X25519 Key Agreement Key, 2020 version
257 X25519KeyAgreementKey2020,
258}
259
260// TODO: set context based on key format:
261// - Ed25519VerificationKey2020 https://w3id.org/security/suites/ed25519-2020/v1
262// - JsonWebKey2020 https://w3id.org/security/suites/jws-2020/v1
263
264impl Display for PublicKeyFormat {
265 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
266 match self {
267 Self::Multikey => write!(f, "Multikey"),
268 Self::Ed25519VerificationKey2020 => write!(f, "Ed25519VerificationKey2020"),
269 Self::X25519KeyAgreementKey2020 => write!(f, "X25519KeyAgreementKey2020"),
270 Self::JsonWebKey => write!(f, "JsonWebKey"),
271 }
272 }
273}
274
275/// DID document metadata. This typically does not change unless the DID
276/// document changes.
277#[derive(Clone, Debug, Default, Deserialize, Serialize, PartialEq, Eq)]
278#[serde(rename_all = "camelCase")]
279#[allow(clippy::module_name_repetitions)]
280pub struct DocumentMetadata {
281 /// Timestamp of the Create operation.
282 /// An XMLSCHEMA11-2 (RFC3339) e.g. 2010-01-01T19:23:24Z.
283 created: DateTime<Utc>,
284
285 /// Timestamp of the last Update operation. Omitted if an Update operation
286 /// has never been performed. May be the same value as the `created`
287 /// property when the difference between the two timestamps is less than
288 /// one second. An XMLSCHEMA11-2 (RFC3339) e.g. 2010-01-01T19:23:24Z.
289 #[serde(skip_serializing_if = "Option::is_none")]
290 updated: Option<DateTime<Utc>>,
291
292 /// MUST be set to true if the DID has been deactivated. Optional if the DID
293 /// has not been deactivated.
294 #[serde(skip_serializing_if = "Option::is_none")]
295 deactivated: Option<bool>,
296
297 /// May be set if the document version is not the latest. Indicates the
298 /// timestamp of the next Update operation as an XMLSCHEMA11-2
299 /// (RFC3339).
300 next_update: Option<DateTime<Utc>>,
301
302 /// Used to indicate the version of the last Update operation. SHOULD be
303 /// set.
304 #[serde(skip_serializing_if = "Option::is_none")]
305 version_id: Option<String>,
306
307 /// MAY be set if the document version is not the latest. It indicates the
308 /// version of the next Update operation.
309 #[serde(skip_serializing_if = "Option::is_none")]
310 next_version_id: Option<String>,
311
312 /// Used when a DID method needs to define different forms of a DID that are
313 /// logically equivalent. For example, when a DID takes one form prior to
314 /// registration in a verifiable data registry and another form after such
315 /// registration.
316 #[serde(skip_serializing_if = "Option::is_none")]
317 pub equivalent_id: Option<Vec<String>>,
318
319 /// Identical to the `equivalent_id` property except that it is a single
320 /// value AND the DID is the canonical ID for the DID subject within the
321 /// containing DID document.
322 #[serde(skip_serializing_if = "Option::is_none")]
323 pub canonical_id: Option<String>,
324}
325
326/// Options that can be provided when creating a DID document.
327#[derive(Clone, Debug, Deserialize, Serialize)]
328#[serde(rename_all = "camelCase")]
329pub struct CreateOptions {
330 /// Format to use for the the public key.
331 pub public_key_format: PublicKeyFormat,
332
333 /// Default context for the DID document. SHOULD be set to
334 /// `"https://www.w3.org/ns/did/v1"`.
335 pub default_context: String,
336
337 /// Enable experimental public key types. SHOULD be set to "false".
338 pub enable_experimental_public_key_types: bool,
339
340 /// Will add a `keyAgreement` object to the DID document.
341 pub enable_encryption_key_derivation: bool,
342
343 // service_endpoints: Vec<Value>,
344 // verification_methods: Vec<Value>,
345 // authentication: Vec<Value>,
346 /// Additional options.
347 #[serde(flatten)]
348 pub additional: Option<HashMap<String, String>>,
349}
350
351impl Default for CreateOptions {
352 fn default() -> Self {
353 Self {
354 public_key_format: PublicKeyFormat::default(),
355 enable_experimental_public_key_types: false,
356 default_context: "https://www.w3.org/ns/did/v1".to_string(),
357 enable_encryption_key_derivation: false,
358 additional: None,
359 }
360 }
361}