1use core::convert::TryInto as _;
5use core::fmt::Display;
6use core::fmt::Formatter;
7use std::collections::HashMap;
8use std::convert::Infallible;
9
10use identity_did::DIDJwk;
11use identity_verification::jose::jwk::Jwk;
12use identity_verification::jose::jws::DecodedJws;
13use identity_verification::jose::jws::Decoder;
14use identity_verification::jose::jws::JwsVerifier;
15use serde::Serialize;
16
17use identity_core::common::Object;
18use identity_core::common::OneOrSet;
19use identity_core::common::OrderedSet;
20use identity_core::common::Url;
21use identity_core::convert::FmtJson;
22use serde::Serializer;
23
24use crate::document::DocumentBuilder;
25use crate::error::Error;
26use crate::error::Result;
27use crate::service::Service;
28use crate::utils::DIDUrlQuery;
29use crate::utils::Queryable;
30use crate::verifiable::JwsVerificationOptions;
31use identity_did::CoreDID;
32use identity_did::DIDUrl;
33use identity_verification::MethodRef;
34use identity_verification::MethodRelationship;
35use identity_verification::MethodScope;
36use identity_verification::VerificationMethod;
37
38#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
39#[rustfmt::skip]
40pub(crate) struct CoreDocumentData
41{
42 pub(crate) id: CoreDID,
43 #[serde(skip_serializing_if = "Option::is_none")]
44 pub(crate) controller: Option<OneOrSet<CoreDID>>,
45 #[serde(default = "Default::default", rename = "alsoKnownAs", skip_serializing_if = "OrderedSet::is_empty")]
46 pub(crate) also_known_as: OrderedSet<Url>,
47 #[serde(default = "Default::default", rename = "verificationMethod", skip_serializing_if = "OrderedSet::is_empty")]
48 pub(crate) verification_method: OrderedSet<VerificationMethod>,
49 #[serde(default = "Default::default", skip_serializing_if = "OrderedSet::is_empty")]
50 pub(crate) authentication: OrderedSet<MethodRef>,
51 #[serde(default = "Default::default", rename = "assertionMethod", skip_serializing_if = "OrderedSet::is_empty")]
52 pub(crate) assertion_method: OrderedSet<MethodRef>,
53 #[serde(default = "Default::default", rename = "keyAgreement", skip_serializing_if = "OrderedSet::is_empty")]
54 pub(crate) key_agreement: OrderedSet<MethodRef>,
55 #[serde(default = "Default::default", rename = "capabilityDelegation", skip_serializing_if = "OrderedSet::is_empty")]
56 pub(crate) capability_delegation: OrderedSet<MethodRef>,
57 #[serde(default = "Default::default", rename = "capabilityInvocation", skip_serializing_if = "OrderedSet::is_empty")]
58 pub(crate) capability_invocation: OrderedSet<MethodRef>,
59 #[serde(default = "Default::default", skip_serializing_if = "OrderedSet::is_empty")]
60 pub(crate) service: OrderedSet<Service>,
61 #[serde(flatten)]
62 pub(crate) properties: Object,
63}
64
65impl CoreDocumentData {
66 fn check_id_constraints(&self) -> Result<()> {
71 let max_unique_method_ids = self.verification_method.len()
72 + self.authentication.len()
73 + self.assertion_method.len()
74 + self.key_agreement.len()
75 + self.capability_delegation.len()
76 + self.capability_invocation.len();
77
78 let mut method_identifiers: HashMap<&DIDUrl, bool> = HashMap::with_capacity(max_unique_method_ids);
81
82 for (id, is_embedded) in self
83 .authentication
84 .iter()
85 .chain(self.assertion_method.iter())
86 .chain(self.key_agreement.iter())
87 .chain(self.capability_delegation.iter())
88 .chain(self.capability_invocation.iter())
89 .map(|method_ref| match method_ref {
90 MethodRef::Embed(_) => (method_ref.id(), true),
91 MethodRef::Refer(_) => (method_ref.id(), false),
92 })
93 {
94 if let Some(previous) = method_identifiers.insert(id, is_embedded) {
95 match previous {
96 true => {
98 return Err(Error::InvalidDocument(
99 "attempted to construct document with a duplicated or aliased embedded method",
100 None,
101 ));
102 }
103 false => {
105 if is_embedded {
106 return Err(Error::InvalidDocument(
107 "attempted to construct document with an aliased embedded method",
108 None,
109 ));
110 }
111 }
112 }
113 }
114 }
115
116 for method_id in self.verification_method.iter().map(|method| method.id()) {
117 if method_identifiers
118 .insert(method_id, false)
119 .filter(|value| *value)
120 .is_some()
121 {
122 return Err(Error::InvalidDocument(
123 "attempted to construct document with a duplicated embedded method",
124 None,
125 ));
126 }
127 }
128
129 for service_id in self.service.iter().map(|service| service.id()) {
130 if method_identifiers.contains_key(service_id) {
131 return Err(Error::InvalidDocument(
132 "attempted to construct document with a service identifier shared with a verification method",
133 None,
134 ));
135 }
136 }
137
138 Ok(())
139 }
140
141 fn try_map<F, G, H, L, E>(
144 self,
145 id_map: F,
146 mut controller_map: G,
147 mut method_map: H,
148 mut services_map: L,
149 ) -> Result<Self, E>
150 where
151 F: FnOnce(CoreDID) -> std::result::Result<CoreDID, E>,
152 G: FnMut(CoreDID) -> std::result::Result<CoreDID, E>,
153 H: FnMut(CoreDID) -> std::result::Result<CoreDID, E>,
154 L: FnMut(CoreDID) -> std::result::Result<CoreDID, E>,
155 {
156 let current_data = self;
157 let id = id_map(current_data.id)?;
159 let controller = if let Some(controllers) = current_data.controller {
161 Some(controllers.try_map(&mut controller_map)?)
162 } else {
163 None
164 };
165
166 let verification_method = current_data
169 .verification_method
170 .into_iter()
171 .map(|method| method.try_map(&mut method_map))
172 .collect::<Result<_, E>>()?;
173
174 let authentication = current_data
175 .authentication
176 .into_iter()
177 .map(|method_ref| method_ref.try_map(&mut method_map))
178 .collect::<Result<_, E>>()?;
179
180 let assertion_method = current_data
181 .assertion_method
182 .into_iter()
183 .map(|method_ref| method_ref.try_map(&mut method_map))
184 .collect::<Result<_, E>>()?;
185
186 let key_agreement = current_data
187 .key_agreement
188 .into_iter()
189 .map(|method_ref| method_ref.try_map(&mut method_map))
190 .collect::<Result<_, E>>()?;
191
192 let capability_delegation = current_data
193 .capability_delegation
194 .into_iter()
195 .map(|method_ref| method_ref.try_map(&mut method_map))
196 .collect::<Result<_, E>>()?;
197
198 let capability_invocation = current_data
199 .capability_invocation
200 .into_iter()
201 .map(|method_ref| method_ref.try_map(&mut method_map))
202 .collect::<Result<_, E>>()?;
203
204 let service = current_data
206 .service
207 .into_iter()
208 .map(|service| service.try_map(&mut services_map))
209 .collect::<Result<_, E>>()?;
210
211 Ok(CoreDocumentData {
212 id,
213 controller,
214 also_known_as: current_data.also_known_as,
215 verification_method,
216 authentication,
217 assertion_method,
218 key_agreement,
219 capability_delegation,
220 capability_invocation,
221 service,
222 properties: current_data.properties,
223 })
224 }
225}
226
227#[derive(Clone, Debug, PartialEq, Eq, Deserialize)]
231#[rustfmt::skip]
232#[serde(try_from = "CoreDocumentData")]
233pub struct CoreDocument
234{
235 pub(crate) data: CoreDocumentData,
236}
237
238impl Serialize for CoreDocument {
240 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
241 where
242 S: Serializer,
243 {
244 self.data.serialize(serializer)
245 }
246}
247
248macro_rules! method_ref_mut_helper {
250 ($doc:ident, $method: ident, $query: ident) => {
251 match $doc.data.$method.query_mut($query.into())? {
252 MethodRef::Embed(method) => Some(method),
253 MethodRef::Refer(ref did) => $doc.data.verification_method.query_mut(did),
254 }
255 };
256}
257
258impl CoreDocument {
259 pub fn builder(properties: Object) -> DocumentBuilder {
263 DocumentBuilder::new(properties)
264 }
265
266 pub fn from_builder(builder: DocumentBuilder) -> Result<Self> {
268 Self::try_from(CoreDocumentData {
269 id: builder.id.ok_or(Error::InvalidDocument("missing id", None))?,
270 controller: Some(builder.controller)
271 .filter(|controllers| !controllers.is_empty())
272 .map(TryFrom::try_from)
273 .transpose()
274 .map_err(|err| Error::InvalidDocument("controller", Some(err)))?,
275 also_known_as: builder
276 .also_known_as
277 .try_into()
278 .map_err(|err| Error::InvalidDocument("also_known_as", Some(err)))?,
279 verification_method: builder
280 .verification_method
281 .try_into()
282 .map_err(|err| Error::InvalidDocument("verification_method", Some(err)))?,
283 authentication: builder
284 .authentication
285 .try_into()
286 .map_err(|err| Error::InvalidDocument("authentication", Some(err)))?,
287 assertion_method: builder
288 .assertion_method
289 .try_into()
290 .map_err(|err| Error::InvalidDocument("assertion_method", Some(err)))?,
291 key_agreement: builder
292 .key_agreement
293 .try_into()
294 .map_err(|err| Error::InvalidDocument("key_agreement", Some(err)))?,
295 capability_delegation: builder
296 .capability_delegation
297 .try_into()
298 .map_err(|err| Error::InvalidDocument("capability_delegation", Some(err)))?,
299 capability_invocation: builder
300 .capability_invocation
301 .try_into()
302 .map_err(|err| Error::InvalidDocument("capability_invocation", Some(err)))?,
303 service: builder
304 .service
305 .try_into()
306 .map_err(|err| Error::InvalidDocument("service", Some(err)))?,
307 properties: builder.properties,
308 })
309 }
310
311 pub fn id(&self) -> &CoreDID {
313 &self.data.id
314 }
315
316 pub fn id_mut_unchecked(&mut self) -> &mut CoreDID {
324 &mut self.data.id
325 }
326
327 pub fn controller(&self) -> Option<&OneOrSet<CoreDID>> {
329 self.data.controller.as_ref()
330 }
331
332 pub fn controller_mut(&mut self) -> &mut Option<OneOrSet<CoreDID>> {
334 &mut self.data.controller
335 }
336
337 pub fn also_known_as(&self) -> &OrderedSet<Url> {
339 &self.data.also_known_as
340 }
341
342 pub fn also_known_as_mut(&mut self) -> &mut OrderedSet<Url> {
344 &mut self.data.also_known_as
345 }
346
347 pub fn verification_method(&self) -> &OrderedSet<VerificationMethod> {
349 &self.data.verification_method
350 }
351
352 pub fn authentication(&self) -> &OrderedSet<MethodRef> {
354 &self.data.authentication
355 }
356
357 pub fn assertion_method(&self) -> &OrderedSet<MethodRef> {
359 &self.data.assertion_method
360 }
361
362 pub fn key_agreement(&self) -> &OrderedSet<MethodRef> {
364 &self.data.key_agreement
365 }
366
367 pub fn capability_delegation(&self) -> &OrderedSet<MethodRef> {
369 &self.data.capability_delegation
370 }
371
372 pub fn capability_invocation(&self) -> &OrderedSet<MethodRef> {
374 &self.data.capability_invocation
375 }
376
377 pub fn service(&self) -> &OrderedSet<Service> {
379 &self.data.service
380 }
381
382 pub fn service_mut_unchecked(&mut self) -> &mut OrderedSet<Service> {
387 &mut self.data.service
388 }
389
390 pub fn properties(&self) -> &Object {
392 &self.data.properties
393 }
394
395 pub fn properties_mut_unchecked(&mut self) -> &mut Object {
403 &mut self.data.properties
404 }
405
406 pub fn insert_method(&mut self, method: VerificationMethod, scope: MethodScope) -> Result<()> {
412 if self.resolve_method(method.id(), None).is_some() || self.service().query(method.id()).is_some() {
417 return Err(Error::MethodInsertionError);
418 }
419 match scope {
420 MethodScope::VerificationMethod => self.data.verification_method.append(method),
421 MethodScope::VerificationRelationship(MethodRelationship::Authentication) => {
422 self.data.authentication.append(MethodRef::Embed(method))
423 }
424 MethodScope::VerificationRelationship(MethodRelationship::AssertionMethod) => {
425 self.data.assertion_method.append(MethodRef::Embed(method))
426 }
427 MethodScope::VerificationRelationship(MethodRelationship::KeyAgreement) => {
428 self.data.key_agreement.append(MethodRef::Embed(method))
429 }
430 MethodScope::VerificationRelationship(MethodRelationship::CapabilityDelegation) => {
431 self.data.capability_delegation.append(MethodRef::Embed(method))
432 }
433 MethodScope::VerificationRelationship(MethodRelationship::CapabilityInvocation) => {
434 self.data.capability_invocation.append(MethodRef::Embed(method))
435 }
436 };
437
438 Ok(())
439 }
440
441 pub fn remove_method(&mut self, did_url: &DIDUrl) -> Option<VerificationMethod> {
448 self.remove_method_and_scope(did_url).map(|(method, _scope)| method)
449 }
450
451 pub fn remove_method_and_scope(&mut self, did_url: &DIDUrl) -> Option<(VerificationMethod, MethodScope)> {
459 for (method_ref, scope) in [
460 self.data.authentication.remove(did_url).map(|method_ref| {
461 (
462 method_ref,
463 MethodScope::VerificationRelationship(MethodRelationship::Authentication),
464 )
465 }),
466 self.data.assertion_method.remove(did_url).map(|method_ref| {
467 (
468 method_ref,
469 MethodScope::VerificationRelationship(MethodRelationship::AssertionMethod),
470 )
471 }),
472 self.data.key_agreement.remove(did_url).map(|method_ref| {
473 (
474 method_ref,
475 MethodScope::VerificationRelationship(MethodRelationship::KeyAgreement),
476 )
477 }),
478 self.data.capability_delegation.remove(did_url).map(|method_ref| {
479 (
480 method_ref,
481 MethodScope::VerificationRelationship(MethodRelationship::CapabilityDelegation),
482 )
483 }),
484 self.data.capability_invocation.remove(did_url).map(|method_ref| {
485 (
486 method_ref,
487 MethodScope::VerificationRelationship(MethodRelationship::CapabilityInvocation),
488 )
489 }),
490 ]
491 .into_iter()
492 .flatten()
493 {
494 if let (MethodRef::Embed(embedded_method), scope) = (method_ref, scope) {
495 return Some((embedded_method, scope));
498 }
499 }
500
501 self
502 .data
503 .verification_method
504 .remove(did_url)
505 .map(|method| (method, MethodScope::VerificationMethod))
506 }
507
508 pub fn insert_service(&mut self, service: Service) -> Result<()> {
514 let service_id = service.id();
515 let id_exists = self
516 .verification_relationships()
517 .map(|method_ref| method_ref.id())
518 .chain(self.verification_method().iter().map(|method| method.id()))
519 .any(|id| id == service_id);
520
521 ((!id_exists) && self.data.service.append(service))
522 .then_some(())
523 .ok_or(Error::InvalidServiceInsertion)
524 }
525
526 pub fn remove_service(&mut self, id: &DIDUrl) -> Option<Service> {
528 self.data.service.remove(id)
529 }
530
531 pub fn attach_method_relationship<'query, Q>(
539 &mut self,
540 method_query: Q,
541 relationship: MethodRelationship,
542 ) -> Result<bool>
543 where
544 Q: Into<DIDUrlQuery<'query>>,
545 {
546 let method_query: DIDUrlQuery<'query> = method_query.into();
547
548 match self.resolve_method(method_query.clone(), Some(MethodScope::VerificationMethod)) {
549 None => match self.resolve_method(method_query, None) {
550 Some(_) => Err(Error::InvalidMethodEmbedded),
551 None => Err(Error::MethodNotFound),
552 },
553 Some(method) => {
554 let method_ref = MethodRef::Refer(method.id().clone());
555
556 let was_attached = match relationship {
557 MethodRelationship::Authentication => self.data.authentication.append(method_ref),
558 MethodRelationship::AssertionMethod => self.data.assertion_method.append(method_ref),
559 MethodRelationship::KeyAgreement => self.data.key_agreement.append(method_ref),
560 MethodRelationship::CapabilityDelegation => self.data.capability_delegation.append(method_ref),
561 MethodRelationship::CapabilityInvocation => self.data.capability_invocation.append(method_ref),
562 };
563
564 Ok(was_attached)
565 }
566 }
567 }
568
569 pub fn detach_method_relationship<'query, Q>(
582 &mut self,
583 method_query: Q,
584 relationship: MethodRelationship,
585 ) -> Result<bool>
586 where
587 Q: Into<DIDUrlQuery<'query>>,
588 {
589 let method_query: DIDUrlQuery<'query> = method_query.into();
590 match self.resolve_method(method_query.clone(), Some(MethodScope::VerificationMethod)) {
591 None => match self.resolve_method(method_query, None) {
592 Some(_) => Err(Error::InvalidMethodEmbedded),
593 None => Err(Error::MethodNotFound),
594 },
595 Some(method) => {
596 let did_url: DIDUrl = method.id().clone();
597
598 let was_detached = match relationship {
599 MethodRelationship::Authentication => self.data.authentication.remove(&did_url),
600 MethodRelationship::AssertionMethod => self.data.assertion_method.remove(&did_url),
601 MethodRelationship::KeyAgreement => self.data.key_agreement.remove(&did_url),
602 MethodRelationship::CapabilityDelegation => self.data.capability_delegation.remove(&did_url),
603 MethodRelationship::CapabilityInvocation => self.data.capability_invocation.remove(&did_url),
604 };
605
606 Ok(was_detached.is_some())
607 }
608 }
609 }
610
611 pub fn methods(&self, scope: Option<MethodScope>) -> Vec<&VerificationMethod> {
615 if let Some(scope) = scope {
616 match scope {
617 MethodScope::VerificationMethod => self.verification_method().iter().collect(),
618 MethodScope::VerificationRelationship(MethodRelationship::AssertionMethod) => self
619 .assertion_method()
620 .iter()
621 .filter_map(|method_ref| self.resolve_method_ref(method_ref))
622 .collect(),
623 MethodScope::VerificationRelationship(MethodRelationship::Authentication) => self
624 .authentication()
625 .iter()
626 .filter_map(|method_ref| self.resolve_method_ref(method_ref))
627 .collect(),
628 MethodScope::VerificationRelationship(MethodRelationship::CapabilityDelegation) => self
629 .capability_delegation()
630 .iter()
631 .filter_map(|method_ref| self.resolve_method_ref(method_ref))
632 .collect(),
633 MethodScope::VerificationRelationship(MethodRelationship::CapabilityInvocation) => self
634 .capability_invocation()
635 .iter()
636 .filter_map(|method_ref| self.resolve_method_ref(method_ref))
637 .collect(),
638 MethodScope::VerificationRelationship(MethodRelationship::KeyAgreement) => self
639 .key_agreement()
640 .iter()
641 .filter_map(|method_ref| self.resolve_method_ref(method_ref))
642 .collect(),
643 }
644 } else {
645 self.all_methods().collect()
646 }
647 }
648
649 fn all_methods(&self) -> impl Iterator<Item = &VerificationMethod> {
653 fn __filter_ref(method: &MethodRef) -> Option<&VerificationMethod> {
654 match method {
655 MethodRef::Embed(method) => Some(method),
656 MethodRef::Refer(_) => None,
657 }
658 }
659
660 self
661 .data
662 .verification_method
663 .iter()
664 .chain(self.data.authentication.iter().filter_map(__filter_ref))
665 .chain(self.data.assertion_method.iter().filter_map(__filter_ref))
666 .chain(self.data.key_agreement.iter().filter_map(__filter_ref))
667 .chain(self.data.capability_delegation.iter().filter_map(__filter_ref))
668 .chain(self.data.capability_invocation.iter().filter_map(__filter_ref))
669 }
670
671 pub fn verification_relationships(&self) -> impl Iterator<Item = &MethodRef> {
675 self
676 .data
677 .authentication
678 .iter()
679 .chain(self.data.assertion_method.iter())
680 .chain(self.data.key_agreement.iter())
681 .chain(self.data.capability_delegation.iter())
682 .chain(self.data.capability_invocation.iter())
683 }
684
685 pub fn resolve_method<'query, 'me, Q>(
690 &'me self,
691 method_query: Q,
692 scope: Option<MethodScope>,
693 ) -> Option<&'me VerificationMethod>
694 where
695 Q: Into<DIDUrlQuery<'query>>,
696 {
697 match scope {
698 Some(scope) => {
699 let resolve_ref_helper = |method_ref: &'me MethodRef| self.resolve_method_ref(method_ref);
700
701 match scope {
702 MethodScope::VerificationMethod => self.data.verification_method.query(method_query.into()),
703 MethodScope::VerificationRelationship(MethodRelationship::Authentication) => self
704 .data
705 .authentication
706 .query(method_query.into())
707 .and_then(resolve_ref_helper),
708 MethodScope::VerificationRelationship(MethodRelationship::AssertionMethod) => self
709 .data
710 .assertion_method
711 .query(method_query.into())
712 .and_then(resolve_ref_helper),
713 MethodScope::VerificationRelationship(MethodRelationship::KeyAgreement) => self
714 .data
715 .key_agreement
716 .query(method_query.into())
717 .and_then(resolve_ref_helper),
718 MethodScope::VerificationRelationship(MethodRelationship::CapabilityDelegation) => self
719 .data
720 .capability_delegation
721 .query(method_query.into())
722 .and_then(resolve_ref_helper),
723 MethodScope::VerificationRelationship(MethodRelationship::CapabilityInvocation) => self
724 .data
725 .capability_invocation
726 .query(method_query.into())
727 .and_then(resolve_ref_helper),
728 }
729 }
730 None => self.resolve_method_inner(method_query.into()),
731 }
732 }
733
734 pub fn resolve_method_mut<'query, 'me, Q>(
743 &'me mut self,
744 method_query: Q,
745 scope: Option<MethodScope>,
746 ) -> Option<&'me mut VerificationMethod>
747 where
748 Q: Into<DIDUrlQuery<'query>>,
749 {
750 match scope {
751 Some(scope) => match scope {
752 MethodScope::VerificationMethod => self.data.verification_method.query_mut(method_query.into()),
753 MethodScope::VerificationRelationship(MethodRelationship::Authentication) => {
754 method_ref_mut_helper!(self, authentication, method_query)
755 }
756 MethodScope::VerificationRelationship(MethodRelationship::AssertionMethod) => {
757 method_ref_mut_helper!(self, assertion_method, method_query)
758 }
759 MethodScope::VerificationRelationship(MethodRelationship::KeyAgreement) => {
760 method_ref_mut_helper!(self, key_agreement, method_query)
761 }
762 MethodScope::VerificationRelationship(MethodRelationship::CapabilityDelegation) => {
763 method_ref_mut_helper!(self, capability_delegation, method_query)
764 }
765 MethodScope::VerificationRelationship(MethodRelationship::CapabilityInvocation) => {
766 method_ref_mut_helper!(self, capability_invocation, method_query)
767 }
768 },
769 None => self.resolve_method_mut_inner(method_query.into()),
770 }
771 }
772
773 pub fn resolve_service<'query, 'me, Q>(&'me self, service_query: Q) -> Option<&'me Service>
777 where
778 Q: Into<DIDUrlQuery<'query>>,
779 {
780 self.service().query(service_query.into())
781 }
782
783 #[doc(hidden)]
784 pub fn resolve_method_ref<'a>(&'a self, method_ref: &'a MethodRef) -> Option<&'a VerificationMethod> {
785 match method_ref {
786 MethodRef::Embed(method) => Some(method),
787 MethodRef::Refer(did) => self.data.verification_method.query(did),
788 }
789 }
790
791 fn resolve_method_inner(&self, query: DIDUrlQuery<'_>) -> Option<&VerificationMethod> {
792 let mut method: Option<&MethodRef> = None;
793
794 if method.is_none() {
795 method = self.data.authentication.query(query.clone());
796 }
797
798 if method.is_none() {
799 method = self.data.assertion_method.query(query.clone());
800 }
801
802 if method.is_none() {
803 method = self.data.key_agreement.query(query.clone());
804 }
805
806 if method.is_none() {
807 method = self.data.capability_delegation.query(query.clone());
808 }
809
810 if method.is_none() {
811 method = self.data.capability_invocation.query(query.clone());
812 }
813
814 match method {
815 Some(MethodRef::Embed(method)) => Some(method),
816 Some(MethodRef::Refer(did)) => self.data.verification_method.query(&did.to_string()),
817 None => self.data.verification_method.query(query),
818 }
819 }
820
821 fn resolve_method_mut_inner(&mut self, query: DIDUrlQuery<'_>) -> Option<&mut VerificationMethod> {
822 let mut method: Option<&mut MethodRef> = None;
823
824 if method.is_none() {
825 method = self.data.authentication.query_mut(query.clone());
826 }
827
828 if method.is_none() {
829 method = self.data.assertion_method.query_mut(query.clone());
830 }
831
832 if method.is_none() {
833 method = self.data.key_agreement.query_mut(query.clone());
834 }
835
836 if method.is_none() {
837 method = self.data.capability_delegation.query_mut(query.clone());
838 }
839
840 if method.is_none() {
841 method = self.data.capability_invocation.query_mut(query.clone());
842 }
843
844 match method {
845 Some(MethodRef::Embed(method)) => Some(method),
846 Some(MethodRef::Refer(did)) => self.data.verification_method.query_mut(&did.to_string()),
847 None => self.data.verification_method.query_mut(query),
848 }
849 }
850
851 pub fn try_map<F, G, H, L, M, E>(
862 self,
863 id_update: F,
864 controller_update: G,
865 methods_update: H,
866 service_update: L,
867 error_cast: M,
868 ) -> Result<Self, E>
869 where
870 F: FnOnce(CoreDID) -> std::result::Result<CoreDID, E>,
871 G: FnMut(CoreDID) -> std::result::Result<CoreDID, E>,
872 H: FnMut(CoreDID) -> std::result::Result<CoreDID, E>,
873 L: FnMut(CoreDID) -> std::result::Result<CoreDID, E>,
874 M: FnOnce(crate::Error) -> E,
875 {
876 let data = self
877 .data
878 .try_map(id_update, controller_update, methods_update, service_update)?;
879 CoreDocument::try_from(data).map_err(error_cast)
880 }
881
882 pub fn map_unchecked<F, G, H, L>(
884 self,
885 id_update: F,
886 mut controller_update: G,
887 mut methods_update: H,
888 mut service_update: L,
889 ) -> Self
890 where
891 F: FnOnce(CoreDID) -> CoreDID,
892 G: FnMut(CoreDID) -> CoreDID,
893 H: FnMut(CoreDID) -> CoreDID,
894 L: FnMut(CoreDID) -> CoreDID,
895 {
896 type InfallibleCoreDIDResult = std::result::Result<CoreDID, Infallible>;
897
898 let id_map = |did: CoreDID| -> InfallibleCoreDIDResult { Ok(id_update(did)) };
899 let controller_map = |did: CoreDID| -> InfallibleCoreDIDResult { Ok(controller_update(did)) };
900 let method_map = |did: CoreDID| -> InfallibleCoreDIDResult { Ok(methods_update(did)) };
901 let services_map = |did: CoreDID| -> InfallibleCoreDIDResult { Ok(service_update(did)) };
902 let data = self
903 .data
904 .try_map(id_map, controller_map, method_map, services_map)
905 .expect("unwrapping infallible should be fine");
906 CoreDocument { data }
907 }
908}
909
910impl AsRef<CoreDocument> for CoreDocument {
911 fn as_ref(&self) -> &CoreDocument {
912 self
913 }
914}
915
916impl TryFrom<CoreDocumentData> for CoreDocument {
917 type Error = crate::error::Error;
918 fn try_from(value: CoreDocumentData) -> Result<Self, Self::Error> {
919 match value.check_id_constraints() {
920 Ok(_) => Ok(Self { data: value }),
921 Err(err) => Err(err),
922 }
923 }
924}
925
926impl Display for CoreDocument {
927 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
928 self.fmt_json(f)
929 }
930}
931
932impl CoreDocument {
936 pub fn verify_jws<'jws, T: JwsVerifier>(
947 &self,
948 jws: &'jws str,
949 detached_payload: Option<&'jws [u8]>,
950 signature_verifier: &T,
951 options: &JwsVerificationOptions,
952 ) -> Result<DecodedJws<'jws>> {
953 let validation_item = Decoder::new()
954 .decode_compact_serialization(jws.as_bytes(), detached_payload)
955 .map_err(Error::JwsVerificationError)?;
956
957 let nonce: Option<&str> = options.nonce.as_deref();
958 if validation_item.nonce() != nonce {
960 return Err(Error::JwsVerificationError(
961 identity_verification::jose::error::Error::InvalidParam("invalid nonce value"),
962 ));
963 }
964
965 let method_url_query: DIDUrlQuery<'_> = match &options.method_id {
966 Some(method_id) => method_id.into(),
967 None => validation_item
968 .kid()
969 .ok_or(Error::JwsVerificationError(
970 identity_verification::jose::error::Error::InvalidParam("missing kid value"),
971 ))?
972 .into(),
973 };
974
975 let public_key: &Jwk = self
976 .resolve_method(method_url_query, options.method_scope)
977 .ok_or(Error::MethodNotFound)?
978 .data()
979 .try_public_key_jwk()
980 .map_err(Error::InvalidKeyMaterial)?;
981
982 validation_item
983 .verify(signature_verifier, public_key)
984 .map_err(Error::JwsVerificationError)
985 }
986}
987
988impl CoreDocument {
989 pub fn expand_did_jwk(did_jwk: DIDJwk) -> Result<Self, Error> {
991 let verification_method = VerificationMethod::try_from(did_jwk.clone()).map_err(Error::InvalidKeyMaterial)?;
992 let verification_method_id = verification_method.id().clone();
993
994 DocumentBuilder::default()
995 .id(did_jwk.into())
996 .verification_method(verification_method)
997 .assertion_method(verification_method_id.clone())
998 .authentication(verification_method_id.clone())
999 .capability_invocation(verification_method_id.clone())
1000 .capability_delegation(verification_method_id.clone())
1001 .build()
1002 }
1003}
1004
1005#[cfg(test)]
1006mod tests {
1007 use identity_core::convert::FromJson;
1008 use identity_core::convert::ToJson;
1009 use identity_did::DID;
1010 use identity_verification::MethodType;
1011
1012 use crate::service::ServiceBuilder;
1013 use identity_verification::MethodBuilder;
1014 use identity_verification::MethodData;
1015
1016 use super::*;
1017
1018 fn controller() -> CoreDID {
1019 "did:example:1234".parse().unwrap()
1020 }
1021
1022 fn method(controller: &CoreDID, fragment: &str) -> VerificationMethod {
1023 VerificationMethod::builder(Default::default())
1024 .id(controller.to_url().join(fragment).unwrap())
1025 .controller(controller.clone())
1026 .type_(MethodType::ED25519_VERIFICATION_KEY_2018)
1027 .data(MethodData::new_multibase(fragment.as_bytes()))
1028 .build()
1029 .unwrap()
1030 }
1031
1032 fn document() -> CoreDocument {
1033 let controller: CoreDID = controller();
1034
1035 CoreDocument::builder(Default::default())
1036 .id(controller.clone())
1037 .verification_method(method(&controller, "#key-1"))
1038 .verification_method(method(&controller, "#key-2"))
1039 .verification_method(method(&controller, "#key-3"))
1040 .authentication(method(&controller, "#auth-key"))
1041 .authentication(controller.to_url().join("#key-3").unwrap())
1042 .key_agreement(controller.to_url().join("#key-4").unwrap())
1043 .build()
1044 .unwrap()
1045 }
1046
1047 #[test]
1048 fn test_controller() {
1049 {
1051 let mut document: CoreDocument = document();
1052 let expected: CoreDID = CoreDID::parse("did:example:one1234").unwrap();
1053 *document.controller_mut() = Some(OneOrSet::new_one(expected.clone()));
1054 assert_eq!(document.controller().unwrap().as_slice(), &[expected]);
1055 *document.controller_mut() = None;
1057 assert!(document.controller().is_none());
1058 }
1059
1060 {
1062 let mut document: CoreDocument = document();
1063 let expected_controllers: Vec<CoreDID> = vec![
1064 CoreDID::parse("did:example:many1234").unwrap(),
1065 CoreDID::parse("did:example:many4567").unwrap(),
1066 CoreDID::parse("did:example:many8910").unwrap(),
1067 ];
1068 *document.controller_mut() = Some(expected_controllers.clone().try_into().unwrap());
1069 assert_eq!(document.controller().unwrap().as_slice(), &expected_controllers);
1070 *document.controller_mut() = None;
1072 assert!(document.controller().is_none());
1073 }
1074 }
1075
1076 #[rustfmt::skip]
1077 #[test]
1078 fn test_resolve_method() {
1079 let document: CoreDocument = document();
1080
1081 assert_eq!(document.resolve_method("#key-1", None).unwrap().id().to_string(), "did:example:1234#key-1");
1083 assert_eq!(document.resolve_method("#key-2", None).unwrap().id().to_string(), "did:example:1234#key-2");
1084 assert_eq!(document.resolve_method("#key-3", None).unwrap().id().to_string(), "did:example:1234#key-3");
1085
1086 assert_eq!(document.resolve_method("key-1", None).unwrap().id().to_string(), "did:example:1234#key-1");
1088 assert_eq!(document.resolve_method("key-2", None).unwrap().id().to_string(), "did:example:1234#key-2");
1089 assert_eq!(document.resolve_method("key-3", None).unwrap().id().to_string(), "did:example:1234#key-3");
1090
1091 assert_eq!(document.resolve_method("did:example:1234#key-1", None).unwrap().id().to_string(), "did:example:1234#key-1");
1093 assert_eq!(document.resolve_method("did:example:1234#key-2", None).unwrap().id().to_string(), "did:example:1234#key-2");
1094 assert_eq!(document.resolve_method("did:example:1234#key-3", None).unwrap().id().to_string(), "did:example:1234#key-3");
1095
1096 assert_eq!(
1098 document.resolve_method("#key-1", Some(MethodScope::VerificationMethod)).unwrap().id().to_string(), "did:example:1234#key-1"
1099 );
1100 }
1101
1102 #[rustfmt::skip]
1103 #[test]
1104 fn test_resolve_method_mut() {
1105 let mut document: CoreDocument = document();
1106
1107 assert_eq!(document.resolve_method_mut("#key-1", None).unwrap().id().to_string(), "did:example:1234#key-1");
1109 assert_eq!(document.resolve_method_mut("#key-3", None).unwrap().id().to_string(), "did:example:1234#key-3");
1110 assert_eq!(document.resolve_method_mut("#key-2", None).unwrap().id().to_string(), "did:example:1234#key-2");
1111
1112 assert_eq!(document.resolve_method_mut("key-1", None).unwrap().id().to_string(), "did:example:1234#key-1");
1114 assert_eq!(document.resolve_method_mut("key-2", None).unwrap().id().to_string(), "did:example:1234#key-2");
1115 assert_eq!(document.resolve_method_mut("key-3", None).unwrap().id().to_string(), "did:example:1234#key-3");
1116
1117 assert_eq!(document.resolve_method_mut("did:example:1234#key-1", None).unwrap().id().to_string(), "did:example:1234#key-1");
1119 assert_eq!(document.resolve_method_mut("did:example:1234#key-2", None).unwrap().id().to_string(), "did:example:1234#key-2");
1120 assert_eq!(document.resolve_method_mut("did:example:1234#key-3", None).unwrap().id().to_string(), "did:example:1234#key-3");
1121
1122 assert_eq!(
1124 document.resolve_method_mut("#key-1", Some(MethodScope::VerificationMethod)).unwrap().id().to_string(), "did:example:1234#key-1"
1125 );
1126 }
1127
1128 #[test]
1129 fn test_resolve_method_fails() {
1130 let document: CoreDocument = document();
1131
1132 assert_eq!(document.resolve_method("#key-4", None), None);
1134
1135 assert_eq!(document.resolve_method("did:example:1234", None), None);
1137
1138 assert_eq!(document.resolve_method("", None), None);
1140
1141 assert_eq!(
1143 document.resolve_method("#key-1", Some(MethodScope::key_agreement())),
1144 None
1145 );
1146 }
1147
1148 #[test]
1149 fn test_resolve_method_mut_fails() {
1150 let mut document: CoreDocument = document();
1151
1152 assert_eq!(document.resolve_method_mut("#key-4", None), None);
1154
1155 assert_eq!(document.resolve_method_mut("did:example:1234", None), None);
1157
1158 assert_eq!(document.resolve_method_mut("", None), None);
1160
1161 assert_eq!(
1163 document.resolve_method_mut("#key-1", Some(MethodScope::key_agreement())),
1164 None
1165 );
1166 }
1167
1168 #[rustfmt::skip]
1169 #[test]
1170 fn test_methods_index() {
1171 let document: CoreDocument = document();
1172
1173 assert_eq!(document.methods(None).first().unwrap().id().to_string(), "did:example:1234#key-1");
1175 assert_eq!(document.methods(None).get(2).unwrap().id().to_string(), "did:example:1234#key-3");
1176 }
1177
1178 #[test]
1179 fn test_methods_scope() {
1180 let document: CoreDocument = document();
1181
1182 let verification_methods: Vec<&VerificationMethod> = document.methods(Some(MethodScope::VerificationMethod));
1184 assert_eq!(
1185 verification_methods.first().unwrap().id().to_string(),
1186 "did:example:1234#key-1"
1187 );
1188 assert_eq!(
1189 verification_methods.get(1).unwrap().id().to_string(),
1190 "did:example:1234#key-2"
1191 );
1192 assert_eq!(
1193 verification_methods.get(2).unwrap().id().to_string(),
1194 "did:example:1234#key-3"
1195 );
1196 assert_eq!(verification_methods.len(), 3);
1197
1198 let authentication: Vec<&VerificationMethod> = document.methods(Some(MethodScope::authentication()));
1200 assert_eq!(
1201 authentication.first().unwrap().id().to_string(),
1202 "did:example:1234#auth-key"
1203 );
1204 assert_eq!(
1205 authentication.get(1).unwrap().id().to_string(),
1206 "did:example:1234#key-3"
1207 );
1208 assert_eq!(authentication.len(), 2);
1209 }
1210
1211 #[test]
1212 fn test_attach_verification_relationships() {
1213 let mut document: CoreDocument = document();
1214
1215 let fragment = "#attach-test";
1216 let method = method(document.id(), fragment);
1217 document.insert_method(method, MethodScope::VerificationMethod).unwrap();
1218
1219 assert!(document
1220 .attach_method_relationship(
1221 document.id().to_url().join(fragment).unwrap(),
1222 MethodRelationship::CapabilityDelegation,
1223 )
1224 .unwrap());
1225
1226 assert_eq!(document.verification_relationships().count(), 4);
1227
1228 assert!(!document
1230 .attach_method_relationship(
1231 document.id().to_url().join(fragment).unwrap(),
1232 MethodRelationship::CapabilityDelegation,
1233 )
1234 .unwrap());
1235
1236 assert_eq!(document.verification_relationships().count(), 4);
1238
1239 assert!(document
1241 .attach_method_relationship(
1242 document.id().to_url().join("#doesNotExist").unwrap(),
1243 MethodRelationship::CapabilityDelegation,
1244 )
1245 .is_err());
1246
1247 assert!(document
1249 .attach_method_relationship(
1250 document.id().to_url().join("#auth-key").unwrap(),
1251 MethodRelationship::CapabilityDelegation,
1252 )
1253 .is_err());
1254 }
1255
1256 #[test]
1257 fn test_detach_verification_relationships() {
1258 let mut document: CoreDocument = document();
1259
1260 let fragment = "#detach-test";
1261 let method = method(document.id(), fragment);
1262 document.insert_method(method, MethodScope::VerificationMethod).unwrap();
1263
1264 assert!(document
1265 .attach_method_relationship(
1266 document.id().to_url().join(fragment).unwrap(),
1267 MethodRelationship::AssertionMethod,
1268 )
1269 .is_ok());
1270
1271 assert!(document
1272 .detach_method_relationship(
1273 document.id().to_url().join(fragment).unwrap(),
1274 MethodRelationship::AssertionMethod,
1275 )
1276 .unwrap());
1277
1278 assert_eq!(document.verification_relationships().count(), 3);
1280
1281 assert!(!document
1283 .detach_method_relationship(
1284 document.id().to_url().join(fragment).unwrap(),
1285 MethodRelationship::AssertionMethod,
1286 )
1287 .unwrap());
1288
1289 assert_eq!(document.verification_relationships().count(), 3);
1291
1292 assert!(document
1294 .detach_method_relationship(
1295 document.id().to_url().join("#doesNotExist").unwrap(),
1296 MethodRelationship::AssertionMethod,
1297 )
1298 .is_err());
1299 }
1300
1301 #[test]
1302 fn test_method_insert_duplication() {
1303 let mut document: CoreDocument = document();
1304
1305 let fragment = "#duplication-test";
1306 let method1 = method(document.id(), fragment);
1307 assert!(document
1308 .insert_method(method1.clone(), MethodScope::VerificationMethod)
1309 .is_ok());
1310 assert!(document
1311 .insert_method(method1.clone(), MethodScope::VerificationMethod)
1312 .is_err());
1313 assert!(document
1314 .insert_method(method1.clone(), MethodScope::authentication())
1315 .is_err());
1316
1317 let fragment = "#duplication-test-2";
1318 let method2 = method(document.id(), fragment);
1319 assert!(document.insert_method(method2, MethodScope::assertion_method()).is_ok());
1320 assert!(document
1321 .insert_method(method1.clone(), MethodScope::VerificationMethod)
1322 .is_err());
1323 assert!(document
1324 .insert_method(method1, MethodScope::capability_delegation())
1325 .is_err());
1326 }
1327
1328 #[test]
1329 fn test_method_remove_existence() {
1330 let mut document: CoreDocument = document();
1331
1332 let fragment = "#existence-test";
1333 let method1 = method(document.id(), fragment);
1334 assert!(document
1335 .insert_method(method1.clone(), MethodScope::VerificationMethod)
1336 .is_ok());
1337 assert_eq!(method1, document.remove_method(method1.id()).unwrap());
1338 assert!(document.remove_method(method1.id()).is_none());
1339
1340 let fragment = "#existence-test-2";
1341 let method2 = method(document.id(), fragment);
1342 assert!(document.insert_method(method2, MethodScope::assertion_method()).is_ok());
1343 assert!(document.remove_method(method1.id()).is_none());
1344 assert!(document.remove_method(method1.id()).is_none());
1345
1346 let fragment = "#removal-test-3";
1347 let method3 = method(document.id(), fragment);
1348 assert!(document
1349 .insert_method(method3.clone(), MethodScope::VerificationMethod)
1350 .is_ok());
1351 assert!(document
1352 .attach_method_relationship(fragment, MethodRelationship::CapabilityDelegation)
1353 .is_ok());
1354
1355 assert_eq!(method3, document.remove_method(method3.id()).unwrap());
1356
1357 assert!(document.capability_delegation().query(method3.id()).is_none());
1359 assert!(document.verification_method().query(method3.id()).is_none());
1360 }
1361
1362 #[test]
1363 fn test_service_updates() {
1364 let mut document = document();
1365 let service_id = document.id().to_url().join("#service-update-test").unwrap();
1366 let service_type = "test";
1367 let service_endpoint = Url::parse("https://example.com").unwrap();
1368
1369 let service: Service = ServiceBuilder::default()
1370 .id(service_id)
1371 .type_(service_type)
1372 .service_endpoint(service_endpoint)
1373 .build()
1374 .unwrap();
1375 assert!(document.insert_service(service.clone()).is_ok());
1377 let mut service_clone = service.clone();
1379 *service_clone.service_endpoint_mut() = Url::parse("https://other-example.com").unwrap().into();
1380 assert!(document.insert_service(service_clone).is_err());
1381 assert_eq!(service, document.remove_service(service.id()).unwrap());
1383 assert!(document.insert_service(service.clone()).is_ok());
1385
1386 let method: VerificationMethod = MethodBuilder::default()
1388 .type_(MethodType::ED25519_VERIFICATION_KEY_2018)
1389 .data(MethodData::PublicKeyBase58(
1390 "3M5RCDjPTWPkKSN3sxUmmMqHbmRPegYP1tjcKyrDbt9J".into(),
1391 ))
1392 .id(service.id().clone())
1393 .controller(document.id().clone())
1394 .build()
1395 .unwrap();
1396
1397 let method_scopes = [
1398 MethodScope::VerificationMethod,
1399 MethodScope::assertion_method(),
1400 MethodScope::authentication(),
1401 MethodScope::key_agreement(),
1402 MethodScope::capability_delegation(),
1403 MethodScope::capability_invocation(),
1404 ];
1405 for scope in method_scopes {
1406 let mut document_clone = document.clone();
1407 assert!(document_clone.insert_method(method.clone(), scope).is_err());
1408 assert!(document_clone.remove_service(service.id()).is_some());
1410 assert!(document_clone.insert_method(method.clone(), scope).is_ok());
1411 }
1412
1413 for scope in method_scopes {
1415 let mut doc_clone = document.clone();
1416 let valid_method_id = document.id().to_url().join("#valid-method-identifier").unwrap();
1417 let mut valid_method = method.clone();
1418 valid_method.set_id(valid_method_id.clone()).unwrap();
1419 assert!(doc_clone.insert_method(valid_method.clone(), scope).is_ok());
1421 let mut service_clone = service.clone();
1422 service_clone.set_id(valid_method_id).unwrap();
1423 assert!(doc_clone.insert_service(service_clone.clone()).is_err());
1424 assert!(doc_clone.remove_method(valid_method.id()).is_some());
1426 assert!(doc_clone.insert_service(service_clone).is_ok());
1427 }
1428
1429 assert!(document
1431 .remove_service(&service.id().join("#service-does-not-exist").unwrap())
1432 .is_none());
1433 }
1434
1435 #[test]
1436 fn serialize_deserialize_roundtrip() {
1437 let document: CoreDocument = document();
1438 let doc_json: String = document.to_json().unwrap();
1439 let doc_json_value: serde_json::Value = document.to_json_value().unwrap();
1440 let doc_json_vec: Vec<u8> = document.to_json_vec().unwrap();
1441 assert_eq!(document, CoreDocument::from_json(&doc_json).unwrap());
1442 assert_eq!(document, CoreDocument::from_json_value(doc_json_value).unwrap());
1443
1444 assert_eq!(document, CoreDocument::from_json_slice(&doc_json_vec).unwrap());
1445 }
1446
1447 #[test]
1448 fn deserialize_valid() {
1449 const JSON_DOCUMENT: &str = r#"{
1452 "@context": [
1453 "https://www.w3.org/ns/did/v1",
1454 "https://w3id.org/security/suites/ed25519-2020/v1"
1455 ],
1456 "id": "did:example:123",
1457 "authentication": [
1458 {
1459 "id": "did:example:123#z6MkecaLyHuYWkayBDLw5ihndj3T1m6zKTGqau3A51G7RBf3",
1460 "type": "Ed25519VerificationKey2018",
1461 "controller": "did:example:123",
1462 "publicKeyMultibase": "zAKJP3f7BD6W4iWEQ9jwndVTCBq8ua2Utt8EEjJ6Vxsf"
1463 }
1464 ],
1465 "capabilityInvocation": [
1466 {
1467 "id": "did:example:123#z6MkhdmzFu659ZJ4XKj31vtEDmjvsi5yDZG5L7Caz63oP39k",
1468 "type": "Ed25519VerificationKey2018",
1469 "controller": "did:example:123",
1470 "publicKeyMultibase": "z4BWwfeqdp1obQptLLMvPNgBw48p7og1ie6Hf9p5nTpNN"
1471 }
1472 ],
1473 "capabilityDelegation": [
1474 {
1475 "id": "did:example:123#z6Mkw94ByR26zMSkNdCUi6FNRsWnc2DFEeDXyBGJ5KTzSWyi",
1476 "type": "Ed25519VerificationKey2018",
1477 "controller": "did:example:123",
1478 "publicKeyMultibase": "zHgo9PAmfeoxHG8Mn2XHXamxnnSwPpkyBHAMNF3VyXJCL"
1479 }
1480 ],
1481 "assertionMethod": [
1482 {
1483 "id": "did:example:123#z6MkiukuAuQAE8ozxvmahnQGzApvtW7KT5XXKfojjwbdEomY",
1484 "type": "Ed25519VerificationKey2018",
1485 "controller": "did:example:123",
1486 "publicKeyMultibase": "z5TVraf9itbKXrRvt2DSS95Gw4vqU3CHAdetoufdcKazA"
1487 }
1488 ]
1489 }"#;
1490 let doc: std::result::Result<CoreDocument, Box<dyn std::error::Error>> =
1491 CoreDocument::from_json(JSON_DOCUMENT).map_err(Into::into);
1492 dbg!(&doc);
1494 assert!(doc.is_ok());
1495 }
1496
1497 #[test]
1498 fn deserialize_duplicate_method_different_scopes() {
1499 const JSON_VERIFICATION_METHOD_KEY_AGREEMENT: &str = r#"{
1500 "id": "did:example:1234",
1501 "verificationMethod": [
1502 {
1503 "id": "did:example:1234#key1",
1504 "controller": "did:example:1234",
1505 "type": "Ed25519VerificationKey2018",
1506 "publicKeyBase58": "3M5RCDjPTWPkKSN3sxUmmMqHbmRPegYP1tjcKyrDbt9J"
1507 }
1508 ],
1509 "keyAgreement": [
1510 {
1511 "id": "did:example:1234#key1",
1512 "controller": "did:example:1234",
1513 "type": "X25519KeyAgreementKey2019",
1514 "publicKeyBase58": "FbQWLPRhTH95MCkQUeFYdiSoQt8zMwetqfWoxqPgaq7x"
1515 }
1516 ]
1517 }"#;
1518
1519 const JSON_KEY_AGREEMENT_CAPABILITY_INVOCATION: &str = r#"{
1520 "id": "did:example:1234",
1521 "capabilityInvocation": [
1522 {
1523 "id": "did:example:1234#key1",
1524 "controller": "did:example:1234",
1525 "type": "Ed25519VerificationKey2018",
1526 "publicKeyBase58": "3M5RCDjPTWPkKSN3sxUmmMqHbmRPegYP1tjcKyrDbt9J"
1527 }
1528 ],
1529 "keyAgreement": [
1530 {
1531 "id": "did:example:1234#key1",
1532 "controller": "did:example:1234",
1533 "type": "X25519KeyAgreementKey2019",
1534 "publicKeyBase58": "FbQWLPRhTH95MCkQUeFYdiSoQt8zMwetqfWoxqPgaq7x"
1535 }
1536 ]
1537 }"#;
1538
1539 const JSON_ASSERTION_METHOD_CAPABILITY_INVOCATION: &str = r#"{
1540 "id": "did:example:1234",
1541 "assertionMethod": [
1542 {
1543 "id": "did:example:1234#key1",
1544 "controller": "did:example:1234",
1545 "type": "Ed25519VerificationKey2018",
1546 "publicKeyBase58": "H3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV"
1547 }
1548 ],
1549 "capabilityInvocation": [
1550 {
1551 "id": "did:example:1234#key1",
1552 "controller": "did:example:1234",
1553 "type": "Ed25519VerificationKey2018",
1554 "publicKeyBase58": "3M5RCDjPTWPkKSN3sxUmmMqHbmRPegYP1tjcKyrDbt9J"
1555 }
1556 ]
1557 }"#;
1558
1559 const JSON_VERIFICATION_METHOD_AUTHENTICATION: &str = r#"{
1560 "id": "did:example:1234",
1561 "verificationMethod": [
1562 {
1563 "id": "did:example:1234#key1",
1564 "controller": "did:example:1234",
1565 "type": "Ed25519VerificationKey2018",
1566 "publicKeyBase58": "3M5RCDjPTWPkKSN3sxUmmMqHbmRPegYP1tjcKyrDbt9J"
1567 }
1568 ],
1569 "authentication": [
1570 {
1571 "id": "did:example:1234#key1",
1572 "controller": "did:example:1234",
1573 "type": "Ed25519VerificationKey2018",
1574 "publicKeyBase58": "H3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV"
1575 }
1576 ]
1577 }"#;
1578
1579 const JSON_CAPABILITY_DELEGATION_ASSERTION_METHOD: &str = r#"{
1580 "id": "did:example:1234",
1581 "capabilityDelegation": [
1582 {
1583 "id": "did:example:1234#key1",
1584 "controller": "did:example:1234",
1585 "type": "Ed25519VerificationKey2018",
1586 "publicKeyBase58": "3M5RCDjPTWPkKSN3sxUmmMqHbmRPegYP1tjcKyrDbt9J"
1587 }
1588 ],
1589 "assertionMethod": [
1590 {
1591 "id": "did:example:1234#key1",
1592 "controller": "did:example:1234",
1593 "type": "Ed25519VerificationKey2018",
1594 "publicKeyBase58": "H3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV"
1595 }
1596 ]
1597 }"#;
1598
1599 let verifier = |json: &str| {
1600 let result: std::result::Result<CoreDocument, Box<dyn std::error::Error>> =
1601 CoreDocument::from_json(json).map_err(Into::into);
1602 println!("the following non-spec compliant document was deserialized: \n {json}");
1604 assert!(result.is_err());
1605 };
1606
1607 for json in [
1608 JSON_VERIFICATION_METHOD_KEY_AGREEMENT,
1609 JSON_KEY_AGREEMENT_CAPABILITY_INVOCATION,
1610 JSON_ASSERTION_METHOD_CAPABILITY_INVOCATION,
1611 JSON_VERIFICATION_METHOD_AUTHENTICATION,
1612 JSON_CAPABILITY_DELEGATION_ASSERTION_METHOD,
1613 ] {
1614 verifier(json);
1615 }
1616 }
1617
1618 #[test]
1619 fn deserialize_invalid_id_references() {
1620 const JSON_KEY_AGREEMENT_CAPABILITY_INVOCATION: &str = r#"{
1621 "id": "did:example:1234",
1622 "capabilityInvocation": [
1623 "did:example:1234#key1"
1624 ],
1625 "keyAgreement": [
1626 {
1627 "id": "did:example:1234#key1",
1628 "controller": "did:example:1234",
1629 "type": "X25519KeyAgreementKey2019",
1630 "publicKeyBase58": "FbQWLPRhTH95MCkQUeFYdiSoQt8zMwetqfWoxqPgaq7x"
1631 }
1632 ]
1633 }"#;
1634
1635 const JSON_ASSERTION_METHOD_CAPABILITY_INVOCATION: &str = r#"{
1636 "id": "did:example:1234",
1637 "assertionMethod": [
1638 "did:example:1234#key1",
1639 {
1640 "id": "did:example:1234#key2",
1641 "controller": "did:example:1234",
1642 "type": "Ed25519VerificationKey2018",
1643 "publicKeyBase58": "H3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV"
1644 }
1645 ],
1646 "capabilityInvocation": [
1647 {
1648 "id": "did:example:1234#key1",
1649 "controller": "did:example:1234",
1650 "type": "Ed25519VerificationKey2018",
1651 "publicKeyBase58": "3M5RCDjPTWPkKSN3sxUmmMqHbmRPegYP1tjcKyrDbt9J"
1652 }
1653 ]
1654 }"#;
1655
1656 const JSON_AUTHENTICATION_KEY_AGREEMENT: &str = r#"{
1657 "id": "did:example:1234",
1658 "keyAgreement": [
1659 "did:example:1234#key1"
1660 ],
1661 "authentication": [
1662 {
1663 "id": "did:example:1234#key1",
1664 "controller": "did:example:1234",
1665 "type": "Ed25519VerificationKey2018",
1666 "publicKeyMultibase": "zH3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV"
1667 }
1668 ]
1669 }"#;
1670
1671 const JSON_CAPABILITY_DELEGATION_ASSERTION_METHOD: &str = r#"{
1672 "id": "did:example:1234",
1673 "capabilityDelegation": [
1674 "did:example:1234#key1"
1675 ],
1676 "assertionMethod": [
1677 {
1678 "id": "did:example:1234#key1",
1679 "controller": "did:example:1234",
1680 "type": "X25519KeyAgreementKey2019",
1681 "publicKeyBase58": "FbQWLPRhTH95MCkQUeFYdiSoQt8zMwetqfWoxqPgaq7x"
1682 }
1683 ]
1684 }"#;
1685
1686 let verifier = |json: &str| {
1687 let result: std::result::Result<CoreDocument, Box<dyn std::error::Error>> =
1688 CoreDocument::from_json(json).map_err(Into::into);
1689 println!("the following non-spec compliant document was deserialized: \n {json}");
1691 assert!(result.is_err());
1692 };
1693
1694 for json in [
1695 JSON_KEY_AGREEMENT_CAPABILITY_INVOCATION,
1696 JSON_ASSERTION_METHOD_CAPABILITY_INVOCATION,
1697 JSON_AUTHENTICATION_KEY_AGREEMENT,
1698 JSON_CAPABILITY_DELEGATION_ASSERTION_METHOD,
1699 ] {
1700 verifier(json);
1701 }
1702 }
1703
1704 #[test]
1705 fn test_did_jwk_expansion() {
1706 let did_jwk = "did:jwk:eyJrdHkiOiJPS1AiLCJjcnYiOiJYMjU1MTkiLCJ1c2UiOiJlbmMiLCJ4IjoiM3A3YmZYdDl3YlRUVzJIQzdPUTFOei1EUThoYmVHZE5yZngtRkctSUswOCJ9"
1707 .parse::<DIDJwk>()
1708 .unwrap();
1709 let target_doc = serde_json::from_value(serde_json::json!({
1710 "id": "did:jwk:eyJrdHkiOiJPS1AiLCJjcnYiOiJYMjU1MTkiLCJ1c2UiOiJlbmMiLCJ4IjoiM3A3YmZYdDl3YlRUVzJIQzdPUTFOei1EUThoYmVHZE5yZngtRkctSUswOCJ9",
1711 "verificationMethod": [
1712 {
1713 "id": "did:jwk:eyJrdHkiOiJPS1AiLCJjcnYiOiJYMjU1MTkiLCJ1c2UiOiJlbmMiLCJ4IjoiM3A3YmZYdDl3YlRUVzJIQzdPUTFOei1EUThoYmVHZE5yZngtRkctSUswOCJ9#0",
1714 "type": "JsonWebKey2020",
1715 "controller": "did:jwk:eyJrdHkiOiJPS1AiLCJjcnYiOiJYMjU1MTkiLCJ1c2UiOiJlbmMiLCJ4IjoiM3A3YmZYdDl3YlRUVzJIQzdPUTFOei1EUThoYmVHZE5yZngtRkctSUswOCJ9",
1716 "publicKeyJwk": {
1717 "kty":"OKP",
1718 "crv":"X25519",
1719 "use":"enc",
1720 "x":"3p7bfXt9wbTTW2HC7OQ1Nz-DQ8hbeGdNrfx-FG-IK08"
1721 }
1722 }
1723 ],
1724 "assertionMethod": ["did:jwk:eyJrdHkiOiJPS1AiLCJjcnYiOiJYMjU1MTkiLCJ1c2UiOiJlbmMiLCJ4IjoiM3A3YmZYdDl3YlRUVzJIQzdPUTFOei1EUThoYmVHZE5yZngtRkctSUswOCJ9#0"],
1725 "authentication": ["did:jwk:eyJrdHkiOiJPS1AiLCJjcnYiOiJYMjU1MTkiLCJ1c2UiOiJlbmMiLCJ4IjoiM3A3YmZYdDl3YlRUVzJIQzdPUTFOei1EUThoYmVHZE5yZngtRkctSUswOCJ9#0"],
1726 "capabilityInvocation": ["did:jwk:eyJrdHkiOiJPS1AiLCJjcnYiOiJYMjU1MTkiLCJ1c2UiOiJlbmMiLCJ4IjoiM3A3YmZYdDl3YlRUVzJIQzdPUTFOei1EUThoYmVHZE5yZngtRkctSUswOCJ9#0"],
1727 "capabilityDelegation": ["did:jwk:eyJrdHkiOiJPS1AiLCJjcnYiOiJYMjU1MTkiLCJ1c2UiOiJlbmMiLCJ4IjoiM3A3YmZYdDl3YlRUVzJIQzdPUTFOei1EUThoYmVHZE5yZngtRkctSUswOCJ9#0"]
1728 })).unwrap();
1729
1730 assert_eq!(CoreDocument::expand_did_jwk(did_jwk).unwrap(), target_doc);
1731 }
1732}