identity_document/document/
core_document.rs

1// Copyright 2020-2025 IOTA Stiftung, Fondazione LINKS
2// SPDX-License-Identifier: Apache-2.0
3
4use core::convert::TryInto as _;
5use core::fmt::Display;
6use core::fmt::Formatter;
7use std::collections::HashMap;
8use std::convert::Infallible;
9
10use identity_did::DIDCompositeJwk;
11use identity_did::DIDJwk;
12use identity_verification::jose::jwk::Jwk;
13use identity_verification::jose::jws::DecodedJws;
14use identity_verification::jose::jws::Decoder;
15use identity_verification::jose::jws::JwsVerifier;
16use serde::Serialize;
17
18use identity_core::common::Object;
19use identity_core::common::OneOrSet;
20use identity_core::common::OrderedSet;
21use identity_core::common::Url;
22use identity_core::convert::FmtJson;
23use serde::Serializer;
24
25use crate::document::DocumentBuilder;
26use crate::error::Error;
27use crate::error::Result;
28use crate::service::Service;
29use crate::utils::DIDUrlQuery;
30use crate::utils::Queryable;
31use crate::verifiable::JwsVerificationOptions;
32use identity_did::CoreDID;
33use identity_did::DIDUrl;
34use identity_verification::MethodRef;
35use identity_verification::MethodRelationship;
36use identity_verification::MethodScope;
37use identity_verification::VerificationMethod;
38
39#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
40#[rustfmt::skip]
41pub(crate) struct CoreDocumentData
42{
43  pub(crate) id: CoreDID,
44  #[serde(skip_serializing_if = "Option::is_none")]
45  pub(crate) controller: Option<OneOrSet<CoreDID>>,
46  #[serde(default = "Default::default", rename = "alsoKnownAs", skip_serializing_if = "OrderedSet::is_empty")]
47  pub(crate) also_known_as: OrderedSet<Url>,
48  #[serde(default = "Default::default", rename = "verificationMethod", skip_serializing_if = "OrderedSet::is_empty")]
49  pub(crate) verification_method: OrderedSet<VerificationMethod>,
50  #[serde(default = "Default::default", skip_serializing_if = "OrderedSet::is_empty")]
51  pub(crate) authentication: OrderedSet<MethodRef>,
52  #[serde(default = "Default::default", rename = "assertionMethod", skip_serializing_if = "OrderedSet::is_empty")]
53  pub(crate) assertion_method: OrderedSet<MethodRef>,
54  #[serde(default = "Default::default", rename = "keyAgreement", skip_serializing_if = "OrderedSet::is_empty")]
55  pub(crate) key_agreement: OrderedSet<MethodRef>,
56  #[serde(default = "Default::default", rename = "capabilityDelegation", skip_serializing_if = "OrderedSet::is_empty")]
57  pub(crate) capability_delegation: OrderedSet<MethodRef>,
58  #[serde(default = "Default::default", rename = "capabilityInvocation", skip_serializing_if = "OrderedSet::is_empty")]
59  pub(crate) capability_invocation: OrderedSet<MethodRef>,
60  #[serde(default = "Default::default", skip_serializing_if = "OrderedSet::is_empty")]
61  pub(crate) service: OrderedSet<Service>,
62  #[serde(flatten)]
63  pub(crate) properties: Object,
64}
65
66impl CoreDocumentData {
67  /// Checks the following:
68  /// - There are no scoped method references to an embedded method in the document
69  /// - The ids of verification methods (scoped/embedded or general purpose) and services are unique across the
70  ///   document.
71  fn check_id_constraints(&self) -> Result<()> {
72    let max_unique_method_ids = self.verification_method.len()
73      + self.authentication.len()
74      + self.assertion_method.len()
75      + self.key_agreement.len()
76      + self.capability_delegation.len()
77      + self.capability_invocation.len();
78
79    // Value = true => the identifier belongs to an embedded method, false means it belongs to a method reference or a
80    // general purpose verification method
81    let mut method_identifiers: HashMap<&DIDUrl, bool> = HashMap::with_capacity(max_unique_method_ids);
82
83    for (id, is_embedded) in self
84      .authentication
85      .iter()
86      .chain(self.assertion_method.iter())
87      .chain(self.key_agreement.iter())
88      .chain(self.capability_delegation.iter())
89      .chain(self.capability_invocation.iter())
90      .map(|method_ref| match method_ref {
91        MethodRef::Embed(_) => (method_ref.id(), true),
92        MethodRef::Refer(_) => (method_ref.id(), false),
93      })
94    {
95      if let Some(previous) = method_identifiers.insert(id, is_embedded) {
96        match previous {
97          // An embedded method with the same id has previously been encountered
98          true => {
99            return Err(Error::InvalidDocument(
100              "attempted to construct document with a duplicated or aliased embedded method",
101              None,
102            ));
103          }
104          // A method reference to the identifier has previously been encountered
105          false => {
106            if is_embedded {
107              return Err(Error::InvalidDocument(
108                "attempted to construct document with an aliased embedded method",
109                None,
110              ));
111            }
112          }
113        }
114      }
115    }
116
117    for method_id in self.verification_method.iter().map(|method| method.id()) {
118      if method_identifiers
119        .insert(method_id, false)
120        .filter(|value| *value)
121        .is_some()
122      {
123        return Err(Error::InvalidDocument(
124          "attempted to construct document with a duplicated embedded method",
125          None,
126        ));
127      }
128    }
129
130    for service_id in self.service.iter().map(|service| service.id()) {
131      if method_identifiers.contains_key(service_id) {
132        return Err(Error::InvalidDocument(
133          "attempted to construct document with a service identifier shared with a verification method",
134          None,
135        ));
136      }
137    }
138
139    Ok(())
140  }
141
142  // Apply the provided fallible functions to the DID components of `id`, `controller`, methods and services
143  // respectively.
144  fn try_map<F, G, H, L, E>(
145    self,
146    id_map: F,
147    mut controller_map: G,
148    mut method_map: H,
149    mut services_map: L,
150  ) -> Result<Self, E>
151  where
152    F: FnOnce(CoreDID) -> std::result::Result<CoreDID, E>,
153    G: FnMut(CoreDID) -> std::result::Result<CoreDID, E>,
154    H: FnMut(CoreDID) -> std::result::Result<CoreDID, E>,
155    L: FnMut(CoreDID) -> std::result::Result<CoreDID, E>,
156  {
157    let current_data = self;
158    // Update `id`
159    let id = id_map(current_data.id)?;
160    // Update controllers
161    let controller = if let Some(controllers) = current_data.controller {
162      Some(controllers.try_map(&mut controller_map)?)
163    } else {
164      None
165    };
166
167    // Update methods
168
169    let verification_method = current_data
170      .verification_method
171      .into_iter()
172      .map(|method| method.try_map(&mut method_map))
173      .collect::<Result<_, E>>()?;
174
175    let authentication = current_data
176      .authentication
177      .into_iter()
178      .map(|method_ref| method_ref.try_map(&mut method_map))
179      .collect::<Result<_, E>>()?;
180
181    let assertion_method = current_data
182      .assertion_method
183      .into_iter()
184      .map(|method_ref| method_ref.try_map(&mut method_map))
185      .collect::<Result<_, E>>()?;
186
187    let key_agreement = current_data
188      .key_agreement
189      .into_iter()
190      .map(|method_ref| method_ref.try_map(&mut method_map))
191      .collect::<Result<_, E>>()?;
192
193    let capability_delegation = current_data
194      .capability_delegation
195      .into_iter()
196      .map(|method_ref| method_ref.try_map(&mut method_map))
197      .collect::<Result<_, E>>()?;
198
199    let capability_invocation = current_data
200      .capability_invocation
201      .into_iter()
202      .map(|method_ref| method_ref.try_map(&mut method_map))
203      .collect::<Result<_, E>>()?;
204
205    // Update services
206    let service = current_data
207      .service
208      .into_iter()
209      .map(|service| service.try_map(&mut services_map))
210      .collect::<Result<_, E>>()?;
211
212    Ok(CoreDocumentData {
213      id,
214      controller,
215      also_known_as: current_data.also_known_as,
216      verification_method,
217      authentication,
218      assertion_method,
219      key_agreement,
220      capability_delegation,
221      capability_invocation,
222      service,
223      properties: current_data.properties,
224    })
225  }
226}
227
228/// A DID Document.
229///
230/// [Specification](https://www.w3.org/TR/did-core/#did-document-properties)
231#[derive(Clone, Debug, PartialEq, Eq, Deserialize)]
232#[rustfmt::skip]
233#[serde(try_from = "CoreDocumentData")]
234pub struct CoreDocument
235{
236  pub(crate) data: CoreDocumentData, 
237}
238
239//Forward serialization to inner
240impl Serialize for CoreDocument {
241  fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
242  where
243    S: Serializer,
244  {
245    self.data.serialize(serializer)
246  }
247}
248
249// Workaround for lifetime issues with a mutable reference to self preventing closures from being used.
250macro_rules! method_ref_mut_helper {
251  ($doc:ident, $method: ident, $query: ident) => {
252    match $doc.data.$method.query_mut($query.into())? {
253      MethodRef::Embed(method) => Some(method),
254      MethodRef::Refer(ref did) => $doc.data.verification_method.query_mut(did),
255    }
256  };
257}
258
259impl CoreDocument {
260  /// Creates a [`DocumentBuilder`] to configure a new `CoreDocument`.
261  ///
262  /// This is the same as [`DocumentBuilder::new`].
263  pub fn builder(properties: Object) -> DocumentBuilder {
264    DocumentBuilder::new(properties)
265  }
266
267  /// Returns a new `CoreDocument` based on the [`DocumentBuilder`] configuration.
268  pub fn from_builder(builder: DocumentBuilder) -> Result<Self> {
269    Self::try_from(CoreDocumentData {
270      id: builder.id.ok_or(Error::InvalidDocument("missing id", None))?,
271      controller: Some(builder.controller)
272        .filter(|controllers| !controllers.is_empty())
273        .map(TryFrom::try_from)
274        .transpose()
275        .map_err(|err| Error::InvalidDocument("controller", Some(err)))?,
276      also_known_as: builder
277        .also_known_as
278        .try_into()
279        .map_err(|err| Error::InvalidDocument("also_known_as", Some(err)))?,
280      verification_method: builder
281        .verification_method
282        .try_into()
283        .map_err(|err| Error::InvalidDocument("verification_method", Some(err)))?,
284      authentication: builder
285        .authentication
286        .try_into()
287        .map_err(|err| Error::InvalidDocument("authentication", Some(err)))?,
288      assertion_method: builder
289        .assertion_method
290        .try_into()
291        .map_err(|err| Error::InvalidDocument("assertion_method", Some(err)))?,
292      key_agreement: builder
293        .key_agreement
294        .try_into()
295        .map_err(|err| Error::InvalidDocument("key_agreement", Some(err)))?,
296      capability_delegation: builder
297        .capability_delegation
298        .try_into()
299        .map_err(|err| Error::InvalidDocument("capability_delegation", Some(err)))?,
300      capability_invocation: builder
301        .capability_invocation
302        .try_into()
303        .map_err(|err| Error::InvalidDocument("capability_invocation", Some(err)))?,
304      service: builder
305        .service
306        .try_into()
307        .map_err(|err| Error::InvalidDocument("service", Some(err)))?,
308      properties: builder.properties,
309    })
310  }
311
312  /// Returns a reference to the `CoreDocument` id.
313  pub fn id(&self) -> &CoreDID {
314    &self.data.id
315  }
316
317  /// Returns a mutable reference to the `CoreDocument` id.
318  ///
319  /// # Warning
320  ///
321  /// Changes to the identifier can drastically alter the results of
322  /// [`Self::resolve_method`](CoreDocument::resolve_method()),
323  /// [`Self::resolve_service`](CoreDocument::resolve_service()) and the related [DID URL dereferencing](https://w3c-ccg.github.io/did-resolution/#dereferencing) algorithm.
324  pub fn id_mut_unchecked(&mut self) -> &mut CoreDID {
325    &mut self.data.id
326  }
327
328  /// Returns a reference to the `CoreDocument` controller.
329  pub fn controller(&self) -> Option<&OneOrSet<CoreDID>> {
330    self.data.controller.as_ref()
331  }
332
333  /// Returns a mutable reference to the `CoreDocument` controller.
334  pub fn controller_mut(&mut self) -> &mut Option<OneOrSet<CoreDID>> {
335    &mut self.data.controller
336  }
337
338  /// Returns a reference to the `CoreDocument` alsoKnownAs set.
339  pub fn also_known_as(&self) -> &OrderedSet<Url> {
340    &self.data.also_known_as
341  }
342
343  /// Returns a mutable reference to the `CoreDocument` alsoKnownAs set.
344  pub fn also_known_as_mut(&mut self) -> &mut OrderedSet<Url> {
345    &mut self.data.also_known_as
346  }
347
348  /// Returns a reference to the `CoreDocument` verificationMethod set.
349  pub fn verification_method(&self) -> &OrderedSet<VerificationMethod> {
350    &self.data.verification_method
351  }
352
353  /// Returns a reference to the `CoreDocument` authentication set.
354  pub fn authentication(&self) -> &OrderedSet<MethodRef> {
355    &self.data.authentication
356  }
357
358  /// Returns a reference to the `CoreDocument` assertionMethod set.
359  pub fn assertion_method(&self) -> &OrderedSet<MethodRef> {
360    &self.data.assertion_method
361  }
362
363  /// Returns a reference to the `CoreDocument` keyAgreement set.
364  pub fn key_agreement(&self) -> &OrderedSet<MethodRef> {
365    &self.data.key_agreement
366  }
367
368  /// Returns a reference to the `CoreDocument` capabilityDelegation set.
369  pub fn capability_delegation(&self) -> &OrderedSet<MethodRef> {
370    &self.data.capability_delegation
371  }
372
373  /// Returns a reference to the `CoreDocument` capabilityInvocation set.
374  pub fn capability_invocation(&self) -> &OrderedSet<MethodRef> {
375    &self.data.capability_invocation
376  }
377
378  /// Returns a reference to the `CoreDocument` service set.
379  pub fn service(&self) -> &OrderedSet<Service> {
380    &self.data.service
381  }
382
383  /// # Warning
384  ///
385  /// Changing a service's identifier can drastically alter the results of
386  /// [`Self::resolve_service`](CoreDocument::resolve_service()) and the related [DID URL dereferencing](https://w3c-ccg.github.io/did-resolution/#dereferencing) algorithm.
387  pub fn service_mut_unchecked(&mut self) -> &mut OrderedSet<Service> {
388    &mut self.data.service
389  }
390
391  /// Returns a reference to the custom `CoreDocument` properties.
392  pub fn properties(&self) -> &Object {
393    &self.data.properties
394  }
395
396  /// Returns a mutable reference to the custom `CoreDocument` properties.
397  ///
398  /// # Warning
399  ///
400  /// The properties returned are not checked against the standard fields in a [`CoreDocument`]. Incautious use can have
401  /// undesired consequences such as key collision when attempting to serialize the document or distinct resources (such
402  /// as services and methods) being identified by the same DID URL.  
403  pub fn properties_mut_unchecked(&mut self) -> &mut Object {
404    &mut self.data.properties
405  }
406
407  /// Adds a new [`VerificationMethod`] to the document in the given [`MethodScope`].
408  ///
409  /// # Errors
410  ///
411  /// Returns an error if a method or service with the same fragment already exists.
412  pub fn insert_method(&mut self, method: VerificationMethod, scope: MethodScope) -> Result<()> {
413    // Check that the method identifier is not already in use by an existing method or service.
414    //
415    // NOTE: this check cannot be relied upon if the document contains methods or services whose ids are
416    // of the form <did different from this document's>#<fragment>.
417    if self.resolve_method(method.id(), None).is_some() || self.service().query(method.id()).is_some() {
418      return Err(Error::MethodInsertionError);
419    }
420    match scope {
421      MethodScope::VerificationMethod => self.data.verification_method.append(method),
422      MethodScope::VerificationRelationship(MethodRelationship::Authentication) => {
423        self.data.authentication.append(MethodRef::Embed(method))
424      }
425      MethodScope::VerificationRelationship(MethodRelationship::AssertionMethod) => {
426        self.data.assertion_method.append(MethodRef::Embed(method))
427      }
428      MethodScope::VerificationRelationship(MethodRelationship::KeyAgreement) => {
429        self.data.key_agreement.append(MethodRef::Embed(method))
430      }
431      MethodScope::VerificationRelationship(MethodRelationship::CapabilityDelegation) => {
432        self.data.capability_delegation.append(MethodRef::Embed(method))
433      }
434      MethodScope::VerificationRelationship(MethodRelationship::CapabilityInvocation) => {
435        self.data.capability_invocation.append(MethodRef::Embed(method))
436      }
437    };
438
439    Ok(())
440  }
441
442  /// Removes and returns the [`VerificationMethod`] identified by `did_url` from the document.
443  ///
444  /// # Note
445  ///
446  /// All _references to the method_ found in the document will be removed.
447  /// This includes cases where the reference is to a method contained in another DID document.
448  pub fn remove_method(&mut self, did_url: &DIDUrl) -> Option<VerificationMethod> {
449    self.remove_method_and_scope(did_url).map(|(method, _scope)| method)
450  }
451
452  /// Removes and returns the [`VerificationMethod`] from the document. The [`MethodScope`] under which the method was
453  /// found is appended to the second position of the returned tuple.
454  ///
455  /// # Note
456  ///
457  /// All _references to the method_ found in the document will be removed.
458  /// This includes cases where the reference is to a method contained in another DID document.
459  pub fn remove_method_and_scope(&mut self, did_url: &DIDUrl) -> Option<(VerificationMethod, MethodScope)> {
460    for (method_ref, scope) in [
461      self.data.authentication.remove(did_url).map(|method_ref| {
462        (
463          method_ref,
464          MethodScope::VerificationRelationship(MethodRelationship::Authentication),
465        )
466      }),
467      self.data.assertion_method.remove(did_url).map(|method_ref| {
468        (
469          method_ref,
470          MethodScope::VerificationRelationship(MethodRelationship::AssertionMethod),
471        )
472      }),
473      self.data.key_agreement.remove(did_url).map(|method_ref| {
474        (
475          method_ref,
476          MethodScope::VerificationRelationship(MethodRelationship::KeyAgreement),
477        )
478      }),
479      self.data.capability_delegation.remove(did_url).map(|method_ref| {
480        (
481          method_ref,
482          MethodScope::VerificationRelationship(MethodRelationship::CapabilityDelegation),
483        )
484      }),
485      self.data.capability_invocation.remove(did_url).map(|method_ref| {
486        (
487          method_ref,
488          MethodScope::VerificationRelationship(MethodRelationship::CapabilityInvocation),
489        )
490      }),
491    ]
492    .into_iter()
493    .flatten()
494    {
495      if let (MethodRef::Embed(embedded_method), scope) = (method_ref, scope) {
496        // embedded methods cannot be referenced, or be in the set of general purpose verification methods hence the
497        // search is complete
498        return Some((embedded_method, scope));
499      }
500    }
501
502    self
503      .data
504      .verification_method
505      .remove(did_url)
506      .map(|method| (method, MethodScope::VerificationMethod))
507  }
508
509  /// Adds a new [`Service`] to the document.
510  ///
511  /// # Errors
512  ///
513  /// Returns an error if there already exists a service or verification method with the same identifier.
514  pub fn insert_service(&mut self, service: Service) -> Result<()> {
515    let service_id = service.id();
516    let id_exists = self
517      .verification_relationships()
518      .map(|method_ref| method_ref.id())
519      .chain(self.verification_method().iter().map(|method| method.id()))
520      .any(|id| id == service_id);
521
522    ((!id_exists) && self.data.service.append(service))
523      .then_some(())
524      .ok_or(Error::InvalidServiceInsertion)
525  }
526
527  /// Removes and returns a [`Service`] from the document if it exists.
528  pub fn remove_service(&mut self, id: &DIDUrl) -> Option<Service> {
529    self.data.service.remove(id)
530  }
531
532  /// Attaches the relationship to the method resolved by `method_query`.
533  ///
534  /// # Errors
535  ///
536  /// Returns an error if the method does not exist or if it is embedded.
537  /// To convert an embedded method into a generic verification method, remove it first
538  /// and insert it with [`MethodScope::VerificationMethod`].
539  pub fn attach_method_relationship<'query, Q>(
540    &mut self,
541    method_query: Q,
542    relationship: MethodRelationship,
543  ) -> Result<bool>
544  where
545    Q: Into<DIDUrlQuery<'query>>,
546  {
547    let method_query: DIDUrlQuery<'query> = method_query.into();
548
549    match self.resolve_method(method_query.clone(), Some(MethodScope::VerificationMethod)) {
550      None => match self.resolve_method(method_query, None) {
551        Some(_) => Err(Error::InvalidMethodEmbedded),
552        None => Err(Error::MethodNotFound),
553      },
554      Some(method) => {
555        let method_ref = MethodRef::Refer(method.id().clone());
556
557        let was_attached = match relationship {
558          MethodRelationship::Authentication => self.data.authentication.append(method_ref),
559          MethodRelationship::AssertionMethod => self.data.assertion_method.append(method_ref),
560          MethodRelationship::KeyAgreement => self.data.key_agreement.append(method_ref),
561          MethodRelationship::CapabilityDelegation => self.data.capability_delegation.append(method_ref),
562          MethodRelationship::CapabilityInvocation => self.data.capability_invocation.append(method_ref),
563        };
564
565        Ok(was_attached)
566      }
567    }
568  }
569
570  /// Detaches the relationship from the method resolved by `method_query`.
571  /// Returns `true` if the relationship was found and removed, `false` otherwise.
572  ///
573  /// # Errors
574  ///
575  /// Returns an error if the method does not exist or is embedded.
576  /// To remove an embedded method, use [`Self::remove_method`].
577  ///
578  /// # Note
579  ///
580  /// If the method is referenced in the given scope, but the document does not contain the referenced verification
581  /// method, then the reference will persist in the document (i.e. it is not removed).
582  pub fn detach_method_relationship<'query, Q>(
583    &mut self,
584    method_query: Q,
585    relationship: MethodRelationship,
586  ) -> Result<bool>
587  where
588    Q: Into<DIDUrlQuery<'query>>,
589  {
590    let method_query: DIDUrlQuery<'query> = method_query.into();
591    match self.resolve_method(method_query.clone(), Some(MethodScope::VerificationMethod)) {
592      None => match self.resolve_method(method_query, None) {
593        Some(_) => Err(Error::InvalidMethodEmbedded),
594        None => Err(Error::MethodNotFound),
595      },
596      Some(method) => {
597        let did_url: DIDUrl = method.id().clone();
598
599        let was_detached = match relationship {
600          MethodRelationship::Authentication => self.data.authentication.remove(&did_url),
601          MethodRelationship::AssertionMethod => self.data.assertion_method.remove(&did_url),
602          MethodRelationship::KeyAgreement => self.data.key_agreement.remove(&did_url),
603          MethodRelationship::CapabilityDelegation => self.data.capability_delegation.remove(&did_url),
604          MethodRelationship::CapabilityInvocation => self.data.capability_invocation.remove(&did_url),
605        };
606
607        Ok(was_detached.is_some())
608      }
609    }
610  }
611
612  /// Returns a `Vec` of verification method references whose verification relationship matches `scope`.
613  ///
614  /// If `scope` is `None`, an iterator over all **embedded** methods is returned.
615  pub fn methods(&self, scope: Option<MethodScope>) -> Vec<&VerificationMethod> {
616    if let Some(scope) = scope {
617      match scope {
618        MethodScope::VerificationMethod => self.verification_method().iter().collect(),
619        MethodScope::VerificationRelationship(MethodRelationship::AssertionMethod) => self
620          .assertion_method()
621          .iter()
622          .filter_map(|method_ref| self.resolve_method_ref(method_ref))
623          .collect(),
624        MethodScope::VerificationRelationship(MethodRelationship::Authentication) => self
625          .authentication()
626          .iter()
627          .filter_map(|method_ref| self.resolve_method_ref(method_ref))
628          .collect(),
629        MethodScope::VerificationRelationship(MethodRelationship::CapabilityDelegation) => self
630          .capability_delegation()
631          .iter()
632          .filter_map(|method_ref| self.resolve_method_ref(method_ref))
633          .collect(),
634        MethodScope::VerificationRelationship(MethodRelationship::CapabilityInvocation) => self
635          .capability_invocation()
636          .iter()
637          .filter_map(|method_ref| self.resolve_method_ref(method_ref))
638          .collect(),
639        MethodScope::VerificationRelationship(MethodRelationship::KeyAgreement) => self
640          .key_agreement()
641          .iter()
642          .filter_map(|method_ref| self.resolve_method_ref(method_ref))
643          .collect(),
644      }
645    } else {
646      self.all_methods().collect()
647    }
648  }
649
650  /// Returns an iterator over all embedded verification methods in the DID Document.
651  ///
652  /// This excludes verification methods that are referenced by the DID Document.
653  fn all_methods(&self) -> impl Iterator<Item = &VerificationMethod> {
654    fn __filter_ref(method: &MethodRef) -> Option<&VerificationMethod> {
655      match method {
656        MethodRef::Embed(method) => Some(method),
657        MethodRef::Refer(_) => None,
658      }
659    }
660
661    self
662      .data
663      .verification_method
664      .iter()
665      .chain(self.data.authentication.iter().filter_map(__filter_ref))
666      .chain(self.data.assertion_method.iter().filter_map(__filter_ref))
667      .chain(self.data.key_agreement.iter().filter_map(__filter_ref))
668      .chain(self.data.capability_delegation.iter().filter_map(__filter_ref))
669      .chain(self.data.capability_invocation.iter().filter_map(__filter_ref))
670  }
671
672  /// Returns an iterator over all verification relationships.
673  ///
674  /// This includes embedded and referenced [`VerificationMethods`](VerificationMethod).
675  pub fn verification_relationships(&self) -> impl Iterator<Item = &MethodRef> {
676    self
677      .data
678      .authentication
679      .iter()
680      .chain(self.data.assertion_method.iter())
681      .chain(self.data.key_agreement.iter())
682      .chain(self.data.capability_delegation.iter())
683      .chain(self.data.capability_invocation.iter())
684  }
685
686  /// Returns the first [`VerificationMethod`] with an `id` property matching the
687  /// provided `method_query` and the verification relationship specified by `scope` if present.
688  // NOTE: This method demonstrates unexpected behaviour in the edge cases where the document contains methods
689  // whose ids are of the form <did different from this document's>#<fragment>.
690  pub fn resolve_method<'query, 'me, Q>(
691    &'me self,
692    method_query: Q,
693    scope: Option<MethodScope>,
694  ) -> Option<&'me VerificationMethod>
695  where
696    Q: Into<DIDUrlQuery<'query>>,
697  {
698    match scope {
699      Some(scope) => {
700        let resolve_ref_helper = |method_ref: &'me MethodRef| self.resolve_method_ref(method_ref);
701
702        match scope {
703          MethodScope::VerificationMethod => self.data.verification_method.query(method_query.into()),
704          MethodScope::VerificationRelationship(MethodRelationship::Authentication) => self
705            .data
706            .authentication
707            .query(method_query.into())
708            .and_then(resolve_ref_helper),
709          MethodScope::VerificationRelationship(MethodRelationship::AssertionMethod) => self
710            .data
711            .assertion_method
712            .query(method_query.into())
713            .and_then(resolve_ref_helper),
714          MethodScope::VerificationRelationship(MethodRelationship::KeyAgreement) => self
715            .data
716            .key_agreement
717            .query(method_query.into())
718            .and_then(resolve_ref_helper),
719          MethodScope::VerificationRelationship(MethodRelationship::CapabilityDelegation) => self
720            .data
721            .capability_delegation
722            .query(method_query.into())
723            .and_then(resolve_ref_helper),
724          MethodScope::VerificationRelationship(MethodRelationship::CapabilityInvocation) => self
725            .data
726            .capability_invocation
727            .query(method_query.into())
728            .and_then(resolve_ref_helper),
729        }
730      }
731      None => self.resolve_method_inner(method_query.into()),
732    }
733  }
734
735  /// Returns a mutable reference to the first [`VerificationMethod`] with an `id` property
736  /// matching the provided `method_query`.
737  ///
738  /// # Warning
739  ///
740  /// Incorrect use of this method can lead to distinct document resources being identified by the same DID URL.
741  // NOTE: This method demonstrates unexpected behaviour in the edge cases where the document contains methods
742  // whose ids are of the form <did different from this document's>#<fragment>.
743  pub fn resolve_method_mut<'query, 'me, Q>(
744    &'me mut self,
745    method_query: Q,
746    scope: Option<MethodScope>,
747  ) -> Option<&'me mut VerificationMethod>
748  where
749    Q: Into<DIDUrlQuery<'query>>,
750  {
751    match scope {
752      Some(scope) => match scope {
753        MethodScope::VerificationMethod => self.data.verification_method.query_mut(method_query.into()),
754        MethodScope::VerificationRelationship(MethodRelationship::Authentication) => {
755          method_ref_mut_helper!(self, authentication, method_query)
756        }
757        MethodScope::VerificationRelationship(MethodRelationship::AssertionMethod) => {
758          method_ref_mut_helper!(self, assertion_method, method_query)
759        }
760        MethodScope::VerificationRelationship(MethodRelationship::KeyAgreement) => {
761          method_ref_mut_helper!(self, key_agreement, method_query)
762        }
763        MethodScope::VerificationRelationship(MethodRelationship::CapabilityDelegation) => {
764          method_ref_mut_helper!(self, capability_delegation, method_query)
765        }
766        MethodScope::VerificationRelationship(MethodRelationship::CapabilityInvocation) => {
767          method_ref_mut_helper!(self, capability_invocation, method_query)
768        }
769      },
770      None => self.resolve_method_mut_inner(method_query.into()),
771    }
772  }
773
774  /// Returns the first [`Service`] with an `id` property matching the provided `service_query`, if present.
775  // NOTE: This method demonstrates unexpected behavior in the edge cases where the document contains
776  // services whose ids are of the form <did different from this document's>#<fragment>.
777  pub fn resolve_service<'query, 'me, Q>(&'me self, service_query: Q) -> Option<&'me Service>
778  where
779    Q: Into<DIDUrlQuery<'query>>,
780  {
781    self.service().query(service_query.into())
782  }
783
784  #[doc(hidden)]
785  pub fn resolve_method_ref<'a>(&'a self, method_ref: &'a MethodRef) -> Option<&'a VerificationMethod> {
786    match method_ref {
787      MethodRef::Embed(method) => Some(method),
788      MethodRef::Refer(did) => self.data.verification_method.query(did),
789    }
790  }
791
792  fn resolve_method_inner(&self, query: DIDUrlQuery<'_>) -> Option<&VerificationMethod> {
793    let mut method: Option<&MethodRef> = None;
794
795    if method.is_none() {
796      method = self.data.authentication.query(query.clone());
797    }
798
799    if method.is_none() {
800      method = self.data.assertion_method.query(query.clone());
801    }
802
803    if method.is_none() {
804      method = self.data.key_agreement.query(query.clone());
805    }
806
807    if method.is_none() {
808      method = self.data.capability_delegation.query(query.clone());
809    }
810
811    if method.is_none() {
812      method = self.data.capability_invocation.query(query.clone());
813    }
814
815    match method {
816      Some(MethodRef::Embed(method)) => Some(method),
817      Some(MethodRef::Refer(did)) => self.data.verification_method.query(&did.to_string()),
818      None => self.data.verification_method.query(query),
819    }
820  }
821
822  fn resolve_method_mut_inner(&mut self, query: DIDUrlQuery<'_>) -> Option<&mut VerificationMethod> {
823    let mut method: Option<&mut MethodRef> = None;
824
825    if method.is_none() {
826      method = self.data.authentication.query_mut(query.clone());
827    }
828
829    if method.is_none() {
830      method = self.data.assertion_method.query_mut(query.clone());
831    }
832
833    if method.is_none() {
834      method = self.data.key_agreement.query_mut(query.clone());
835    }
836
837    if method.is_none() {
838      method = self.data.capability_delegation.query_mut(query.clone());
839    }
840
841    if method.is_none() {
842      method = self.data.capability_invocation.query_mut(query.clone());
843    }
844
845    match method {
846      Some(MethodRef::Embed(method)) => Some(method),
847      Some(MethodRef::Refer(did)) => self.data.verification_method.query_mut(&did.to_string()),
848      None => self.data.verification_method.query_mut(query),
849    }
850  }
851
852  /// Update the DID components of the document's `id`, controllers, methods and services by applying the provided
853  /// fallible maps.
854  ///
855  /// This is an advanced method that can be useful for DID methods that do not know the document's identifier prior
856  /// to publishing, but should preferably be avoided otherwise.
857  ///
858  /// # Errors
859  /// Any error is returned if any of the functions fail or the updates cause scoped method references to embedded
860  /// methods, or methods and services with identical identifiers in the document. In the case where illegal identifiers
861  /// are detected the supplied the `error_cast` function gets called in order to convert [`Error`] to `E`.
862  pub fn try_map<F, G, H, L, M, E>(
863    self,
864    id_update: F,
865    controller_update: G,
866    methods_update: H,
867    service_update: L,
868    error_cast: M,
869  ) -> Result<Self, E>
870  where
871    F: FnOnce(CoreDID) -> std::result::Result<CoreDID, E>,
872    G: FnMut(CoreDID) -> std::result::Result<CoreDID, E>,
873    H: FnMut(CoreDID) -> std::result::Result<CoreDID, E>,
874    L: FnMut(CoreDID) -> std::result::Result<CoreDID, E>,
875    M: FnOnce(crate::Error) -> E,
876  {
877    let data = self
878      .data
879      .try_map(id_update, controller_update, methods_update, service_update)?;
880    CoreDocument::try_from(data).map_err(error_cast)
881  }
882
883  /// Unchecked version of [Self::try_map](Self::try_map()).
884  pub fn map_unchecked<F, G, H, L>(
885    self,
886    id_update: F,
887    mut controller_update: G,
888    mut methods_update: H,
889    mut service_update: L,
890  ) -> Self
891  where
892    F: FnOnce(CoreDID) -> CoreDID,
893    G: FnMut(CoreDID) -> CoreDID,
894    H: FnMut(CoreDID) -> CoreDID,
895    L: FnMut(CoreDID) -> CoreDID,
896  {
897    type InfallibleCoreDIDResult = std::result::Result<CoreDID, Infallible>;
898
899    let id_map = |did: CoreDID| -> InfallibleCoreDIDResult { Ok(id_update(did)) };
900    let controller_map = |did: CoreDID| -> InfallibleCoreDIDResult { Ok(controller_update(did)) };
901    let method_map = |did: CoreDID| -> InfallibleCoreDIDResult { Ok(methods_update(did)) };
902    let services_map = |did: CoreDID| -> InfallibleCoreDIDResult { Ok(service_update(did)) };
903    let data = self
904      .data
905      .try_map(id_map, controller_map, method_map, services_map)
906      .expect("unwrapping infallible should be fine");
907    CoreDocument { data }
908  }
909}
910
911impl AsRef<CoreDocument> for CoreDocument {
912  fn as_ref(&self) -> &CoreDocument {
913    self
914  }
915}
916
917impl TryFrom<CoreDocumentData> for CoreDocument {
918  type Error = crate::error::Error;
919  fn try_from(value: CoreDocumentData) -> Result<Self, Self::Error> {
920    match value.check_id_constraints() {
921      Ok(_) => Ok(Self { data: value }),
922      Err(err) => Err(err),
923    }
924  }
925}
926
927impl Display for CoreDocument {
928  fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
929    self.fmt_json(f)
930  }
931}
932
933// =============================================================================
934// JWS verification
935// =============================================================================
936impl CoreDocument {
937  /// Decodes and verifies the provided JWS according to the passed [`JwsVerificationOptions`] and
938  /// [`JwsVerifier`].
939  ///
940  /// Regardless of which options are passed the following conditions must be met in order for a verification attempt to
941  /// take place.
942  /// - The JWS must be encoded according to the JWS compact serialization.
943  /// - The `kid` value in the protected header must be an identifier of a verification method in this DID document, or
944  ///   set explicitly in the `options`.
945  //
946  // NOTE: This is tested in `identity_storage` and `identity_credential`.
947  pub fn verify_jws<'jws, T: JwsVerifier>(
948    &self,
949    jws: &'jws str,
950    detached_payload: Option<&'jws [u8]>,
951    signature_verifier: &T,
952    options: &JwsVerificationOptions,
953  ) -> Result<DecodedJws<'jws>> {
954    let validation_item = Decoder::new()
955      .decode_compact_serialization(jws.as_bytes(), detached_payload)
956      .map_err(Error::JwsVerificationError)?;
957
958    let nonce: Option<&str> = options.nonce.as_deref();
959    // Validate the nonce
960    if validation_item.nonce() != nonce {
961      return Err(Error::JwsVerificationError(
962        identity_verification::jose::error::Error::InvalidParam("invalid nonce value"),
963      ));
964    }
965
966    let method_url_query: DIDUrlQuery<'_> = match &options.method_id {
967      Some(method_id) => method_id.into(),
968      None => validation_item
969        .kid()
970        .ok_or(Error::JwsVerificationError(
971          identity_verification::jose::error::Error::InvalidParam("missing kid value"),
972        ))?
973        .into(),
974    };
975
976    let public_key: &Jwk = self
977      .resolve_method(method_url_query, options.method_scope)
978      .ok_or(Error::MethodNotFound)?
979      .data()
980      .try_public_key_jwk()
981      .map_err(Error::InvalidKeyMaterial)?;
982
983    validation_item
984      .verify(signature_verifier, public_key)
985      .map_err(Error::JwsVerificationError)
986  }
987
988  /// Decodes and verifies the provided PQ/T JWS according to the passed [`JwsVerificationOptions`] with a
989  /// traditional [`JwsVerifier`] and PQ [`JwsVerifier`].
990  ///
991  /// Regardless of which options are passed the following conditions must be met in order for a verification attempt to
992  /// take place.
993  /// - The JWS must be encoded according to the JWS compact serialization.
994  /// - The `kid` value in the protected header must be an identifier of a verification method in this DID document, or
995  ///   set explicitly in the `options`.
996  //
997  // NOTE: This is tested in `identity_storage` and `identity_credential`.
998  pub fn verify_jws_hybrid<'jws, TRV: JwsVerifier, PQV: JwsVerifier>(
999    &self,
1000    jws: &'jws str,
1001    detached_payload: Option<&'jws [u8]>,
1002    traditional_verifier: &TRV,
1003    pq_verifier: &PQV,
1004    options: &JwsVerificationOptions,
1005  ) -> Result<DecodedJws<'jws>> {
1006    let validation_item = Decoder::new()
1007      .decode_compact_serialization(jws.as_bytes(), detached_payload)
1008      .map_err(Error::JwsVerificationError)?;
1009
1010    let nonce: Option<&str> = options.nonce.as_deref();
1011    // Validate the nonce
1012    if validation_item.nonce() != nonce {
1013      return Err(Error::JwsVerificationError(
1014        identity_verification::jose::error::Error::InvalidParam("invalid nonce value"),
1015      ));
1016    }
1017
1018    let method_url_query: DIDUrlQuery<'_> = match &options.method_id {
1019      Some(method_id) => method_id.into(),
1020      None => validation_item
1021        .kid()
1022        .ok_or(Error::JwsVerificationError(
1023          identity_verification::jose::error::Error::InvalidParam("missing kid value"),
1024        ))?
1025        .into(),
1026    };
1027
1028    let composite_public_key = self
1029      .resolve_method(method_url_query, options.method_scope)
1030      .ok_or(Error::MethodNotFound)?
1031      .data()
1032      .try_composite_public_key()
1033      .map_err(Error::InvalidKeyMaterial)?;
1034
1035    validation_item
1036      .verify_hybrid(
1037        traditional_verifier,
1038        pq_verifier,
1039        composite_public_key.traditional_public_key(),
1040        composite_public_key.pq_public_key(),
1041      )
1042      .map_err(Error::JwsVerificationError)
1043  }
1044}
1045
1046impl CoreDocument {
1047  /// Creates a [`CoreDocument`] from a did:jwk DID.
1048  pub fn expand_did_jwk(did_jwk: DIDJwk) -> Result<Self, Error> {
1049    let verification_method = VerificationMethod::try_from(did_jwk.clone()).map_err(Error::InvalidKeyMaterial)?;
1050    let verification_method_id = verification_method.id().clone();
1051
1052    DocumentBuilder::default()
1053      .id(did_jwk.into())
1054      .verification_method(verification_method)
1055      .assertion_method(verification_method_id.clone())
1056      .authentication(verification_method_id.clone())
1057      .capability_invocation(verification_method_id.clone())
1058      .capability_delegation(verification_method_id.clone())
1059      .build()
1060  }
1061}
1062
1063impl CoreDocument {
1064  /// Creates a [`CoreDocument`] from a did:compositejwk DID.
1065  pub fn expand_did_compositejwk(did_compositejwk: DIDCompositeJwk) -> Result<Self, Error> {
1066    let verification_method =
1067      VerificationMethod::try_from(did_compositejwk.clone()).map_err(Error::InvalidKeyMaterial)?;
1068    let verification_method_id = verification_method.id().clone();
1069
1070    DocumentBuilder::default()
1071      .id(did_compositejwk.into())
1072      .verification_method(verification_method)
1073      .assertion_method(verification_method_id.clone())
1074      .authentication(verification_method_id.clone())
1075      .capability_invocation(verification_method_id.clone())
1076      .capability_delegation(verification_method_id.clone())
1077      .build()
1078  }
1079}
1080
1081#[cfg(test)]
1082mod tests {
1083  use identity_core::convert::FromJson;
1084  use identity_core::convert::ToJson;
1085  use identity_did::DID;
1086  use identity_verification::MethodType;
1087
1088  use crate::service::ServiceBuilder;
1089  use identity_verification::MethodBuilder;
1090  use identity_verification::MethodData;
1091
1092  use super::*;
1093
1094  fn controller() -> CoreDID {
1095    "did:example:1234".parse().unwrap()
1096  }
1097
1098  fn method(controller: &CoreDID, fragment: &str) -> VerificationMethod {
1099    VerificationMethod::builder(Default::default())
1100      .id(controller.to_url().join(fragment).unwrap())
1101      .controller(controller.clone())
1102      .type_(MethodType::ED25519_VERIFICATION_KEY_2018)
1103      .data(MethodData::new_multibase(fragment.as_bytes()))
1104      .build()
1105      .unwrap()
1106  }
1107
1108  fn document() -> CoreDocument {
1109    let controller: CoreDID = controller();
1110
1111    CoreDocument::builder(Default::default())
1112      .id(controller.clone())
1113      .verification_method(method(&controller, "#key-1"))
1114      .verification_method(method(&controller, "#key-2"))
1115      .verification_method(method(&controller, "#key-3"))
1116      .authentication(method(&controller, "#auth-key"))
1117      .authentication(controller.to_url().join("#key-3").unwrap())
1118      .key_agreement(controller.to_url().join("#key-4").unwrap())
1119      .build()
1120      .unwrap()
1121  }
1122
1123  #[test]
1124  fn test_controller() {
1125    // One controller.
1126    {
1127      let mut document: CoreDocument = document();
1128      let expected: CoreDID = CoreDID::parse("did:example:one1234").unwrap();
1129      *document.controller_mut() = Some(OneOrSet::new_one(expected.clone()));
1130      assert_eq!(document.controller().unwrap().as_slice(), &[expected]);
1131      // Unset.
1132      *document.controller_mut() = None;
1133      assert!(document.controller().is_none());
1134    }
1135
1136    // Many controllers.
1137    {
1138      let mut document: CoreDocument = document();
1139      let expected_controllers: Vec<CoreDID> = vec![
1140        CoreDID::parse("did:example:many1234").unwrap(),
1141        CoreDID::parse("did:example:many4567").unwrap(),
1142        CoreDID::parse("did:example:many8910").unwrap(),
1143      ];
1144      *document.controller_mut() = Some(expected_controllers.clone().try_into().unwrap());
1145      assert_eq!(document.controller().unwrap().as_slice(), &expected_controllers);
1146      // Unset.
1147      *document.controller_mut() = None;
1148      assert!(document.controller().is_none());
1149    }
1150  }
1151
1152  #[rustfmt::skip]
1153  #[test]
1154  fn test_resolve_method() {
1155    let document: CoreDocument = document();
1156
1157    // Resolve methods by fragment.
1158    assert_eq!(document.resolve_method("#key-1", None).unwrap().id().to_string(), "did:example:1234#key-1");
1159    assert_eq!(document.resolve_method("#key-2", None).unwrap().id().to_string(), "did:example:1234#key-2");
1160    assert_eq!(document.resolve_method("#key-3", None).unwrap().id().to_string(), "did:example:1234#key-3");
1161
1162    // Fine to omit the octothorpe.
1163    assert_eq!(document.resolve_method("key-1", None).unwrap().id().to_string(), "did:example:1234#key-1");
1164    assert_eq!(document.resolve_method("key-2", None).unwrap().id().to_string(), "did:example:1234#key-2");
1165    assert_eq!(document.resolve_method("key-3", None).unwrap().id().to_string(), "did:example:1234#key-3");
1166
1167    // Resolve methods by full DID Url id.
1168    assert_eq!(document.resolve_method("did:example:1234#key-1", None).unwrap().id().to_string(), "did:example:1234#key-1");
1169    assert_eq!(document.resolve_method("did:example:1234#key-2", None).unwrap().id().to_string(), "did:example:1234#key-2");
1170    assert_eq!(document.resolve_method("did:example:1234#key-3", None).unwrap().id().to_string(), "did:example:1234#key-3");
1171
1172    // Scope.
1173    assert_eq!(
1174      document.resolve_method("#key-1", Some(MethodScope::VerificationMethod)).unwrap().id().to_string(), "did:example:1234#key-1"
1175    );
1176  }
1177
1178  #[rustfmt::skip]
1179  #[test]
1180  fn test_resolve_method_mut() {
1181    let mut document: CoreDocument = document();
1182
1183    // Resolve methods by fragment.
1184    assert_eq!(document.resolve_method_mut("#key-1", None).unwrap().id().to_string(), "did:example:1234#key-1");
1185    assert_eq!(document.resolve_method_mut("#key-3", None).unwrap().id().to_string(), "did:example:1234#key-3");
1186    assert_eq!(document.resolve_method_mut("#key-2", None).unwrap().id().to_string(), "did:example:1234#key-2");
1187
1188    // Fine to omit the octothorpe.
1189    assert_eq!(document.resolve_method_mut("key-1", None).unwrap().id().to_string(), "did:example:1234#key-1");
1190    assert_eq!(document.resolve_method_mut("key-2", None).unwrap().id().to_string(), "did:example:1234#key-2");
1191    assert_eq!(document.resolve_method_mut("key-3", None).unwrap().id().to_string(), "did:example:1234#key-3");
1192
1193    // Resolve methods by full DID Url id.
1194    assert_eq!(document.resolve_method_mut("did:example:1234#key-1", None).unwrap().id().to_string(), "did:example:1234#key-1");
1195    assert_eq!(document.resolve_method_mut("did:example:1234#key-2", None).unwrap().id().to_string(), "did:example:1234#key-2");
1196    assert_eq!(document.resolve_method_mut("did:example:1234#key-3", None).unwrap().id().to_string(), "did:example:1234#key-3");
1197
1198    // Resolve with scope.
1199    assert_eq!(
1200      document.resolve_method_mut("#key-1", Some(MethodScope::VerificationMethod)).unwrap().id().to_string(), "did:example:1234#key-1"
1201    );
1202  }
1203
1204  #[test]
1205  fn test_resolve_method_fails() {
1206    let document: CoreDocument = document();
1207
1208    // Resolving an existing reference to a missing method returns None.
1209    assert_eq!(document.resolve_method("#key-4", None), None);
1210
1211    // Resolving a plain DID returns None.
1212    assert_eq!(document.resolve_method("did:example:1234", None), None);
1213
1214    // Resolving an empty string returns None.
1215    assert_eq!(document.resolve_method("", None), None);
1216
1217    // Resolve with scope.
1218    assert_eq!(
1219      document.resolve_method("#key-1", Some(MethodScope::key_agreement())),
1220      None
1221    );
1222  }
1223
1224  #[test]
1225  fn test_resolve_method_mut_fails() {
1226    let mut document: CoreDocument = document();
1227
1228    // Resolving an existing reference to a missing method returns None.
1229    assert_eq!(document.resolve_method_mut("#key-4", None), None);
1230
1231    // Resolving a plain DID returns None.
1232    assert_eq!(document.resolve_method_mut("did:example:1234", None), None);
1233
1234    // Resolving an empty string returns None.
1235    assert_eq!(document.resolve_method_mut("", None), None);
1236
1237    // Resolve with scope.
1238    assert_eq!(
1239      document.resolve_method_mut("#key-1", Some(MethodScope::key_agreement())),
1240      None
1241    );
1242  }
1243
1244  #[rustfmt::skip]
1245  #[test]
1246  fn test_methods_index() {
1247    let document: CoreDocument = document();
1248
1249    // Access methods by index.
1250    assert_eq!(document.methods(None).first().unwrap().id().to_string(), "did:example:1234#key-1");
1251    assert_eq!(document.methods(None).get(2).unwrap().id().to_string(), "did:example:1234#key-3");
1252  }
1253
1254  #[test]
1255  fn test_methods_scope() {
1256    let document: CoreDocument = document();
1257
1258    // VerificationMethod
1259    let verification_methods: Vec<&VerificationMethod> = document.methods(Some(MethodScope::VerificationMethod));
1260    assert_eq!(
1261      verification_methods.first().unwrap().id().to_string(),
1262      "did:example:1234#key-1"
1263    );
1264    assert_eq!(
1265      verification_methods.get(1).unwrap().id().to_string(),
1266      "did:example:1234#key-2"
1267    );
1268    assert_eq!(
1269      verification_methods.get(2).unwrap().id().to_string(),
1270      "did:example:1234#key-3"
1271    );
1272    assert_eq!(verification_methods.len(), 3);
1273
1274    // Authentication
1275    let authentication: Vec<&VerificationMethod> = document.methods(Some(MethodScope::authentication()));
1276    assert_eq!(
1277      authentication.first().unwrap().id().to_string(),
1278      "did:example:1234#auth-key"
1279    );
1280    assert_eq!(
1281      authentication.get(1).unwrap().id().to_string(),
1282      "did:example:1234#key-3"
1283    );
1284    assert_eq!(authentication.len(), 2);
1285  }
1286
1287  #[test]
1288  fn test_attach_verification_relationships() {
1289    let mut document: CoreDocument = document();
1290
1291    let fragment = "#attach-test";
1292    let method = method(document.id(), fragment);
1293    document.insert_method(method, MethodScope::VerificationMethod).unwrap();
1294
1295    assert!(document
1296      .attach_method_relationship(
1297        document.id().to_url().join(fragment).unwrap(),
1298        MethodRelationship::CapabilityDelegation,
1299      )
1300      .unwrap());
1301
1302    assert_eq!(document.verification_relationships().count(), 4);
1303
1304    // Adding it a second time is not an error, but returns false (idempotent).
1305    assert!(!document
1306      .attach_method_relationship(
1307        document.id().to_url().join(fragment).unwrap(),
1308        MethodRelationship::CapabilityDelegation,
1309      )
1310      .unwrap());
1311
1312    // len is still 2.
1313    assert_eq!(document.verification_relationships().count(), 4);
1314
1315    // Attempting to attach a relationship to a non-existing method fails.
1316    assert!(document
1317      .attach_method_relationship(
1318        document.id().to_url().join("#doesNotExist").unwrap(),
1319        MethodRelationship::CapabilityDelegation,
1320      )
1321      .is_err());
1322
1323    // Attempt to attach to an embedded method.
1324    assert!(document
1325      .attach_method_relationship(
1326        document.id().to_url().join("#auth-key").unwrap(),
1327        MethodRelationship::CapabilityDelegation,
1328      )
1329      .is_err());
1330  }
1331
1332  #[test]
1333  fn test_detach_verification_relationships() {
1334    let mut document: CoreDocument = document();
1335
1336    let fragment = "#detach-test";
1337    let method = method(document.id(), fragment);
1338    document.insert_method(method, MethodScope::VerificationMethod).unwrap();
1339
1340    assert!(document
1341      .attach_method_relationship(
1342        document.id().to_url().join(fragment).unwrap(),
1343        MethodRelationship::AssertionMethod,
1344      )
1345      .is_ok());
1346
1347    assert!(document
1348      .detach_method_relationship(
1349        document.id().to_url().join(fragment).unwrap(),
1350        MethodRelationship::AssertionMethod,
1351      )
1352      .unwrap());
1353
1354    // len is 1; the relationship was removed.
1355    assert_eq!(document.verification_relationships().count(), 3);
1356
1357    // Removing it a second time is not an error, but returns false (idempotent).
1358    assert!(!document
1359      .detach_method_relationship(
1360        document.id().to_url().join(fragment).unwrap(),
1361        MethodRelationship::AssertionMethod,
1362      )
1363      .unwrap());
1364
1365    // len is still 1.
1366    assert_eq!(document.verification_relationships().count(), 3);
1367
1368    // Attempting to detach a relationship from a non-existing method fails.
1369    assert!(document
1370      .detach_method_relationship(
1371        document.id().to_url().join("#doesNotExist").unwrap(),
1372        MethodRelationship::AssertionMethod,
1373      )
1374      .is_err());
1375  }
1376
1377  #[test]
1378  fn test_method_insert_duplication() {
1379    let mut document: CoreDocument = document();
1380
1381    let fragment = "#duplication-test";
1382    let method1 = method(document.id(), fragment);
1383    assert!(document
1384      .insert_method(method1.clone(), MethodScope::VerificationMethod)
1385      .is_ok());
1386    assert!(document
1387      .insert_method(method1.clone(), MethodScope::VerificationMethod)
1388      .is_err());
1389    assert!(document
1390      .insert_method(method1.clone(), MethodScope::authentication())
1391      .is_err());
1392
1393    let fragment = "#duplication-test-2";
1394    let method2 = method(document.id(), fragment);
1395    assert!(document.insert_method(method2, MethodScope::assertion_method()).is_ok());
1396    assert!(document
1397      .insert_method(method1.clone(), MethodScope::VerificationMethod)
1398      .is_err());
1399    assert!(document
1400      .insert_method(method1, MethodScope::capability_delegation())
1401      .is_err());
1402  }
1403
1404  #[test]
1405  fn test_method_remove_existence() {
1406    let mut document: CoreDocument = document();
1407
1408    let fragment = "#existence-test";
1409    let method1 = method(document.id(), fragment);
1410    assert!(document
1411      .insert_method(method1.clone(), MethodScope::VerificationMethod)
1412      .is_ok());
1413    assert_eq!(method1, document.remove_method(method1.id()).unwrap());
1414    assert!(document.remove_method(method1.id()).is_none());
1415
1416    let fragment = "#existence-test-2";
1417    let method2 = method(document.id(), fragment);
1418    assert!(document.insert_method(method2, MethodScope::assertion_method()).is_ok());
1419    assert!(document.remove_method(method1.id()).is_none());
1420    assert!(document.remove_method(method1.id()).is_none());
1421
1422    let fragment = "#removal-test-3";
1423    let method3 = method(document.id(), fragment);
1424    assert!(document
1425      .insert_method(method3.clone(), MethodScope::VerificationMethod)
1426      .is_ok());
1427    assert!(document
1428      .attach_method_relationship(fragment, MethodRelationship::CapabilityDelegation)
1429      .is_ok());
1430
1431    assert_eq!(method3, document.remove_method(method3.id()).unwrap());
1432
1433    // Ensure *all* references were removed.
1434    assert!(document.capability_delegation().query(method3.id()).is_none());
1435    assert!(document.verification_method().query(method3.id()).is_none());
1436  }
1437
1438  #[test]
1439  fn test_service_updates() {
1440    let mut document = document();
1441    let service_id = document.id().to_url().join("#service-update-test").unwrap();
1442    let service_type = "test";
1443    let service_endpoint = Url::parse("https://example.com").unwrap();
1444
1445    let service: Service = ServiceBuilder::default()
1446      .id(service_id)
1447      .type_(service_type)
1448      .service_endpoint(service_endpoint)
1449      .build()
1450      .unwrap();
1451    // inserting a service with an identifier not present in the document should be Ok.
1452    assert!(document.insert_service(service.clone()).is_ok());
1453    // inserting a service with the same identifier as an already existing service should fail.
1454    let mut service_clone = service.clone();
1455    *service_clone.service_endpoint_mut() = Url::parse("https://other-example.com").unwrap().into();
1456    assert!(document.insert_service(service_clone).is_err());
1457    // removing an existing service should succeed
1458    assert_eq!(service, document.remove_service(service.id()).unwrap());
1459    // it should now be possible to insert the service again
1460    assert!(document.insert_service(service.clone()).is_ok());
1461
1462    // inserting a method with the same identifier as an existing service should fail
1463    let method: VerificationMethod = MethodBuilder::default()
1464      .type_(MethodType::ED25519_VERIFICATION_KEY_2018)
1465      .data(MethodData::PublicKeyBase58(
1466        "3M5RCDjPTWPkKSN3sxUmmMqHbmRPegYP1tjcKyrDbt9J".into(),
1467      ))
1468      .id(service.id().clone())
1469      .controller(document.id().clone())
1470      .build()
1471      .unwrap();
1472
1473    let method_scopes = [
1474      MethodScope::VerificationMethod,
1475      MethodScope::assertion_method(),
1476      MethodScope::authentication(),
1477      MethodScope::key_agreement(),
1478      MethodScope::capability_delegation(),
1479      MethodScope::capability_invocation(),
1480    ];
1481    for scope in method_scopes {
1482      let mut document_clone = document.clone();
1483      assert!(document_clone.insert_method(method.clone(), scope).is_err());
1484      // should succeed after removing the service
1485      assert!(document_clone.remove_service(service.id()).is_some());
1486      assert!(document_clone.insert_method(method.clone(), scope).is_ok());
1487    }
1488
1489    // inserting a service with the same identifier as a method should fail
1490    for scope in method_scopes {
1491      let mut doc_clone = document.clone();
1492      let valid_method_id = document.id().to_url().join("#valid-method-identifier").unwrap();
1493      let mut valid_method = method.clone();
1494      valid_method.set_id(valid_method_id.clone()).unwrap();
1495      // make sure that the method actually gets inserted
1496      assert!(doc_clone.insert_method(valid_method.clone(), scope).is_ok());
1497      let mut service_clone = service.clone();
1498      service_clone.set_id(valid_method_id).unwrap();
1499      assert!(doc_clone.insert_service(service_clone.clone()).is_err());
1500      // but should work after the method has been removed
1501      assert!(doc_clone.remove_method(valid_method.id()).is_some());
1502      assert!(doc_clone.insert_service(service_clone).is_ok());
1503    }
1504
1505    //removing a service that does not exist should fail
1506    assert!(document
1507      .remove_service(&service.id().join("#service-does-not-exist").unwrap())
1508      .is_none());
1509  }
1510
1511  #[test]
1512  fn serialize_deserialize_roundtrip() {
1513    let document: CoreDocument = document();
1514    let doc_json: String = document.to_json().unwrap();
1515    let doc_json_value: serde_json::Value = document.to_json_value().unwrap();
1516    let doc_json_vec: Vec<u8> = document.to_json_vec().unwrap();
1517    assert_eq!(document, CoreDocument::from_json(&doc_json).unwrap());
1518    assert_eq!(document, CoreDocument::from_json_value(doc_json_value).unwrap());
1519
1520    assert_eq!(document, CoreDocument::from_json_slice(&doc_json_vec).unwrap());
1521  }
1522
1523  #[test]
1524  fn deserialize_valid() {
1525    // The verification method types here are really Ed25519VerificationKey2020, changed to be compatible
1526    // with the current version of this library.
1527    const JSON_DOCUMENT: &str = r#"{
1528      "@context": [
1529        "https://www.w3.org/ns/did/v1",
1530        "https://w3id.org/security/suites/ed25519-2020/v1"
1531      ],
1532      "id": "did:example:123",
1533      "authentication": [
1534        {
1535          "id": "did:example:123#z6MkecaLyHuYWkayBDLw5ihndj3T1m6zKTGqau3A51G7RBf3",
1536          "type": "Ed25519VerificationKey2018",
1537          "controller": "did:example:123",
1538          "publicKeyMultibase": "zAKJP3f7BD6W4iWEQ9jwndVTCBq8ua2Utt8EEjJ6Vxsf"
1539        }
1540      ],
1541      "capabilityInvocation": [
1542        {
1543          "id": "did:example:123#z6MkhdmzFu659ZJ4XKj31vtEDmjvsi5yDZG5L7Caz63oP39k",
1544          "type": "Ed25519VerificationKey2018",
1545          "controller": "did:example:123",
1546          "publicKeyMultibase": "z4BWwfeqdp1obQptLLMvPNgBw48p7og1ie6Hf9p5nTpNN"
1547        }
1548      ],
1549      "capabilityDelegation": [
1550        {
1551          "id": "did:example:123#z6Mkw94ByR26zMSkNdCUi6FNRsWnc2DFEeDXyBGJ5KTzSWyi",
1552          "type": "Ed25519VerificationKey2018",
1553          "controller": "did:example:123",
1554          "publicKeyMultibase": "zHgo9PAmfeoxHG8Mn2XHXamxnnSwPpkyBHAMNF3VyXJCL"
1555        }
1556      ],
1557      "assertionMethod": [
1558        {
1559          "id": "did:example:123#z6MkiukuAuQAE8ozxvmahnQGzApvtW7KT5XXKfojjwbdEomY",
1560          "type": "Ed25519VerificationKey2018",
1561          "controller": "did:example:123",
1562          "publicKeyMultibase": "z5TVraf9itbKXrRvt2DSS95Gw4vqU3CHAdetoufdcKazA"
1563        }
1564      ]
1565  }"#;
1566    let doc: std::result::Result<CoreDocument, Box<dyn std::error::Error>> =
1567      CoreDocument::from_json(JSON_DOCUMENT).map_err(Into::into);
1568    // Print debug representation if the test fails.
1569    dbg!(&doc);
1570    assert!(doc.is_ok());
1571  }
1572
1573  #[test]
1574  fn deserialize_duplicate_method_different_scopes() {
1575    const JSON_VERIFICATION_METHOD_KEY_AGREEMENT: &str = r#"{
1576      "id": "did:example:1234",
1577      "verificationMethod": [
1578        {
1579          "id": "did:example:1234#key1",
1580          "controller": "did:example:1234",
1581          "type": "Ed25519VerificationKey2018",
1582          "publicKeyBase58": "3M5RCDjPTWPkKSN3sxUmmMqHbmRPegYP1tjcKyrDbt9J"
1583        }
1584      ],
1585      "keyAgreement": [
1586        {
1587          "id": "did:example:1234#key1",
1588          "controller": "did:example:1234",
1589          "type": "X25519KeyAgreementKey2019",
1590          "publicKeyBase58": "FbQWLPRhTH95MCkQUeFYdiSoQt8zMwetqfWoxqPgaq7x"
1591        }
1592      ]
1593    }"#;
1594
1595    const JSON_KEY_AGREEMENT_CAPABILITY_INVOCATION: &str = r#"{
1596      "id": "did:example:1234",
1597      "capabilityInvocation": [
1598        {
1599          "id": "did:example:1234#key1",
1600          "controller": "did:example:1234",
1601          "type": "Ed25519VerificationKey2018",
1602          "publicKeyBase58": "3M5RCDjPTWPkKSN3sxUmmMqHbmRPegYP1tjcKyrDbt9J"
1603        }
1604      ],
1605      "keyAgreement": [
1606        {
1607          "id": "did:example:1234#key1",
1608          "controller": "did:example:1234",
1609          "type": "X25519KeyAgreementKey2019",
1610          "publicKeyBase58": "FbQWLPRhTH95MCkQUeFYdiSoQt8zMwetqfWoxqPgaq7x"
1611        }
1612      ]
1613    }"#;
1614
1615    const JSON_ASSERTION_METHOD_CAPABILITY_INVOCATION: &str = r#"{
1616      "id": "did:example:1234",
1617      "assertionMethod": [
1618        {
1619          "id": "did:example:1234#key1",
1620          "controller": "did:example:1234",
1621          "type": "Ed25519VerificationKey2018",
1622          "publicKeyBase58": "H3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV"
1623        }
1624      ],
1625      "capabilityInvocation": [
1626        {
1627          "id": "did:example:1234#key1",
1628          "controller": "did:example:1234",
1629          "type": "Ed25519VerificationKey2018",
1630          "publicKeyBase58": "3M5RCDjPTWPkKSN3sxUmmMqHbmRPegYP1tjcKyrDbt9J"
1631        }
1632      ]
1633    }"#;
1634
1635    const JSON_VERIFICATION_METHOD_AUTHENTICATION: &str = r#"{
1636      "id": "did:example:1234",
1637      "verificationMethod": [
1638        {
1639          "id": "did:example:1234#key1",
1640          "controller": "did:example:1234",
1641          "type": "Ed25519VerificationKey2018",
1642          "publicKeyBase58": "3M5RCDjPTWPkKSN3sxUmmMqHbmRPegYP1tjcKyrDbt9J"
1643        }
1644      ],
1645      "authentication": [
1646        {
1647          "id": "did:example:1234#key1",
1648          "controller": "did:example:1234",
1649          "type": "Ed25519VerificationKey2018",
1650          "publicKeyBase58": "H3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV"
1651        }
1652      ]
1653    }"#;
1654
1655    const JSON_CAPABILITY_DELEGATION_ASSERTION_METHOD: &str = r#"{
1656      "id": "did:example:1234",
1657      "capabilityDelegation": [
1658        {
1659          "id": "did:example:1234#key1",
1660          "controller": "did:example:1234",
1661          "type": "Ed25519VerificationKey2018",
1662          "publicKeyBase58": "3M5RCDjPTWPkKSN3sxUmmMqHbmRPegYP1tjcKyrDbt9J"
1663        }
1664      ],
1665      "assertionMethod": [
1666        {
1667          "id": "did:example:1234#key1",
1668          "controller": "did:example:1234",
1669          "type": "Ed25519VerificationKey2018",
1670          "publicKeyBase58": "H3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV"
1671        }
1672      ]
1673    }"#;
1674
1675    let verifier = |json: &str| {
1676      let result: std::result::Result<CoreDocument, Box<dyn std::error::Error>> =
1677        CoreDocument::from_json(json).map_err(Into::into);
1678      // Print the json if the test fails to aid debugging.
1679      println!("the following non-spec compliant document was deserialized: \n {json}");
1680      assert!(result.is_err());
1681    };
1682
1683    for json in [
1684      JSON_VERIFICATION_METHOD_KEY_AGREEMENT,
1685      JSON_KEY_AGREEMENT_CAPABILITY_INVOCATION,
1686      JSON_ASSERTION_METHOD_CAPABILITY_INVOCATION,
1687      JSON_VERIFICATION_METHOD_AUTHENTICATION,
1688      JSON_CAPABILITY_DELEGATION_ASSERTION_METHOD,
1689    ] {
1690      verifier(json);
1691    }
1692  }
1693
1694  #[test]
1695  fn deserialize_invalid_id_references() {
1696    const JSON_KEY_AGREEMENT_CAPABILITY_INVOCATION: &str = r#"{
1697      "id": "did:example:1234",
1698      "capabilityInvocation": [
1699        "did:example:1234#key1"
1700      ],
1701      "keyAgreement": [
1702        {
1703          "id": "did:example:1234#key1",
1704          "controller": "did:example:1234",
1705          "type": "X25519KeyAgreementKey2019",
1706          "publicKeyBase58": "FbQWLPRhTH95MCkQUeFYdiSoQt8zMwetqfWoxqPgaq7x"
1707        }
1708      ]
1709    }"#;
1710
1711    const JSON_ASSERTION_METHOD_CAPABILITY_INVOCATION: &str = r#"{
1712      "id": "did:example:1234",
1713      "assertionMethod": [
1714        "did:example:1234#key1", 
1715        {
1716          "id": "did:example:1234#key2",
1717          "controller": "did:example:1234",
1718          "type": "Ed25519VerificationKey2018",
1719          "publicKeyBase58": "H3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV"
1720        }
1721      ],
1722      "capabilityInvocation": [
1723        {
1724          "id": "did:example:1234#key1",
1725          "controller": "did:example:1234",
1726          "type": "Ed25519VerificationKey2018",
1727          "publicKeyBase58": "3M5RCDjPTWPkKSN3sxUmmMqHbmRPegYP1tjcKyrDbt9J"
1728        }
1729      ]
1730    }"#;
1731
1732    const JSON_AUTHENTICATION_KEY_AGREEMENT: &str = r#"{
1733      "id": "did:example:1234",
1734      "keyAgreement": [
1735         "did:example:1234#key1"
1736      ],
1737      "authentication": [
1738        {
1739          "id": "did:example:1234#key1",
1740          "controller": "did:example:1234",
1741          "type": "Ed25519VerificationKey2018",
1742          "publicKeyMultibase": "zH3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV"
1743        }
1744      ]
1745    }"#;
1746
1747    const JSON_CAPABILITY_DELEGATION_ASSERTION_METHOD: &str = r#"{
1748      "id": "did:example:1234",
1749      "capabilityDelegation": [
1750        "did:example:1234#key1"
1751      ],
1752      "assertionMethod": [
1753        {
1754          "id": "did:example:1234#key1",
1755          "controller": "did:example:1234",
1756          "type": "X25519KeyAgreementKey2019",
1757          "publicKeyBase58": "FbQWLPRhTH95MCkQUeFYdiSoQt8zMwetqfWoxqPgaq7x"
1758        }
1759      ]
1760    }"#;
1761
1762    let verifier = |json: &str| {
1763      let result: std::result::Result<CoreDocument, Box<dyn std::error::Error>> =
1764        CoreDocument::from_json(json).map_err(Into::into);
1765      // Print the json if the test fails to aid debugging.
1766      println!("the following non-spec compliant document was deserialized: \n {json}");
1767      assert!(result.is_err());
1768    };
1769
1770    for json in [
1771      JSON_KEY_AGREEMENT_CAPABILITY_INVOCATION,
1772      JSON_ASSERTION_METHOD_CAPABILITY_INVOCATION,
1773      JSON_AUTHENTICATION_KEY_AGREEMENT,
1774      JSON_CAPABILITY_DELEGATION_ASSERTION_METHOD,
1775    ] {
1776      verifier(json);
1777    }
1778  }
1779
1780  #[test]
1781  fn test_did_jwk_expansion() {
1782    let did_jwk = "did:jwk:eyJrdHkiOiJPS1AiLCJjcnYiOiJYMjU1MTkiLCJ1c2UiOiJlbmMiLCJ4IjoiM3A3YmZYdDl3YlRUVzJIQzdPUTFOei1EUThoYmVHZE5yZngtRkctSUswOCJ9"
1783      .parse::<DIDJwk>()
1784      .unwrap();
1785    let target_doc = serde_json::from_value(serde_json::json!({
1786      "id": "did:jwk:eyJrdHkiOiJPS1AiLCJjcnYiOiJYMjU1MTkiLCJ1c2UiOiJlbmMiLCJ4IjoiM3A3YmZYdDl3YlRUVzJIQzdPUTFOei1EUThoYmVHZE5yZngtRkctSUswOCJ9",
1787      "verificationMethod": [
1788        {
1789          "id": "did:jwk:eyJrdHkiOiJPS1AiLCJjcnYiOiJYMjU1MTkiLCJ1c2UiOiJlbmMiLCJ4IjoiM3A3YmZYdDl3YlRUVzJIQzdPUTFOei1EUThoYmVHZE5yZngtRkctSUswOCJ9#0",
1790          "type": "JsonWebKey2020",
1791          "controller": "did:jwk:eyJrdHkiOiJPS1AiLCJjcnYiOiJYMjU1MTkiLCJ1c2UiOiJlbmMiLCJ4IjoiM3A3YmZYdDl3YlRUVzJIQzdPUTFOei1EUThoYmVHZE5yZngtRkctSUswOCJ9",
1792          "publicKeyJwk": {
1793            "kty":"OKP",
1794            "crv":"X25519",
1795            "use":"enc",
1796            "x":"3p7bfXt9wbTTW2HC7OQ1Nz-DQ8hbeGdNrfx-FG-IK08"
1797          }
1798        }
1799      ],
1800      "assertionMethod": ["did:jwk:eyJrdHkiOiJPS1AiLCJjcnYiOiJYMjU1MTkiLCJ1c2UiOiJlbmMiLCJ4IjoiM3A3YmZYdDl3YlRUVzJIQzdPUTFOei1EUThoYmVHZE5yZngtRkctSUswOCJ9#0"],
1801      "authentication": ["did:jwk:eyJrdHkiOiJPS1AiLCJjcnYiOiJYMjU1MTkiLCJ1c2UiOiJlbmMiLCJ4IjoiM3A3YmZYdDl3YlRUVzJIQzdPUTFOei1EUThoYmVHZE5yZngtRkctSUswOCJ9#0"],
1802      "capabilityInvocation": ["did:jwk:eyJrdHkiOiJPS1AiLCJjcnYiOiJYMjU1MTkiLCJ1c2UiOiJlbmMiLCJ4IjoiM3A3YmZYdDl3YlRUVzJIQzdPUTFOei1EUThoYmVHZE5yZngtRkctSUswOCJ9#0"],
1803      "capabilityDelegation": ["did:jwk:eyJrdHkiOiJPS1AiLCJjcnYiOiJYMjU1MTkiLCJ1c2UiOiJlbmMiLCJ4IjoiM3A3YmZYdDl3YlRUVzJIQzdPUTFOei1EUThoYmVHZE5yZngtRkctSUswOCJ9#0"]
1804    })).unwrap();
1805
1806    assert_eq!(CoreDocument::expand_did_jwk(did_jwk).unwrap(), target_doc);
1807  }
1808}