1use base64::prelude::*;
21use iref::UriBuf;
22use serde::{Deserialize, Serialize};
23use serde_json::Value;
24use service::convert_service;
25use ssi::{
26 OneOrMany,
27 dids::{
28 DID, DIDBuf, DIDKey, DIDMethod, DIDMethodResolver, DIDURL, DIDURLBuf, DIDURLReferenceBuf,
29 Document, RelativeDIDURLBuf,
30 document::{
31 self, DIDVerificationMethod, Resource, Service, VerificationRelationships,
32 representation::{self, MediaType},
33 service::Endpoint,
34 verification_method,
35 },
36 key::VerificationMethodType,
37 resolution::{self, Content, Error, Options, Output, Parameters},
38 },
39 jwk::Params,
40 prelude::*,
41};
42use std::{collections::BTreeMap, fmt};
43use thiserror::Error;
44use wasm_bindgen::prelude::*;
45
46pub mod service;
47
48#[derive(Error, Debug)]
49pub enum DIDPeerError {
50 #[error("Unsupported key type")]
51 UnsupportedKeyType,
52 #[error("Unsupported curve: {0}")]
53 UnsupportedCurve(String),
54 #[error("Unsupported source")]
55 UnsupportedSource,
56 #[error("Syntax error on Service definition: {0}")]
57 SyntaxErrorServiceDefinition(String),
58 #[error("Unsupported Method. Must be method 2")]
59 MethodNotSupported,
60 #[error("Key Parsing error {0}")]
61 KeyParsingError(String),
62 #[error("DID Document doesn't contain any verificationMethod items")]
63 MissingVerificationMethods,
64 #[error("JSON Parsing error: {0}")]
65 JsonParsingError(String),
66 #[error("Internal error: {0}")]
67 InternalError(String),
68}
69
70impl From<DIDPeerError> for JsValue {
72 fn from(err: DIDPeerError) -> JsValue {
73 JsValue::from(err.to_string())
74 }
75}
76
77pub struct DIDPeer;
78
79#[derive(Debug, Serialize, Deserialize)]
83#[serde(untagged)]
84pub enum PeerServiceEndPoint {
85 Short(PeerServiceEndPointShort),
86 Long(PeerServiceEndPointLong),
87}
88
89impl PeerServiceEndPoint {
90 pub fn to_short(&self) -> PeerServiceEndPointShort {
91 match self {
92 PeerServiceEndPoint::Short(short) => short.clone(),
93 PeerServiceEndPoint::Long(long) => match long {
94 PeerServiceEndPointLong::URI(uri) => PeerServiceEndPointShort::URI(uri.to_string()),
95 PeerServiceEndPointLong::Map(map) => match map {
96 OneOrMany::One(single) => {
97 PeerServiceEndPointShort::Map(OneOrMany::One(PeerServiceEndPointShortMap {
98 uri: single.uri.to_string(),
99 a: single.accept.clone(),
100 r: single.routing_keys.clone(),
101 }))
102 }
103 OneOrMany::Many(many) => PeerServiceEndPointShort::Map(OneOrMany::Many(
104 many.iter()
105 .map(|m| PeerServiceEndPointShortMap {
106 uri: m.uri.to_string(),
107 a: m.accept.clone(),
108 r: m.routing_keys.clone(),
109 })
110 .collect(),
111 )),
112 },
113 },
114 }
115 }
116
117 pub fn to_long(&self) -> PeerServiceEndPointLong {
118 match self {
119 PeerServiceEndPoint::Short(short) => PeerServiceEndPointLong::from(short.clone()),
120 PeerServiceEndPoint::Long(long) => long.clone(),
121 }
122 }
123}
124
125#[derive(Debug, Clone, Serialize, Deserialize)]
127#[serde(untagged)]
128pub enum PeerServiceEndPointShort {
129 URI(String),
130 Map(OneOrMany<PeerServiceEndPointShortMap>),
131}
132
133#[derive(Debug, Clone, Serialize, Deserialize)]
134pub struct PeerServiceEndPointShortMap {
135 pub uri: String,
136 pub a: Vec<String>,
137 pub r: Vec<String>,
138}
139
140#[derive(Debug, Clone, Serialize, Deserialize)]
142#[serde(untagged)]
143pub enum PeerServiceEndPointLong {
144 URI(String),
145 Map(OneOrMany<PeerServiceEndPointLongMap>),
146}
147
148#[derive(Debug, Clone, Serialize, Deserialize)]
149pub struct PeerServiceEndPointLongMap {
150 pub uri: String,
151 pub accept: Vec<String>,
152 pub routing_keys: Vec<String>,
153}
154
155impl From<PeerServiceEndPointShort> for PeerServiceEndPointLong {
156 fn from(service: PeerServiceEndPointShort) -> Self {
157 match service {
158 PeerServiceEndPointShort::URI(uri) => PeerServiceEndPointLong::URI(uri),
159 PeerServiceEndPointShort::Map(map) => match map {
160 OneOrMany::One(single) => {
161 PeerServiceEndPointLong::Map(OneOrMany::One(PeerServiceEndPointLongMap {
162 uri: single.uri,
163 accept: single.a,
164 routing_keys: single.r,
165 }))
166 }
167 OneOrMany::Many(many) => PeerServiceEndPointLong::Map(OneOrMany::Many(
168 many.iter()
169 .map(|m| PeerServiceEndPointLongMap {
170 uri: m.uri.clone(),
171 accept: m.a.clone(),
172 routing_keys: m.r.clone(),
173 })
174 .collect(),
175 )),
176 },
177 }
178 }
179}
180#[derive(Debug, Serialize, Deserialize)]
182pub struct DIDPeerService {
183 #[serde(rename = "t")]
184 #[serde(alias = "t")]
185 pub _type: String,
186 #[serde(rename = "s")]
187 #[serde(alias = "s")]
188 pub service_end_point: PeerServiceEndPoint, #[serde(skip_serializing_if = "Option::is_none")]
192 pub id: Option<String>,
193}
194
195impl DIDPeerService {
196 fn convert(did: &str, service: DIDPeerService) -> Result<Service, DIDPeerError> {
197 let service_endpoint = match serde_json::to_value(PeerServiceEndPoint::to_long(
198 &service.service_end_point,
199 )) {
200 Ok(value) => {
201 if value.is_string() {
202 if let Some(value) = value.as_str() {
203 if let Ok(uri) = UriBuf::new(value.as_bytes().to_vec()) {
204 Some(OneOrMany::One(Endpoint::Uri(uri)))
205 } else {
206 return Err(DIDPeerError::SyntaxErrorServiceDefinition(format!(
207 "Couldn't convert ServiceEndPoint to a valid URI: {}",
208 value
209 )));
210 }
211 } else {
212 return Err(DIDPeerError::SyntaxErrorServiceDefinition(format!(
213 "Service URI appears to be a string, but can't parse as a string: {}",
214 value
215 )));
216 }
217 } else {
218 Some(OneOrMany::One(Endpoint::Map(value)))
219 }
220 }
221 Err(err) => {
222 return Err(DIDPeerError::SyntaxErrorServiceDefinition(format!(
223 "Couldn't convert ServiceEndPoint to a valid representation. Reason: {}",
224 err
225 )));
226 }
227 };
228
229 let id = if let Some(id) = service.id {
230 [did, &id].concat()
231 } else {
232 [did, "#service"].concat()
233 };
234
235 let id = match UriBuf::new(id.as_bytes().to_vec()) {
236 Ok(uri) => uri,
237 Err(e) => {
238 return Err(DIDPeerError::SyntaxErrorServiceDefinition(format!(
239 "Error parsing service id: {}. Reason: {:?}",
240 id, e
241 )));
242 }
243 };
244
245 Ok(Service {
246 id,
247 type_: OneOrMany::One("DIDCommMessaging".into()),
248 service_endpoint,
249 property_set: BTreeMap::new(),
250 })
251 }
252}
253
254#[derive(Clone)]
255#[wasm_bindgen]
256pub enum DIDPeerKeys {
260 Verification,
261 Encryption,
262}
263
264impl fmt::Display for DIDPeerKeys {
265 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
266 match *self {
267 DIDPeerKeys::Verification => write!(f, "verification"),
268 DIDPeerKeys::Encryption => write!(f, "encryption"),
269 }
270 }
271}
272
273#[derive(Clone)]
274#[wasm_bindgen]
275pub enum DIDPeerKeyType {
277 Ed25519,
278 Secp256k1,
279 P256,
280}
281
282impl fmt::Display for DIDPeerKeyType {
283 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
284 match *self {
285 DIDPeerKeyType::Ed25519 => write!(f, "ed25519"),
286 DIDPeerKeyType::Secp256k1 => write!(f, "secp256k1"),
287 DIDPeerKeyType::P256 => write!(f, "p256"),
288 }
289 }
290}
291
292#[derive(Clone)]
293#[wasm_bindgen(getter_with_clone)]
294pub struct DIDPeerCreateKeys {
299 pub purpose: DIDPeerKeys,
300 pub type_: Option<DIDPeerKeyType>,
301 pub public_key_multibase: Option<String>,
302}
303
304#[wasm_bindgen]
305impl DIDPeerCreateKeys {
306 #[wasm_bindgen(constructor)]
307 pub fn new(
308 purpose: DIDPeerKeys,
309 type_: Option<DIDPeerKeyType>,
310 public_key_multibase: Option<String>,
311 ) -> Self {
312 DIDPeerCreateKeys {
313 purpose,
314 type_,
315 public_key_multibase,
316 }
317 }
318}
319
320#[derive(Clone, Debug, Serialize, Deserialize)]
328#[wasm_bindgen(getter_with_clone)]
329pub struct DIDPeerCreatedKeys {
330 pub key_multibase: String,
331 pub curve: String,
332 pub d: String,
333 pub x: String,
334 pub y: Option<String>,
335}
336
337fn process_key(did: &str, id: &str, public_key: &str) -> Result<DIDVerificationMethod, Error> {
339 let mut properties = BTreeMap::new();
340
341 properties.insert(
342 "publicKeyMultibase".to_string(),
343 Value::String(public_key.to_string()),
344 );
345
346 Ok(DIDVerificationMethod {
347 id: DIDURLBuf::from_string(["did:peer:", did, id].concat()).unwrap(),
348 type_: "Multikey".to_string(),
349 controller: DIDBuf::from_string(["did:peer:", did].concat()).unwrap(),
350 properties,
351 })
352}
353
354impl DIDMethodResolver for DIDPeer {
355 async fn resolve_method_representation<'a>(
356 &'a self,
357 method_specific_id: &'a str,
358 options: Options,
359 ) -> Result<Output<Vec<u8>>, Error> {
360 let did = ["did:peer:", method_specific_id].concat();
361
362 if let Some(id) = method_specific_id.strip_prefix('0') {
364 return DIDKey.resolve_method_representation(id, options).await;
365 }
366
367 if !method_specific_id.starts_with('2') {
369 return Err(Error::MethodNotSupported(
370 "did:peer version 2 supported only".to_string(),
371 ));
372 }
373
374 let mut context = BTreeMap::new();
375 context.insert("@base".to_string(), serde_json::json!(method_specific_id));
376
377 let mut verification_methods: Vec<DIDVerificationMethod> = Vec::new();
378 let mut verification_relationships: VerificationRelationships =
379 VerificationRelationships::default();
380
381 let mut services: Vec<Service> = Vec::new();
385
386 let parts: Vec<&str> = method_specific_id[2..].split('.').collect();
389 let mut key_count: u32 = 1;
390 let mut service_idx: u32 = 0;
391
392 for part in parts {
393 let ch = part.chars().next();
394 match ch {
395 Some(e) => {
396 match e {
397 'A' => {
398 verification_methods.push(process_key(
400 method_specific_id,
401 &["#key-", &key_count.to_string()].concat(),
402 &part[1..],
403 )?);
404
405 verification_relationships.assertion_method.push(
406 verification_method::ValueOrReference::Reference(
407 DIDURLReferenceBuf::Relative(
408 RelativeDIDURLBuf::new(
409 ["#key-", &key_count.to_string()]
410 .concat()
411 .as_bytes()
412 .to_vec(),
413 )
414 .unwrap(),
415 ),
416 ),
417 );
418 key_count += 1;
419 }
420 'D' => {
421 verification_methods.push(process_key(
423 method_specific_id,
424 &["#key-", &key_count.to_string()].concat(),
425 &part[1..],
426 )?);
427
428 verification_relationships.capability_delegation.push(
429 verification_method::ValueOrReference::Reference(
430 DIDURLReferenceBuf::Relative(
431 RelativeDIDURLBuf::new(
432 ["#key-", &key_count.to_string()]
433 .concat()
434 .as_bytes()
435 .to_vec(),
436 )
437 .unwrap(),
438 ),
439 ),
440 );
441 key_count += 1;
442 }
443 'E' => {
444 verification_methods.push(process_key(
446 method_specific_id,
447 &["#key-", &key_count.to_string()].concat(),
448 &part[1..],
449 )?);
450 verification_relationships.key_agreement.push(
451 verification_method::ValueOrReference::Reference(
452 DIDURLReferenceBuf::Relative(
453 RelativeDIDURLBuf::new(
454 ["#key-", &key_count.to_string()]
455 .concat()
456 .as_bytes()
457 .to_vec(),
458 )
459 .unwrap(),
460 ),
461 ),
462 );
463 key_count += 1;
464 }
465 'I' => {
466 verification_methods.push(process_key(
468 method_specific_id,
469 &["#key-", &key_count.to_string()].concat(),
470 &part[1..],
471 )?);
472
473 verification_relationships.capability_invocation.push(
474 verification_method::ValueOrReference::Reference(
475 DIDURLReferenceBuf::Relative(
476 RelativeDIDURLBuf::new(
477 ["#key-", &key_count.to_string()]
478 .concat()
479 .as_bytes()
480 .to_vec(),
481 )
482 .unwrap(),
483 ),
484 ),
485 );
486 key_count += 1;
487 }
488 'V' => {
489 verification_methods.push(process_key(
491 method_specific_id,
492 &["#key-", &key_count.to_string()].concat(),
493 &part[1..],
494 )?);
495
496 verification_relationships.authentication.push(
497 verification_method::ValueOrReference::Reference(
498 DIDURLReferenceBuf::Relative(
499 RelativeDIDURLBuf::new(
500 ["#key-", &key_count.to_string()]
501 .concat()
502 .as_bytes()
503 .to_vec(),
504 )
505 .unwrap(),
506 ),
507 ),
508 );
509 verification_relationships.assertion_method.push(
510 verification_method::ValueOrReference::Reference(
511 DIDURLReferenceBuf::Relative(
512 RelativeDIDURLBuf::new(
513 ["#key-", &key_count.to_string()]
514 .concat()
515 .as_bytes()
516 .to_vec(),
517 )
518 .unwrap(),
519 ),
520 ),
521 );
522
523 key_count += 1;
524 }
525 'S' => {
526 let service = convert_service(&did, part, service_idx)
528 .map_err(|e| Error::Internal(e.to_string()))?;
529 services.push(service);
530 service_idx += 1;
531 }
532 other => {
533 return Err(Error::RepresentationNotSupported(format!(
534 "An invalid Purpose Code ({}) was found in the DID",
535 other
536 )));
537 }
538 }
539 }
540 None => {
541 }
544 }
545 }
546
547 let vm_type = match options.parameters.public_key_format {
548 Some(name) => VerificationMethodType::from_name(&name).ok_or_else(|| {
549 Error::Internal(format!(
550 "verification method type `{name}` unsupported by did:peer"
551 ))
552 })?,
553 None => VerificationMethodType::Multikey,
554 };
555
556 let mut doc =
557 Document::new(DIDBuf::from_string(["did:peer:", method_specific_id].concat()).unwrap());
558 doc.verification_method = verification_methods;
559 doc.verification_relationships = verification_relationships;
560 doc.service = services;
561
562 let mut json_ld_context = Vec::new();
563 if let Some(context) = vm_type.context_entry() {
564 json_ld_context.push(context)
565 }
566
567 let content_type = options.accept.unwrap_or(MediaType::JsonLd);
568
569 let represented = doc.into_representation(representation::Options::from_media_type(
570 content_type,
571 move || representation::json_ld::Options {
572 context: representation::json_ld::Context::array(
573 representation::json_ld::DIDContext::V1,
574 json_ld_context,
575 ),
576 },
577 ));
578
579 Ok(resolution::Output::new(
580 represented.to_bytes(),
581 document::Metadata::default(),
582 resolution::Metadata::from_content_type(Some(content_type.to_string())),
583 ))
584 }
585}
586
587impl DIDMethod for DIDPeer {
588 const DID_METHOD_NAME: &'static str = "peer";
589}
590
591impl DIDPeer {
592 pub fn create_peer_did(
639 keys: &Vec<DIDPeerCreateKeys>,
640 services: Option<&Vec<DIDPeerService>>,
641 ) -> Result<(String, Vec<DIDPeerCreatedKeys>), DIDPeerError> {
642 let mut result = String::from("did:peer:2");
643
644 let mut private_keys: Vec<DIDPeerCreatedKeys> = vec![];
645 for key in keys {
646 let public_key = if let Some(key) = key.public_key_multibase.as_ref() {
648 key.clone()
649 } else {
650 let jwk = match &key.type_ {
651 Some(type_) => match type_ {
652 DIDPeerKeyType::Ed25519 => match JWK::generate_ed25519() {
653 Ok(k) => k,
654 Err(e) => {
655 return Err(DIDPeerError::InternalError(format!(
656 "Failed to generate ed25519 key. Reason: {}",
657 e
658 )));
659 }
660 },
661 DIDPeerKeyType::Secp256k1 => JWK::generate_secp256k1(),
662 DIDPeerKeyType::P256 => JWK::generate_p256(),
663 },
664 None => return Err(DIDPeerError::UnsupportedKeyType),
665 };
666 let did = if let Ok(output) = ssi::dids::DIDKey::generate(&jwk) {
667 output.to_string()
668 } else {
669 return Err(DIDPeerError::InternalError(
670 "Couldn't create did:key".to_string(),
671 ));
672 };
673
674 match jwk.params {
675 Params::OKP(map) => {
676 let d = if let Some(d) = &map.private_key {
677 d
678 } else {
679 return Err(DIDPeerError::KeyParsingError(
680 "Missing private key".to_string(),
681 ));
682 };
683 private_keys.push(DIDPeerCreatedKeys {
684 key_multibase: did[8..].to_string(),
685 curve: map.curve.clone(),
686 d: String::from(d),
687 x: String::from(map.public_key.clone()),
688 y: None,
689 })
690 }
691 Params::EC(map) => {
692 let curve = if let Some(curve) = &map.curve {
693 curve
694 } else {
695 return Err(DIDPeerError::KeyParsingError("Missing curve".to_string()));
696 };
697 let d = if let Some(d) = &map.ecc_private_key {
698 d
699 } else {
700 return Err(DIDPeerError::KeyParsingError(
701 "Missing private key".to_string(),
702 ));
703 };
704
705 let x = if let Some(x) = &map.x_coordinate {
706 x
707 } else {
708 return Err(DIDPeerError::KeyParsingError(
709 "Missing public key (x)".to_string(),
710 ));
711 };
712 let y = if let Some(y) = &map.y_coordinate {
713 y
714 } else {
715 return Err(DIDPeerError::KeyParsingError(
716 "Missing public key (y)".to_string(),
717 ));
718 };
719
720 private_keys.push(DIDPeerCreatedKeys {
721 key_multibase: did[8..].to_string(),
722 curve: curve.into(),
723 d: String::from(d),
724 x: String::from(x),
725 y: Some(String::from(y)),
726 })
727 }
728 _ => return Err(DIDPeerError::UnsupportedKeyType),
729 }
730
731 did[8..].to_string()
732 };
733
734 match key.purpose {
736 DIDPeerKeys::Verification => {
737 result.push_str(&format!(".V{}", public_key));
738 }
739 DIDPeerKeys::Encryption => {
740 result.push_str(&format!(".E{}", public_key));
741 }
742 }
743 }
744
745 if let Some(services) = services {
746 for service in services {
747 let service = serde_json::to_string(&service).map_err(|e| {
748 DIDPeerError::SyntaxErrorServiceDefinition(format!(
749 "Error parsing service: {}",
750 e
751 ))
752 })?;
753 result.push_str(&format!(".S{}", BASE64_URL_SAFE_NO_PAD.encode(service)));
754 }
755 }
756
757 Ok((result, private_keys))
758 }
759
760 pub async fn expand_keys(doc: &Document) -> Result<Document, DIDPeerError> {
764 let mut new_doc = doc.clone();
765
766 let mut new_vms: Vec<DIDVerificationMethod> = vec![];
767 for v_method in &doc.verification_method {
768 new_vms.push(Self::_convert_vm(v_method).await?);
769 }
770
771 new_doc.verification_method = new_vms;
772 Ok(new_doc)
773 }
774
775 async fn _convert_vm(
777 method: &DIDVerificationMethod,
778 ) -> Result<DIDVerificationMethod, DIDPeerError> {
779 let current_controller = method.controller.clone();
780 let current_id = method.id.clone();
781 let did_key = if let Some(key) = method.properties.get("publicKeyBase58") {
782 ["did:key:", key.as_str().unwrap()].concat()
783 } else if let Some(key) = method.properties.get("publicKeyMultibase") {
784 ["did:key:", key.as_str().unwrap()].concat()
785 } else {
786 return Err(DIDPeerError::KeyParsingError(
787 "Failed to convert verification_method. Reason: Missing publicKeyBase58"
788 .to_string(),
789 ));
790 };
791
792 let key_method = DIDKey;
793
794 let output = match key_method
795 .dereference_with(
796 DIDURL::new::<String>(&did_key.clone()).unwrap(),
797 Options {
798 accept: None,
799 parameters: Parameters {
800 public_key_format: Some("JsonWebKey2020".to_string()),
801 ..Default::default()
802 },
803 },
804 )
805 .await
806 {
807 Ok(output) => output.content,
808 Err(e) => {
809 return Err(DIDPeerError::KeyParsingError(format!(
810 "Failed to resolve key ({}). Reason: {}",
811 did_key, e
812 )));
813 }
814 };
815
816 if let Content::Resource(Resource::Document(doc)) = output {
817 if let Some(vm) = doc.into_any_verification_method() {
818 let mut new_vm = vm.clone();
819 new_vm.controller = current_controller;
820 new_vm.id = current_id;
821 return Ok(new_vm);
822 }
823 }
824
825 Err(DIDPeerError::KeyParsingError(
826 "Failed to convert verification_method. Reason: Missing verification_method"
827 .to_string(),
828 ))
829 }
830}
831
832#[cfg(test)]
833mod test {
834 use crate::{
835 DIDPeer, DIDPeerCreateKeys, DIDPeerKeyType, DIDPeerKeys, DIDPeerService,
836 PeerServiceEndPoint, PeerServiceEndPointLong, PeerServiceEndPointLongMap,
837 };
838
839 use ssi::{
840 JWK,
841 dids::{DID, DIDBuf, DIDResolver, document::DIDVerificationMethod},
842 verification_methods::ssi_core::OneOrMany,
843 };
844
845 const DID_PEER: &str = "did:peer:2.Vz6MkiToqovww7vYtxm1xNM15u9JzqzUFZ1k7s7MazYJUyAxv.EzQ3shQLqRUza6AMJFbPuMdvFRFWm1wKviQRnQSC1fScovJN4s.SeyJ0IjoiRElEQ29tbU1lc3NhZ2luZyIsInMiOnsidXJpIjoiaHR0cHM6Ly8xMjcuMC4wLjE6NzAzNyIsImEiOlsiZGlkY29tbS92MiJdLCJyIjpbXX19";
846
847 #[should_panic(
848 expected = "Failed to convert verification_method. Reason: Missing publicKeyBase58"
849 )]
850 #[tokio::test]
851 async fn expand_keys_throws_key_parsing_missing_pbk58_error() {
852 let peer = DIDPeer;
853 let output = peer
854 .resolve(DID::new::<String>(&DID_PEER.to_string()).unwrap())
855 .await
856 .unwrap();
857
858 let mut document = output.document.document().clone();
859 let mut new_vms: Vec<DIDVerificationMethod> = vec![];
860 for mut vm in document.verification_method {
861 vm.properties.remove("publicKeyMultibase");
862 new_vms.push(vm);
863 }
864
865 document.verification_method = new_vms;
866 let _expanded_doc = DIDPeer::expand_keys(&document).await.unwrap();
867 }
868
869 #[tokio::test]
870 async fn expand_keys_works() {
871 let peer = DIDPeer;
872 let document = peer
873 .resolve(DID::new::<String>(&DID_PEER.to_string()).unwrap())
874 .await
875 .expect("Couldn't resolve DID");
876
877 let vm_before_expansion = document.clone().document.verification_method.clone();
878 let expanded_doc = DIDPeer::expand_keys(&document.document).await.unwrap();
879 let vms_after_expansion = expanded_doc.verification_method;
880
881 for vm in vms_after_expansion.clone() {
882 assert!(vm.id.starts_with("did:peer"));
883 }
884 assert_eq!(vm_before_expansion.len(), vms_after_expansion.len())
885 }
886
887 #[tokio::test]
888 async fn create_peer_did_without_keys_and_services() {
889 let keys: Vec<DIDPeerCreateKeys> = vec![];
890 let services: Vec<DIDPeerService> = vec![];
891
892 let (did, _) = DIDPeer::create_peer_did(&keys, Some(&services)).unwrap();
893 let parts: Vec<&str> = did.split(":").collect();
894
895 assert_eq!(parts.len(), 3);
896 assert_eq!(parts[1], "peer");
897 assert!(parts[2].len() == 1);
898 }
899
900 #[tokio::test]
901 async fn create_peer_did_without_keys() {
902 let keys: Vec<DIDPeerCreateKeys> = vec![];
903 let services = vec![DIDPeerService {
904 _type: "dm".into(),
905 service_end_point: PeerServiceEndPoint::Long(PeerServiceEndPointLong::Map(
906 OneOrMany::One(PeerServiceEndPointLongMap {
907 uri: "https://localhost:7037".into(),
908 accept: vec!["didcomm/v2".into()],
909 routing_keys: vec![],
910 }),
911 )),
912 id: None,
913 }];
914
915 let (did, _) = DIDPeer::create_peer_did(&keys, Some(&services)).unwrap();
916 let parts: Vec<&str> = did.split(":").collect();
917 let method_ids: Vec<&str> = parts[2].split(".").collect();
918
919 assert_eq!(parts.len(), 3);
920 assert_eq!(parts[1], "peer");
921 assert!(method_ids.len() > 1);
922 assert!(method_ids[1].len() > 1);
923 }
924
925 #[tokio::test]
926 async fn create_peer_did_without_services() {
927 let (e_did_key, v_did_key, keys) = _get_keys(Some(DIDPeerKeyType::Ed25519), true);
928 let services: Vec<DIDPeerService> = vec![];
929
930 let (did, _) = DIDPeer::create_peer_did(&keys, Some(&services)).unwrap();
931 let parts: Vec<&str> = did.split(":").collect();
932 let mut method_ids: Vec<&str> = parts[2].split(".").collect();
933 method_ids = method_ids[1..].to_vec();
934 let keys_multibase = [v_did_key[8..].to_string(), e_did_key[8..].to_string()];
935
936 method_ids.iter().take(2).for_each(|id| {
937 assert!(keys_multibase.contains(&id[1..].to_string()));
938 });
939 assert_eq!(parts.len(), 3);
940 assert_eq!(parts[1], "peer");
941 }
942
943 #[should_panic(expected = "UnsupportedKeyType")]
944 #[tokio::test]
945 async fn create_peer_did_should_throw_unsupported_key_error_p384() {
946 let (_, _, keys) = _get_keys(None, false);
947 let services = vec![DIDPeerService {
949 _type: "dm".into(),
950 service_end_point: PeerServiceEndPoint::Long(PeerServiceEndPointLong::Map(
951 OneOrMany::One(PeerServiceEndPointLongMap {
952 uri: "https://localhost:7037".into(),
953 accept: vec!["didcomm/v2".into()],
954 routing_keys: vec![],
955 }),
956 )),
957 id: None,
958 }];
959
960 DIDPeer::create_peer_did(&keys, Some(&services)).unwrap();
961 }
962
963 #[tokio::test]
964 async fn create_peer_did_works_ed25519_without_passing_pub_key() {
965 let (_, _, keys) = _get_keys(Some(DIDPeerKeyType::Ed25519), false);
966
967 let services = vec![DIDPeerService {
969 _type: "dm".into(),
970 service_end_point: PeerServiceEndPoint::Long(PeerServiceEndPointLong::Map(
971 OneOrMany::One(PeerServiceEndPointLongMap {
972 uri: "https://localhost:7037".into(),
973 accept: vec!["didcomm/v2".into()],
974 routing_keys: vec![],
975 }),
976 )),
977 id: None,
978 }];
979
980 let (did, keys) = DIDPeer::create_peer_did(&keys, Some(&services)).unwrap();
981 let parts: Vec<&str> = did.split(":").collect();
982 let method_ids: Vec<&str> = parts[2].split(".").collect();
983
984 assert_eq!(keys.len(), 2);
985 assert_eq!(parts.len(), 3);
986 assert_eq!(parts[1], "peer");
987 assert_eq!(method_ids.first().unwrap().parse::<i32>().unwrap(), 2);
988 assert_eq!(method_ids.len(), 4);
989 }
990
991 #[tokio::test]
992 async fn create_peer_did_works_p256_without_passing_pub_key() {
993 let (_, _, keys) = _get_keys(Some(DIDPeerKeyType::P256), false);
994
995 let services = vec![DIDPeerService {
997 _type: "dm".into(),
998 service_end_point: PeerServiceEndPoint::Long(PeerServiceEndPointLong::Map(
999 OneOrMany::One(PeerServiceEndPointLongMap {
1000 uri: "https://localhost:7037".into(),
1001 accept: vec!["didcomm/v2".into()],
1002 routing_keys: vec![],
1003 }),
1004 )),
1005 id: None,
1006 }];
1007
1008 let (did, keys) = DIDPeer::create_peer_did(&keys, Some(&services)).unwrap();
1009 let parts: Vec<&str> = did.split(":").collect();
1010 let method_ids: Vec<&str> = parts[2].split(".").collect();
1011
1012 assert_eq!(keys.len(), 2);
1013 assert_eq!(parts.len(), 3);
1014 assert_eq!(parts[1], "peer");
1015 assert_eq!(method_ids.first().unwrap().parse::<i32>().unwrap(), 2);
1016 assert_eq!(method_ids.len(), 4);
1017 }
1018
1019 #[tokio::test]
1020 async fn create_peer_did_works_secp256k1_without_passing_pub_key() {
1021 let (_, _, keys) = _get_keys(Some(DIDPeerKeyType::Secp256k1), false);
1022
1023 let services = vec![DIDPeerService {
1025 _type: "dm".into(),
1026 service_end_point: PeerServiceEndPoint::Long(PeerServiceEndPointLong::Map(
1027 OneOrMany::One(PeerServiceEndPointLongMap {
1028 uri: "https://localhost:7037".into(),
1029 accept: vec!["didcomm/v2".into()],
1030 routing_keys: vec![],
1031 }),
1032 )),
1033 id: None,
1034 }];
1035
1036 let (did, keys) = DIDPeer::create_peer_did(&keys, Some(&services)).unwrap();
1037
1038 let parts: Vec<&str> = did.split(":").collect();
1039 let method_ids: Vec<&str> = parts[2].split(".").collect();
1040
1041 assert_eq!(keys.len(), 2);
1042 assert_eq!(parts.len(), 3);
1043 assert_eq!(parts[1], "peer");
1044 assert_eq!(method_ids.first().unwrap().parse::<i32>().unwrap(), 2);
1045 assert_eq!(method_ids.len(), 4);
1046 }
1047
1048 #[tokio::test]
1049 async fn create_peer_did_works_ed25519() {
1050 let (e_did_key, v_did_key, keys) = _get_keys(Some(DIDPeerKeyType::Ed25519), true);
1051
1052 let services = vec![DIDPeerService {
1054 _type: "dm".into(),
1055 service_end_point: PeerServiceEndPoint::Long(PeerServiceEndPointLong::Map(
1056 OneOrMany::One(PeerServiceEndPointLongMap {
1057 uri: "https://localhost:7037".into(),
1058 accept: vec!["didcomm/v2".into()],
1059 routing_keys: vec![],
1060 }),
1061 )),
1062 id: None,
1063 }];
1064
1065 let (did, _) = DIDPeer::create_peer_did(&keys, Some(&services)).unwrap();
1066 let parts: Vec<&str> = did.split(":").collect();
1067 let mut method_ids: Vec<&str> = parts[2].split(".").collect();
1068 method_ids = method_ids[1..].to_vec();
1069 let keys_multibase = [v_did_key[8..].to_string(), e_did_key[8..].to_string()];
1070
1071 method_ids.iter().take(2).for_each(|id| {
1072 assert!(keys_multibase.contains(&id[1..].to_string()));
1073 });
1074
1075 assert_eq!(parts.len(), 3);
1076 assert_eq!(parts[1], "peer");
1077 }
1078
1079 #[tokio::test]
1080 async fn create_peer_did_works_p256() {
1081 let (e_did_key, v_did_key, keys) = _get_keys(Some(DIDPeerKeyType::P256), true);
1082 let services = vec![DIDPeerService {
1084 _type: "dm".into(),
1085 service_end_point: PeerServiceEndPoint::Long(PeerServiceEndPointLong::Map(
1086 OneOrMany::One(PeerServiceEndPointLongMap {
1087 uri: "https://localhost:7037".into(),
1088 accept: vec!["didcomm/v2".into()],
1089 routing_keys: vec![],
1090 }),
1091 )),
1092 id: None,
1093 }];
1094
1095 let (did, _) = DIDPeer::create_peer_did(&keys, Some(&services)).unwrap();
1096 let parts: Vec<&str> = did.split(":").collect();
1097 let mut method_ids: Vec<&str> = parts[2].split(".").collect();
1098 method_ids = method_ids[1..].to_vec();
1099 let keys_multibase = [v_did_key[8..].to_string(), e_did_key[8..].to_string()];
1100
1101 method_ids.iter().take(2).for_each(|id| {
1102 assert!(keys_multibase.contains(&id[1..].to_string()));
1103 });
1104 assert_eq!(parts.len(), 3);
1105 assert_eq!(parts[1], "peer");
1106 }
1107
1108 #[tokio::test]
1109 async fn create_peer_did_works_secp256k1() {
1110 let (e_did_key, v_did_key, keys) = _get_keys(Some(DIDPeerKeyType::Secp256k1), true);
1111 let services = vec![DIDPeerService {
1113 _type: "dm".into(),
1114 service_end_point: PeerServiceEndPoint::Long(PeerServiceEndPointLong::Map(
1115 OneOrMany::One(PeerServiceEndPointLongMap {
1116 uri: "https://localhost:7037".into(),
1117 accept: vec!["didcomm/v2".into()],
1118 routing_keys: vec![],
1119 }),
1120 )),
1121 id: None,
1122 }];
1123
1124 let (did, _) = DIDPeer::create_peer_did(&keys, Some(&services)).unwrap();
1125 let parts: Vec<&str> = did.split(":").collect();
1126 let mut method_ids: Vec<&str> = parts[2].split(".").collect();
1127 method_ids = method_ids[1..].to_vec();
1128 let keys_multibase = [v_did_key[8..].to_string(), e_did_key[8..].to_string()];
1129
1130 method_ids.iter().take(2).for_each(|id| {
1131 assert!(keys_multibase.contains(&id[1..].to_string()));
1132 });
1133 assert_eq!(parts.len(), 3);
1134 assert_eq!(parts[1], "peer");
1135 }
1136
1137 fn _get_keys(
1138 key_type: Option<DIDPeerKeyType>,
1139 with_pub_key: bool,
1140 ) -> (DIDBuf, DIDBuf, Vec<DIDPeerCreateKeys>) {
1141 let encryption_key = match key_type {
1142 Some(DIDPeerKeyType::Ed25519) => JWK::generate_ed25519().unwrap(),
1143 Some(DIDPeerKeyType::P256) => JWK::generate_p256(),
1144 Some(DIDPeerKeyType::Secp256k1) => JWK::generate_secp256k1(),
1145 None => JWK::generate_p384(),
1146 };
1147 let verification_key = match key_type {
1148 Some(DIDPeerKeyType::Ed25519) => JWK::generate_ed25519().unwrap(),
1149 Some(DIDPeerKeyType::P256) => JWK::generate_p256(),
1150 Some(DIDPeerKeyType::Secp256k1) => JWK::generate_secp256k1(),
1151 None => JWK::generate_p384(),
1152 };
1153 let e_did_key = ssi::dids::DIDKey::generate(&encryption_key).unwrap();
1155 let v_did_key = ssi::dids::DIDKey::generate(&verification_key).unwrap();
1156
1157 let keys = vec![
1159 DIDPeerCreateKeys {
1160 purpose: DIDPeerKeys::Verification,
1161 type_: key_type.clone(),
1162 public_key_multibase: if with_pub_key {
1163 Some(v_did_key[8..].to_string())
1164 } else {
1165 None
1166 },
1167 },
1168 DIDPeerCreateKeys {
1169 purpose: DIDPeerKeys::Encryption,
1170 type_: key_type.clone(),
1171 public_key_multibase: if with_pub_key {
1172 Some(e_did_key[8..].to_string())
1173 } else {
1174 None
1175 },
1176 },
1177 ];
1178
1179 (e_did_key, v_did_key, keys)
1180 }
1181}
1182
1183#[wasm_bindgen(getter_with_clone)]
1197#[derive(Clone, Serialize, Deserialize)]
1198pub struct DIDService {
1199 pub _type: Option<String>,
1200 pub uri: String,
1201 pub accept: Vec<String>,
1202 pub routing_keys: Vec<String>,
1203 pub id: Option<String>,
1204}
1205
1206#[wasm_bindgen]
1207impl DIDService {
1208 #[wasm_bindgen(constructor)]
1209 pub fn new(
1210 uri: String,
1211 accept: Vec<String>,
1212 routing_keys: Vec<String>,
1213 id: Option<String>,
1214 ) -> Self {
1215 DIDService {
1216 _type: None,
1217 uri,
1218 accept,
1219 routing_keys,
1220 id,
1221 }
1222 }
1223}
1224
1225impl From<DIDService> for DIDPeerService {
1226 fn from(service: DIDService) -> Self {
1227 DIDPeerService {
1228 _type: service._type.unwrap_or("DIDCommMessaging".into()),
1229 service_end_point: PeerServiceEndPoint::Short(PeerServiceEndPointShort::Map(
1230 OneOrMany::One(PeerServiceEndPointShortMap {
1231 uri: service.uri,
1232 a: service.accept,
1233 r: service.routing_keys,
1234 }),
1235 )),
1236 id: service.id,
1237 }
1238 }
1239}
1240
1241impl From<&DIDService> for DIDPeerService {
1242 fn from(service: &DIDService) -> Self {
1243 service.clone().into()
1244 }
1245}
1246
1247#[derive(Clone)]
1255#[wasm_bindgen(getter_with_clone)]
1256pub struct DidPeerCreate {
1257 pub keys: Vec<DIDPeerCreateKeys>,
1258 pub services: Option<Vec<DIDService>>,
1259}
1260
1261#[wasm_bindgen]
1262impl DidPeerCreate {
1263 #[wasm_bindgen(constructor)]
1264 pub fn new(keys: Vec<DIDPeerCreateKeys>, services: Option<Vec<DIDService>>) -> Self {
1265 DidPeerCreate { keys, services }
1266 }
1267}
1268
1269#[derive(Serialize, Deserialize)]
1270#[wasm_bindgen(getter_with_clone)]
1271pub struct DIDPeerResult {
1272 pub did: String,
1273 pub keys: Vec<DIDPeerCreatedKeys>,
1274}
1275
1276#[wasm_bindgen]
1277pub fn create_did_peer(input: &DidPeerCreate) -> Result<DIDPeerResult, DIDPeerError> {
1287 let mut new_services: Vec<DIDPeerService> = vec![];
1289 if let Some(services) = input.services.as_ref() {
1290 for service in services {
1291 new_services.push(service.into());
1292 }
1293 }
1294
1295 let response = DIDPeer::create_peer_did(&input.keys, Some(&new_services));
1297
1298 if let Ok((did, keys)) = response {
1299 Ok(DIDPeerResult { did, keys })
1300 } else {
1301 Err(response.unwrap_err())
1302 }
1303}
1304
1305#[wasm_bindgen]
1306pub async fn resolve_did_peer(did: &str) -> Result<String, DIDPeerError> {
1312 let peer = DIDPeer;
1313
1314 match peer
1315 .resolve(DID::new::<String>(&did.to_string()).unwrap())
1316 .await
1317 {
1318 Ok(output) => match serde_json::to_string_pretty(&output.document) {
1319 Ok(json) => Ok(json),
1320 Err(e) => Err(DIDPeerError::JsonParsingError(format!(
1321 "Couldn't convert DID Document to JSON. Reason: {}",
1322 e
1323 ))),
1324 },
1325 Err(e) => Err(DIDPeerError::KeyParsingError(format!(
1326 "Failed to resolve key ({}). Reason: {}",
1327 did, e
1328 ))),
1329 }
1330}