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