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}