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