1use std::collections::HashSet;
2
3use bc_components::{
4 EncapsulationPublicKey, PrivateKeyBase, PrivateKeys, PrivateKeysProvider,
5 PublicKeys, PublicKeysProvider, Reference, ReferenceProvider, Signer,
6 SigningPrivateKey, SigningPublicKey, URI, XID, XIDProvider, tags::TAG_XID,
7};
8use bc_envelope::prelude::*;
9use dcbor::prelude::CBORError;
10use known_values::{
11 ATTACHMENT_RAW, DELEGATE, DELEGATE_RAW, DEREFERENCE_VIA,
12 DEREFERENCE_VIA_RAW, EDGE_RAW, KEY, KEY_RAW, PROVENANCE, PROVENANCE_RAW,
13 SERVICE, SERVICE_RAW,
14};
15use provenance_mark::{
16 ProvenanceMark, ProvenanceMarkGenerator, ProvenanceMarkResolution,
17 ProvenanceSeed,
18};
19
20use super::{Delegate, Key};
21use crate::{
22 Error, HasNickname, HasPermissions, Provenance, Result, Service,
23 XIDGeneratorOptions, XIDPrivateKeyOptions,
24};
25
26#[derive(Debug, Clone, PartialEq, Eq)]
27pub struct XIDDocument {
28 xid: XID,
29 resolution_methods: HashSet<URI>,
30 keys: HashSet<Key>,
31 delegates: HashSet<Delegate>,
32 services: HashSet<Service>,
33 provenance: Option<Provenance>,
34 attachments: Attachments,
35 edges: Edges,
36 extra_assertions: Vec<Envelope>,
37}
38
39#[derive(Default)]
40pub enum XIDInceptionKeyOptions {
41 #[default]
42 Default,
43 PublicKeys(PublicKeys),
44 PublicAndPrivateKeys(PublicKeys, PrivateKeys),
45 PrivateKeyBase(PrivateKeyBase),
46}
47
48#[derive(Default)]
49pub enum XIDGenesisMarkOptions {
50 #[default]
51 None,
52 Passphrase(
53 String,
54 Option<ProvenanceMarkResolution>,
55 Option<Date>,
56 Option<CBOR>,
57 ),
58 Seed(
59 ProvenanceSeed,
60 Option<ProvenanceMarkResolution>,
61 Option<Date>,
62 Option<CBOR>,
63 ),
64}
65
66#[derive(Clone, Debug, PartialEq, Eq, Default)]
68pub enum XIDSigningOptions {
69 #[default]
71 None,
72
73 Inception,
75
76 PrivateKeys(PrivateKeys),
78
79 SigningPrivateKey(SigningPrivateKey),
81}
82
83#[derive(Clone, Debug, PartialEq, Eq, Default)]
86pub enum XIDVerifySignature {
87 #[default]
89 None,
90
91 Inception,
93}
94
95impl XIDDocument {
96 pub fn new(
97 key_options: XIDInceptionKeyOptions,
98 mark_options: XIDGenesisMarkOptions,
99 ) -> Self {
100 let inception_key = Self::inception_key_for_options(key_options);
101 let provenance = Self::genesis_mark_with_options(mark_options).map(
102 |(generator, mark)| Provenance::new_with_generator(generator, mark),
103 );
104
105 let mut xid_doc = Self {
106 xid: XID::new(inception_key.public_keys().signing_public_key()),
107 resolution_methods: HashSet::new(),
108 keys: HashSet::new(),
109 delegates: HashSet::new(),
110 services: HashSet::new(),
111 provenance,
112 attachments: Attachments::new(),
113 edges: Edges::new(),
114 extra_assertions: Vec::new(),
115 };
116
117 xid_doc.add_key(inception_key).unwrap();
118
119 xid_doc
120 }
121
122 fn inception_key_for_options(options: XIDInceptionKeyOptions) -> Key {
123 match options {
124 XIDInceptionKeyOptions::Default => {
125 let private_key_base = PrivateKeyBase::new();
127 let public_keys = private_key_base.public_keys();
128 let private_keys = private_key_base.private_keys();
129 Key::new_with_private_keys(private_keys, public_keys)
130 }
131 XIDInceptionKeyOptions::PublicKeys(public_keys) => {
132 Key::new_allow_all(&public_keys)
134 }
135 XIDInceptionKeyOptions::PublicAndPrivateKeys(
136 public_keys,
137 private_keys,
138 ) => {
139 Key::new_with_private_keys(private_keys, public_keys)
141 }
142 XIDInceptionKeyOptions::PrivateKeyBase(private_key_base) => {
143 let public_keys = private_key_base.public_keys();
145 let private_keys = private_key_base.private_keys();
146 Key::new_with_private_keys(private_keys, public_keys)
147 }
148 }
149 }
150
151 fn genesis_mark_with_options(
152 options: XIDGenesisMarkOptions,
153 ) -> Option<(ProvenanceMarkGenerator, ProvenanceMark)> {
154 use ProvenanceMarkGenerator;
155 match options {
156 XIDGenesisMarkOptions::None => None,
157 XIDGenesisMarkOptions::Passphrase(passphrase, res, date, info) => {
158 let mut generator =
159 ProvenanceMarkGenerator::new_with_passphrase(
160 res.unwrap_or(ProvenanceMarkResolution::High),
161 &passphrase,
162 );
163 let date = date.unwrap_or_else(dcbor::Date::now);
164 let mark = generator.next(date, info);
165 Some((generator, mark))
166 }
167 XIDGenesisMarkOptions::Seed(seed, res, date, info) => {
168 let mut generator = ProvenanceMarkGenerator::new_with_seed(
169 res.unwrap_or(ProvenanceMarkResolution::High),
170 seed,
171 );
172 let date = date.unwrap_or_else(dcbor::Date::now);
173 let mark = generator.next(date, info);
174 Some((generator, mark))
175 }
176 }
177 }
178
179 pub fn from_xid(xid: impl Into<XID>) -> Self {
180 Self {
181 xid: xid.into(),
182 resolution_methods: HashSet::new(),
183 keys: HashSet::new(),
184 delegates: HashSet::new(),
185 services: HashSet::new(),
186 provenance: None,
187 attachments: Attachments::new(),
188 edges: Edges::new(),
189 extra_assertions: Vec::new(),
190 }
191 }
192
193 pub fn resolution_methods(&self) -> &HashSet<URI> {
194 &self.resolution_methods
195 }
196
197 pub fn resolution_methods_mut(&mut self) -> &mut HashSet<URI> {
198 &mut self.resolution_methods
199 }
200
201 pub fn add_resolution_method(&mut self, method: URI) {
202 self.resolution_methods.insert(method);
203 }
204
205 pub fn remove_resolution_method(
206 &mut self,
207 method: impl AsRef<URI>,
208 ) -> Option<URI> {
209 self.resolution_methods.take(method.as_ref())
210 }
211
212 pub fn keys(&self) -> &HashSet<Key> { &self.keys }
213
214 pub fn keys_mut(&mut self) -> &mut HashSet<Key> { &mut self.keys }
215
216 pub fn add_key(&mut self, key: Key) -> Result<()> {
217 if self.find_key_by_public_keys(key.public_keys()).is_some() {
218 return Err(Error::Duplicate { item: "key".to_string() });
219 }
220 self.keys.insert(key);
221 Ok(())
222 }
223
224 pub fn find_key_by_public_keys(
225 &self,
226 key: &dyn PublicKeysProvider,
227 ) -> Option<&Key> {
228 let key = key.public_keys();
229 self.keys.iter().find(|k| k.public_keys() == &key)
230 }
231
232 pub fn find_key_by_reference(&self, reference: &Reference) -> Option<&Key> {
233 self.keys
234 .iter()
235 .find(|k| k.public_keys().reference() == *reference)
236 }
237
238 pub fn private_key_envelope_for_key(
276 &self,
277 public_keys: &PublicKeys,
278 password: Option<&str>,
279 ) -> Result<Option<Envelope>> {
280 match self.find_key_by_public_keys(public_keys) {
281 None => Ok(None),
282 Some(key) => key.private_key_envelope(password),
283 }
284 }
285
286 pub fn take_key(&mut self, key: &dyn PublicKeysProvider) -> Option<Key> {
287 if let Some(key) = self.find_key_by_public_keys(key).cloned() {
288 self.keys.take(&key)
289 } else {
290 None
291 }
292 }
293
294 pub fn remove_key(&mut self, key: &dyn PublicKeysProvider) -> Result<()> {
295 if self.services_reference_key(key) {
296 return Err(Error::StillReferenced { item: "key".to_string() });
297 }
298 if self.take_key(key).is_none() {
299 return Err(Error::NotFound { item: "key".to_string() });
300 }
301 Ok(())
302 }
303
304 pub fn set_name_for_key(
305 &mut self,
306 key: &dyn PublicKeysProvider,
307 name: impl Into<String>,
308 ) -> Result<()> {
309 let mut key = self
310 .take_key(key)
311 .ok_or_else(|| Error::NotFound { item: "key".to_string() })?;
312 key.set_nickname(name);
313 self.add_key(key)
314 }
315
316 pub fn is_inception_signing_key(
317 &self,
318 signing_public_key: &SigningPublicKey,
319 ) -> bool {
320 self.xid.validate(signing_public_key)
321 }
322
323 pub fn inception_signing_key(&self) -> Option<&SigningPublicKey> {
324 if let Some(key) = self.keys.iter().find(|k| {
325 self.is_inception_signing_key(k.public_keys().signing_public_key())
326 }) {
327 Some(key.public_keys().signing_public_key())
328 } else {
329 None
330 }
331 }
332
333 pub fn inception_key(&self) -> Option<&Key> {
334 self.keys.iter().find(|k| {
335 self.is_inception_signing_key(k.public_keys().signing_public_key())
336 })
337 }
338
339 pub fn remove_inception_key(&mut self) -> Option<Key> {
340 if let Some(key) = self.inception_key().cloned() {
341 self.keys.take(&key)
342 } else {
343 None
344 }
345 }
346
347 pub fn verification_key(&self) -> Option<&SigningPublicKey> {
348 if let Some(key) = self.inception_key() {
350 Some(key.public_keys().signing_public_key())
351 } else if let Some(key) = self.keys.iter().next() {
352 Some(key.public_keys().signing_public_key())
353 } else {
354 None
355 }
356 }
357
358 pub fn encryption_key(&self) -> Option<&EncapsulationPublicKey> {
359 if let Some(key) = self.inception_key() {
361 Some(key.public_keys().enapsulation_public_key())
362 } else if let Some(key) = self.keys.iter().next() {
363 Some(key.public_keys().enapsulation_public_key())
364 } else {
365 None
366 }
367 }
368
369 pub fn inception_private_keys(&self) -> Option<&PrivateKeys> {
375 self.inception_key().and_then(|key| key.private_keys())
376 }
377
378 pub fn extract_inception_private_keys_from_envelope(
389 envelope: &Envelope,
390 password: &[u8],
391 ) -> Result<Option<PrivateKeys>> {
392 let doc = Self::from_envelope(
393 envelope,
394 Some(password),
395 XIDVerifySignature::None,
396 )?;
397 Ok(doc.inception_private_keys().cloned())
398 }
399
400 pub fn is_empty(&self) -> bool {
401 self.resolution_methods.is_empty()
402 && self.keys.is_empty()
403 && self.delegates.is_empty()
404 && self.provenance.is_none()
405 && self.services.is_empty()
406 && !self.has_attachments()
407 && !self.has_edges()
408 && self.extra_assertions.is_empty()
409 }
410
411 pub fn extra_assertions(&self) -> &[Envelope] { &self.extra_assertions }
412
413 #[allow(clippy::mutable_key_type)]
416 pub fn delegates(&self) -> &HashSet<Delegate> { &self.delegates }
417
418 #[allow(clippy::mutable_key_type)]
421 pub fn delegates_mut(&mut self) -> &mut HashSet<Delegate> {
422 &mut self.delegates
423 }
424
425 pub fn add_delegate(&mut self, delegate: Delegate) -> Result<()> {
426 if self.find_delegate_by_xid(&delegate).is_some() {
427 return Err(Error::Duplicate { item: "delegate".to_string() });
428 }
429 self.delegates.insert(delegate);
430
431 Ok(())
432 }
433
434 pub fn find_delegate_by_xid(
435 &self,
436 xid_provider: &dyn XIDProvider,
437 ) -> Option<&Delegate> {
438 self.delegates
439 .iter()
440 .find(|d| d.controller().read().xid() == xid_provider.xid())
441 }
442
443 pub fn find_delegate_by_reference(
444 &self,
445 reference: &Reference,
446 ) -> Option<&Delegate> {
447 self.delegates
448 .iter()
449 .find(|d| d.controller().read().xid().reference() == *reference)
450 }
451
452 pub fn take_delegate(
453 &mut self,
454 xid_provider: &dyn XIDProvider,
455 ) -> Option<Delegate> {
456 if let Some(delegate) = self.find_delegate_by_xid(xid_provider).cloned()
457 {
458 self.delegates.take(&delegate)
459 } else {
460 None
461 }
462 }
463
464 pub fn remove_delegate(
465 &mut self,
466 xid_provider: &dyn XIDProvider,
467 ) -> Result<()> {
468 if self.services_reference_delegate(xid_provider) {
469 return Err(Error::StillReferenced {
470 item: "delegate".to_string(),
471 });
472 }
473 if self.take_delegate(xid_provider).is_none() {
474 return Err(Error::NotFound { item: "delegate".to_string() });
475 }
476 Ok(())
477 }
478
479 pub fn find_service_by_uri(
480 &self,
481 uri: impl AsRef<URI>,
482 ) -> Option<&Service> {
483 self.services.iter().find(|s| s.uri() == uri.as_ref())
484 }
485
486 pub fn services(&self) -> &HashSet<Service> { &self.services }
487
488 pub fn add_service(&mut self, service: Service) -> Result<()> {
489 if self.find_service_by_uri(service.uri()).is_some() {
490 return Err(Error::Duplicate { item: "service".to_string() });
491 }
492 self.services.insert(service);
493 Ok(())
494 }
495
496 pub fn take_service(&mut self, uri: impl AsRef<URI>) -> Option<Service> {
497 if let Some(service) = self.find_service_by_uri(uri).cloned() {
498 self.services.take(&service)
499 } else {
500 None
501 }
502 }
503
504 pub fn check_services_consistency(&self) -> Result<()> {
505 for service in &self.services {
506 self.check_service_consistency(service)?;
507 }
508 Ok(())
509 }
510
511 pub fn check_service_consistency(&self, service: &Service) -> Result<()> {
512 if service.key_references().is_empty()
513 && service.delegate_references().is_empty()
514 {
515 return Err(Error::NoReferences { uri: service.uri().to_string() });
516 }
517
518 for key_reference in service.key_references() {
519 if self.find_key_by_reference(key_reference).is_none() {
520 return Err(Error::UnknownKeyReference {
521 reference: key_reference.to_string(),
522 uri: service.uri().to_string(),
523 });
524 }
525 }
526
527 for delegate_reference in service.delegate_references() {
528 if self
529 .find_delegate_by_reference(delegate_reference)
530 .is_none()
531 {
532 return Err(Error::UnknownDelegateReference {
533 reference: delegate_reference.to_string(),
534 uri: service.uri().to_string(),
535 });
536 }
537 }
538
539 if service.permissions().allow().is_empty() {
540 return Err(Error::NoPermissions {
541 uri: service.uri().to_string(),
542 });
543 }
544
545 Ok(())
546 }
547
548 pub fn check_contains_key(
549 &self,
550 key: &dyn PublicKeysProvider,
551 ) -> Result<()> {
552 if self.find_key_by_public_keys(key).is_none() {
553 return Err(Error::KeyNotFoundInDocument {
554 key: key.public_keys().to_string(),
555 });
556 }
557 Ok(())
558 }
559
560 pub fn check_contains_delegate(
561 &self,
562 xid_provider: &dyn XIDProvider,
563 ) -> Result<()> {
564 if self.find_delegate_by_xid(xid_provider).is_none() {
565 return Err(Error::DelegateNotFoundInDocument {
566 delegate: xid_provider.xid().to_string(),
567 });
568 }
569 Ok(())
570 }
571
572 pub fn services_reference_key(&self, key: &dyn PublicKeysProvider) -> bool {
573 let key_reference = key.public_keys().reference();
574 self.services
575 .iter()
576 .any(|service| service.key_references().contains(&key_reference))
577 }
578
579 pub fn services_reference_delegate(
580 &self,
581 xid_provider: &dyn XIDProvider,
582 ) -> bool {
583 let delegate_reference = xid_provider.xid().reference();
584 self.services.iter().any(|service| {
585 service.delegate_references().contains(&delegate_reference)
586 })
587 }
588
589 pub fn remove_service(&mut self, uri: impl AsRef<URI>) -> Result<()> {
590 if !self.services.iter().any(|s| s.uri() == uri.as_ref()) {
591 return Err(Error::NotFound { item: "service".to_string() });
592 }
593 self.services.retain(|s| s.uri() != uri.as_ref());
594 Ok(())
595 }
596
597 pub fn provenance(&self) -> Option<&ProvenanceMark> {
598 self.provenance.as_ref().map(|p| p.mark())
599 }
600
601 pub fn provenance_generator(&self) -> Option<&ProvenanceMarkGenerator> {
602 self.provenance.as_ref().and_then(|p| p.generator())
603 }
604
605 pub fn set_provenance(&mut self, provenance: Option<ProvenanceMark>) {
606 self.provenance = provenance.map(Provenance::new);
607 }
608
609 pub fn set_provenance_with_generator(
610 &mut self,
611 generator: ProvenanceMarkGenerator,
612 mark: ProvenanceMark,
613 ) {
614 self.provenance = Some(Provenance::new_with_generator(generator, mark));
615 }
616
617 pub fn next_provenance_mark_with_embedded_generator(
642 &mut self,
643 password: Option<Vec<u8>>,
644 date: Option<Date>,
645 info: Option<CBOR>,
646 ) -> Result<()> {
647 let provenance =
649 self.provenance.as_mut().ok_or(Error::NoProvenanceMark)?;
650
651 let current_mark = provenance.mark().clone();
653
654 let password_ref = password.as_deref();
656 let generator = provenance
657 .generator_mut(password_ref)?
658 .ok_or(Error::NoGenerator)?;
659
660 if generator.chain_id() != current_mark.chain_id() {
662 return Err(Error::ChainIdMismatch {
663 expected: current_mark.chain_id().to_vec(),
664 actual: generator.chain_id().to_vec(),
665 });
666 }
667
668 let expected_seq = current_mark.seq() + 1;
671 if generator.next_seq() != expected_seq {
672 return Err(Error::SequenceMismatch {
673 expected: expected_seq,
674 actual: generator.next_seq(),
675 });
676 }
677
678 let date = date.unwrap_or_else(Date::now);
680 let next_mark = generator.next(date, info);
681
682 provenance.set_mark(next_mark);
684
685 Ok(())
686 }
687
688 pub fn next_provenance_mark_with_provided_generator(
714 &mut self,
715 generator: &mut ProvenanceMarkGenerator,
716 date: Option<Date>,
717 info: Option<CBOR>,
718 ) -> Result<()> {
719 let provenance =
721 self.provenance.as_mut().ok_or(Error::NoProvenanceMark)?;
722
723 if provenance.has_generator() || provenance.has_encrypted_generator() {
725 return Err(Error::GeneratorConflict);
726 }
727
728 let current_mark = provenance.mark().clone();
730
731 if generator.chain_id() != current_mark.chain_id() {
733 return Err(Error::ChainIdMismatch {
734 expected: current_mark.chain_id().to_vec(),
735 actual: generator.chain_id().to_vec(),
736 });
737 }
738
739 let expected_seq = current_mark.seq() + 1;
742 if generator.next_seq() != expected_seq {
743 return Err(Error::SequenceMismatch {
744 expected: expected_seq,
745 actual: generator.next_seq(),
746 });
747 }
748
749 let date = date.unwrap_or_else(Date::now);
751 let next_mark = generator.next(date, info);
752
753 provenance.set_mark(next_mark);
755
756 Ok(())
757 }
758
759 pub fn to_envelope(
761 &self,
762 private_key_options: XIDPrivateKeyOptions,
763 generator_options: XIDGeneratorOptions,
764 signing_options: XIDSigningOptions,
765 ) -> Result<Envelope> {
766 let mut envelope = Envelope::new(self.xid);
767
768 envelope = self
770 .resolution_methods
771 .iter()
772 .cloned()
773 .fold(envelope, |envelope, method| {
774 envelope.add_assertion(DEREFERENCE_VIA, method)
775 });
776
777 envelope = self.keys.iter().cloned().fold(envelope, |envelope, key| {
779 envelope.add_assertion(
780 KEY,
781 key.into_envelope_opt(private_key_options.clone()),
782 )
783 });
784
785 envelope = self
787 .delegates
788 .iter()
789 .cloned()
790 .fold(envelope, |envelope, delegate| {
791 envelope.add_assertion(DELEGATE, delegate)
792 });
793
794 envelope = self
796 .services
797 .iter()
798 .cloned()
799 .fold(envelope, |envelope, service| {
800 envelope.add_assertion(SERVICE, service)
801 });
802
803 if let Some(provenance) = &self.provenance {
805 envelope = envelope.add_assertion(
806 PROVENANCE,
807 provenance.clone().into_envelope_opt(generator_options),
808 );
809 }
810
811 let envelope =
812 envelope.add_assertion_envelopes(&self.extra_assertions)?;
813
814 let envelope = self.attachments.add_to_envelope(envelope);
816
817 let envelope = self.edges.add_to_envelope(envelope);
819
820 let envelope = match signing_options {
822 XIDSigningOptions::None => envelope,
823 XIDSigningOptions::Inception => {
824 let inception_key =
825 self.inception_key().ok_or(Error::MissingInceptionKey)?;
826 let private_keys = inception_key
827 .private_keys()
828 .ok_or(Error::MissingInceptionKey)?;
829 envelope.sign(private_keys)
830 }
831 XIDSigningOptions::PrivateKeys(ref keys) => envelope.sign(keys),
832 XIDSigningOptions::SigningPrivateKey(ref key) => envelope.sign(key),
833 };
834
835 Ok(envelope)
836 }
837
838 pub fn from_envelope(
867 envelope: &Envelope,
868 password: Option<&[u8]>,
869 verify_signature: XIDVerifySignature,
870 ) -> Result<Self> {
871 match verify_signature {
872 XIDVerifySignature::None => {
873 let envelope_to_parse = if envelope.subject().is_wrapped() {
876 envelope.subject().try_unwrap()?
877 } else {
878 envelope.clone()
879 };
880
881 let attachments =
883 Attachments::try_from_envelope(&envelope_to_parse)
884 .map_err(Error::EnvelopeParsing)?;
885
886 let edges = Edges::try_from_envelope(&envelope_to_parse)
888 .map_err(Error::EnvelopeParsing)?;
889
890 let mut xid_document =
891 Self::from_envelope_inner(&envelope_to_parse, password)?;
892 xid_document.attachments = attachments;
893 xid_document.edges = edges;
894 Ok(xid_document)
895 }
896 XIDVerifySignature::Inception => {
897 if !envelope.subject().is_wrapped() {
899 return Err(Error::EnvelopeNotSigned);
900 }
901
902 let unwrapped = envelope.try_unwrap()?;
904
905 let attachments = Attachments::try_from_envelope(&unwrapped)
907 .map_err(Error::EnvelopeParsing)?;
908
909 let edges = Edges::try_from_envelope(&unwrapped)
911 .map_err(Error::EnvelopeParsing)?;
912
913 let mut xid_document =
914 Self::from_envelope_inner(&unwrapped, password)?;
915
916 let inception_key = xid_document
918 .inception_signing_key()
919 .ok_or(Error::MissingInceptionKey)?;
920
921 envelope
923 .verify(inception_key)
924 .map_err(|_| Error::SignatureVerificationFailed)?;
925
926 let xid = xid_document.xid();
928
929 if !xid.validate(inception_key) {
932 Err(Error::InvalidXid)
933 } else {
934 xid_document.attachments = attachments;
935 xid_document.edges = edges;
936 Ok(xid_document)
937 }
938 }
939 }
940 }
941
942 fn from_envelope_inner(
945 envelope: &Envelope,
946 password: Option<&[u8]>,
947 ) -> Result<Self> {
948 let xid: XID = envelope.subject().try_leaf()?.try_into()?;
949 let mut xid_document = XIDDocument::from(xid);
950 for assertion in envelope.assertions() {
951 let Ok(predicate) = assertion.try_predicate() else {
952 xid_document.extra_assertions.push(assertion);
953 continue;
954 };
955 let Ok(predicate) = predicate.try_known_value() else {
956 xid_document.extra_assertions.push(assertion);
957 continue;
958 };
959 let predicate = predicate.value();
960 match predicate {
961 DEREFERENCE_VIA_RAW => {
962 let object = assertion.try_object()?;
963 let method: URI = object
964 .try_leaf()?
965 .try_into()
966 .map_err(|_| Error::InvalidResolutionMethod)?;
967 xid_document.add_resolution_method(method);
968 }
969 KEY_RAW => {
970 let object = assertion.try_object()?;
971 let key = Key::try_from_envelope(&object, password)?;
972 xid_document.add_key(key)?;
973 }
974 DELEGATE_RAW => {
975 let object = assertion.try_object()?;
976 let delegate = Delegate::try_from(object)?;
977 xid_document.add_delegate(delegate)?;
978 }
979 SERVICE_RAW => {
980 let object = assertion.try_object()?;
981 let service = Service::try_from(object)?;
982 xid_document.add_service(service)?;
983 }
984 PROVENANCE_RAW => {
985 let object = assertion.try_object()?;
986 let provenance =
987 Provenance::try_from_envelope(&object, password)?;
988 if xid_document.provenance.is_some() {
989 return Err(Error::MultipleProvenanceMarks);
990 }
991 xid_document.provenance = Some(provenance);
992 }
993 ATTACHMENT_RAW => {
994 }
998 EDGE_RAW => {
999 }
1002 _ => {
1003 xid_document.extra_assertions.push(assertion);
1004 }
1005 }
1006 }
1007
1008 xid_document.check_services_consistency()?;
1009
1010 Ok(xid_document)
1011 }
1012
1013 pub fn to_signed_envelope(&self, signing_key: &impl Signer) -> Envelope {
1014 self.to_signed_envelope_opt(
1015 signing_key,
1016 XIDPrivateKeyOptions::default(),
1017 )
1018 }
1019
1020 pub fn to_signed_envelope_opt(
1021 &self,
1022 signing_key: &impl Signer,
1023 private_key_options: XIDPrivateKeyOptions,
1024 ) -> Envelope {
1025 self.to_envelope(
1026 private_key_options,
1027 XIDGeneratorOptions::default(),
1028 XIDSigningOptions::None,
1029 )
1030 .expect("envelope should not fail")
1031 .sign(signing_key)
1032 }
1033}
1034
1035impl Default for XIDDocument {
1036 fn default() -> Self {
1037 Self::new(XIDInceptionKeyOptions::Default, XIDGenesisMarkOptions::None)
1038 }
1039}
1040
1041bc_envelope::impl_attachable!(XIDDocument);
1042bc_envelope::impl_edgeable!(XIDDocument);
1043
1044impl XIDProvider for XIDDocument {
1045 fn xid(&self) -> XID { self.xid }
1046}
1047
1048impl ReferenceProvider for XIDDocument {
1049 fn reference(&self) -> Reference { self.xid.reference() }
1050}
1051
1052impl AsRef<XIDDocument> for XIDDocument {
1053 fn as_ref(&self) -> &XIDDocument { self }
1054}
1055
1056impl From<XIDDocument> for XID {
1057 fn from(doc: XIDDocument) -> Self { doc.xid }
1058}
1059
1060impl From<XID> for XIDDocument {
1061 fn from(xid: XID) -> Self { XIDDocument::from_xid(xid) }
1062}
1063
1064impl From<PublicKeys> for XIDDocument {
1065 fn from(inception_key: PublicKeys) -> Self {
1066 XIDDocument::new(
1067 XIDInceptionKeyOptions::PublicKeys(inception_key),
1068 XIDGenesisMarkOptions::None,
1069 )
1070 }
1071}
1072
1073impl From<PrivateKeyBase> for XIDDocument {
1074 fn from(inception_key: PrivateKeyBase) -> Self {
1075 XIDDocument::new(
1076 XIDInceptionKeyOptions::PrivateKeyBase(inception_key),
1077 XIDGenesisMarkOptions::None,
1078 )
1079 }
1080}
1081
1082impl From<&PrivateKeyBase> for XIDDocument {
1083 fn from(inception_key: &PrivateKeyBase) -> Self {
1084 XIDDocument::new(
1085 XIDInceptionKeyOptions::PrivateKeyBase(inception_key.clone()),
1086 XIDGenesisMarkOptions::None,
1087 )
1088 }
1089}
1090
1091impl From<XIDDocument> for Envelope {
1092 fn from(value: XIDDocument) -> Self {
1093 if value.is_empty() {
1094 return value.xid.to_envelope();
1095 }
1096 value
1097 .to_envelope(
1098 XIDPrivateKeyOptions::default(),
1099 XIDGeneratorOptions::default(),
1100 XIDSigningOptions::default(),
1101 )
1102 .expect("envelope should not fail")
1103 }
1104}
1105
1106impl TryFrom<&Envelope> for XIDDocument {
1107 type Error = Error;
1108
1109 fn try_from(envelope: &Envelope) -> Result<Self> {
1110 Self::from_envelope(envelope, None, XIDVerifySignature::None)
1111 }
1112}
1113
1114impl TryFrom<Envelope> for XIDDocument {
1115 type Error = Error;
1116
1117 fn try_from(envelope: Envelope) -> Result<Self> {
1118 XIDDocument::try_from(&envelope)
1119 }
1120}
1121
1122impl CBORTagged for XIDDocument {
1123 fn cbor_tags() -> Vec<Tag> { tags_for_values(&[TAG_XID]) }
1124}
1125
1126impl From<XIDDocument> for CBOR {
1127 fn from(value: XIDDocument) -> Self { value.tagged_cbor() }
1128}
1129
1130impl CBORTaggedEncodable for XIDDocument {
1131 fn untagged_cbor(&self) -> CBOR {
1132 if self.is_empty() {
1133 return self.xid.untagged_cbor();
1134 }
1135 self.to_envelope(
1136 XIDPrivateKeyOptions::default(),
1137 XIDGeneratorOptions::default(),
1138 XIDSigningOptions::None,
1139 )
1140 .expect("envelope should not fail")
1141 .to_cbor()
1142 }
1143}
1144
1145impl TryFrom<CBOR> for XIDDocument {
1146 type Error = dcbor::Error;
1147
1148 fn try_from(cbor: CBOR) -> dcbor::Result<Self> {
1149 Self::from_tagged_cbor(cbor)
1150 }
1151}
1152
1153impl CBORTaggedDecodable for XIDDocument {
1154 fn from_untagged_cbor(cbor: CBOR) -> dcbor::Result<Self> {
1155 if let Some(byte_string) = cbor.clone().into_byte_string() {
1156 let xid = XID::from_data_ref(byte_string)?;
1157 return Ok(Self::from_xid(xid));
1158 }
1159
1160 let envelope = Envelope::try_from(cbor)?;
1161 let xid_doc: Self =
1162 envelope.try_into().map_err(|e: Error| match e {
1163 Error::Cbor(cbor_err) => cbor_err,
1164 _ => CBORError::msg(e.to_string()),
1165 })?;
1166 Ok(xid_doc)
1167 }
1168}