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