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) => {
96 PeerServiceEndPointShort::Map(PeerServiceEndPointShortMap {
97 uri: map.uri.to_string(),
98 a: map.accept.clone(),
99 r: map.routing_keys.clone(),
100 })
101 }
102 },
103 }
104 }
105
106 pub fn to_long(&self) -> PeerServiceEndPointLong {
107 match self {
108 PeerServiceEndPoint::Short(short) => PeerServiceEndPointLong::from(short.clone()),
109 PeerServiceEndPoint::Long(long) => long.clone(),
110 }
111 }
112}
113
114#[derive(Debug, Clone, Serialize, Deserialize)]
116#[serde(untagged)]
117pub enum PeerServiceEndPointShort {
118 URI(String),
119 Map(PeerServiceEndPointShortMap),
120}
121
122#[derive(Debug, Clone, Serialize, Deserialize)]
123pub struct PeerServiceEndPointShortMap {
124 pub uri: String,
125 pub a: Vec<String>,
126 pub r: Vec<String>,
127}
128
129#[derive(Debug, Clone, Serialize, Deserialize)]
131#[serde(untagged)]
132pub enum PeerServiceEndPointLong {
133 URI(String),
134 Map(PeerServiceEndPointLongMap),
135}
136
137#[derive(Debug, Clone, Serialize, Deserialize)]
138pub struct PeerServiceEndPointLongMap {
139 pub uri: String,
140 pub accept: Vec<String>,
141 pub routing_keys: Vec<String>,
142}
143
144impl From<PeerServiceEndPointShort> for PeerServiceEndPointLong {
145 fn from(service: PeerServiceEndPointShort) -> Self {
146 match service {
147 PeerServiceEndPointShort::URI(uri) => PeerServiceEndPointLong::URI(uri),
148 PeerServiceEndPointShort::Map(map) => {
149 PeerServiceEndPointLong::Map(PeerServiceEndPointLongMap {
150 uri: map.uri,
151 accept: map.a,
152 routing_keys: map.r,
153 })
154 }
155 }
156 }
157}
158#[derive(Debug, Serialize, Deserialize)]
160pub struct DIDPeerService {
161 #[serde(rename = "t")]
162 #[serde(alias = "t")]
163 pub _type: String,
164 #[serde(rename = "s")]
165 #[serde(alias = "s")]
166 pub service_end_point: PeerServiceEndPoint, #[serde(skip_serializing_if = "Option::is_none")]
170 pub id: Option<String>,
171}
172
173impl DIDPeerService {
174 fn convert(did: &str, service: DIDPeerService) -> Result<Service, DIDPeerError> {
175 let service_endpoint = match serde_json::to_value(PeerServiceEndPoint::to_long(
176 &service.service_end_point,
177 )) {
178 Ok(value) => {
179 if value.is_string() {
180 if let Some(value) = value.as_str() {
181 if let Ok(uri) = UriBuf::new(value.as_bytes().to_vec()) {
182 Some(OneOrMany::One(Endpoint::Uri(uri)))
183 } else {
184 return Err(DIDPeerError::SyntaxErrorServiceDefinition(format!(
185 "Couldn't convert ServiceEndPoint to a valid URI: {}",
186 value
187 )));
188 }
189 } else {
190 return Err(DIDPeerError::SyntaxErrorServiceDefinition(format!(
191 "Service URI appears to be a string, but can't parse as a string: {}",
192 value
193 )));
194 }
195 } else {
196 Some(OneOrMany::One(Endpoint::Map(value)))
197 }
198 }
199 Err(err) => {
200 return Err(DIDPeerError::SyntaxErrorServiceDefinition(format!(
201 "Couldn't convert ServiceEndPoint to a valid representation. Reason: {}",
202 err
203 )));
204 }
205 };
206
207 let id = if let Some(id) = service.id {
208 [did, &id].concat()
209 } else {
210 [did, "#service"].concat()
211 };
212
213 let id = match UriBuf::new(id.as_bytes().to_vec()) {
214 Ok(uri) => uri,
215 Err(e) => {
216 return Err(DIDPeerError::SyntaxErrorServiceDefinition(format!(
217 "Error parsing service id: {}. Reason: {:?}",
218 id, e
219 )));
220 }
221 };
222
223 Ok(Service {
224 id,
225 type_: OneOrMany::One("DIDCommMessaging".into()),
226 service_endpoint,
227 property_set: BTreeMap::new(),
228 })
229 }
230}
231
232#[derive(Clone)]
233#[wasm_bindgen]
234pub enum DIDPeerKeys {
238 Verification,
239 Encryption,
240}
241
242impl fmt::Display for DIDPeerKeys {
243 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
244 match *self {
245 DIDPeerKeys::Verification => write!(f, "verification"),
246 DIDPeerKeys::Encryption => write!(f, "encryption"),
247 }
248 }
249}
250
251#[derive(Clone)]
252#[wasm_bindgen]
253pub enum DIDPeerKeyType {
255 Ed25519,
256 Secp256k1,
257 P256,
258}
259
260impl fmt::Display for DIDPeerKeyType {
261 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
262 match *self {
263 DIDPeerKeyType::Ed25519 => write!(f, "ed25519"),
264 DIDPeerKeyType::Secp256k1 => write!(f, "secp256k1"),
265 DIDPeerKeyType::P256 => write!(f, "p256"),
266 }
267 }
268}
269
270#[derive(Clone)]
271#[wasm_bindgen(getter_with_clone)]
272pub struct DIDPeerCreateKeys {
277 pub purpose: DIDPeerKeys,
278 pub type_: Option<DIDPeerKeyType>,
279 pub public_key_multibase: Option<String>,
280}
281
282#[wasm_bindgen]
283impl DIDPeerCreateKeys {
284 #[wasm_bindgen(constructor)]
285 pub fn new(
286 purpose: DIDPeerKeys,
287 type_: Option<DIDPeerKeyType>,
288 public_key_multibase: Option<String>,
289 ) -> Self {
290 DIDPeerCreateKeys {
291 purpose,
292 type_,
293 public_key_multibase,
294 }
295 }
296}
297
298#[derive(Clone, Debug, Serialize, Deserialize)]
306#[wasm_bindgen(getter_with_clone)]
307pub struct DIDPeerCreatedKeys {
308 pub key_multibase: String,
309 pub curve: String,
310 pub d: String,
311 pub x: String,
312 pub y: Option<String>,
313}
314
315fn process_key(did: &str, id: &str, public_key: &str) -> Result<DIDVerificationMethod, Error> {
317 let mut properties = BTreeMap::new();
318
319 properties.insert(
320 "publicKeyMultibase".to_string(),
321 Value::String(public_key.to_string()),
322 );
323
324 Ok(DIDVerificationMethod {
325 id: DIDURLBuf::from_string(["did:peer:", did, id].concat()).unwrap(),
326 type_: "Multikey".to_string(),
327 controller: DIDBuf::from_string(["did:peer:", did].concat()).unwrap(),
328 properties,
329 })
330}
331
332impl DIDMethodResolver for DIDPeer {
333 async fn resolve_method_representation<'a>(
334 &'a self,
335 method_specific_id: &'a str,
336 options: Options,
337 ) -> Result<Output<Vec<u8>>, Error> {
338 let did = ["did:peer:", method_specific_id].concat();
339
340 if let Some(id) = method_specific_id.strip_prefix('0') {
342 return DIDKey.resolve_method_representation(id, options).await;
343 }
344
345 if !method_specific_id.starts_with('2') {
347 return Err(Error::MethodNotSupported(
348 "did:peer version 2 supported only".to_string(),
349 ));
350 }
351
352 let mut context = BTreeMap::new();
353 context.insert("@base".to_string(), serde_json::json!(method_specific_id));
354
355 let mut verification_methods: Vec<DIDVerificationMethod> = Vec::new();
356 let mut verification_relationships: VerificationRelationships =
357 VerificationRelationships::default();
358
359 let mut services: Vec<Service> = Vec::new();
363
364 let parts: Vec<&str> = method_specific_id[2..].split('.').collect();
367 let mut key_count: u32 = 1;
368 let mut service_idx: u32 = 0;
369
370 for part in parts {
371 let ch = part.chars().next();
372 match ch {
373 Some(e) => {
374 match e {
375 'A' => {
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.assertion_method.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 'D' => {
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.capability_delegation.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 key_count += 1;
420 }
421 'E' => {
422 verification_methods.push(process_key(
424 method_specific_id,
425 &["#key-", &key_count.to_string()].concat(),
426 &part[1..],
427 )?);
428 verification_relationships.key_agreement.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 'I' => {
444 verification_methods.push(process_key(
446 method_specific_id,
447 &["#key-", &key_count.to_string()].concat(),
448 &part[1..],
449 )?);
450
451 verification_relationships.capability_invocation.push(
452 verification_method::ValueOrReference::Reference(
453 DIDURLReferenceBuf::Relative(
454 RelativeDIDURLBuf::new(
455 ["#key-", &key_count.to_string()]
456 .concat()
457 .as_bytes()
458 .to_vec(),
459 )
460 .unwrap(),
461 ),
462 ),
463 );
464 key_count += 1;
465 }
466 'V' => {
467 verification_methods.push(process_key(
469 method_specific_id,
470 &["#key-", &key_count.to_string()].concat(),
471 &part[1..],
472 )?);
473
474 verification_relationships.authentication.push(
475 verification_method::ValueOrReference::Reference(
476 DIDURLReferenceBuf::Relative(
477 RelativeDIDURLBuf::new(
478 ["#key-", &key_count.to_string()]
479 .concat()
480 .as_bytes()
481 .to_vec(),
482 )
483 .unwrap(),
484 ),
485 ),
486 );
487 verification_relationships.assertion_method.push(
488 verification_method::ValueOrReference::Reference(
489 DIDURLReferenceBuf::Relative(
490 RelativeDIDURLBuf::new(
491 ["#key-", &key_count.to_string()]
492 .concat()
493 .as_bytes()
494 .to_vec(),
495 )
496 .unwrap(),
497 ),
498 ),
499 );
500
501 key_count += 1;
502 }
503 'S' => {
504 let service = convert_service(&did, part, service_idx)
506 .map_err(|e| Error::Internal(e.to_string()))?;
507 services.push(service);
508 service_idx += 1;
509 }
510 other => {
511 return Err(Error::RepresentationNotSupported(format!(
512 "An invalid Purpose Code ({}) was found in the DID",
513 other
514 )));
515 }
516 }
517 }
518 None => {
519 }
522 }
523 }
524
525 let vm_type = match options.parameters.public_key_format {
526 Some(name) => VerificationMethodType::from_name(&name).ok_or_else(|| {
527 Error::Internal(format!(
528 "verification method type `{name}` unsupported by did:peer"
529 ))
530 })?,
531 None => VerificationMethodType::Multikey,
532 };
533
534 let mut doc =
535 Document::new(DIDBuf::from_string(["did:peer:", method_specific_id].concat()).unwrap());
536 doc.verification_method = verification_methods;
537 doc.verification_relationships = verification_relationships;
538 doc.service = services;
539
540 let mut json_ld_context = Vec::new();
541 if let Some(context) = vm_type.context_entry() {
542 json_ld_context.push(context)
543 }
544
545 let content_type = options.accept.unwrap_or(MediaType::JsonLd);
546
547 let represented = doc.into_representation(representation::Options::from_media_type(
548 content_type,
549 move || representation::json_ld::Options {
550 context: representation::json_ld::Context::array(
551 representation::json_ld::DIDContext::V1,
552 json_ld_context,
553 ),
554 },
555 ));
556
557 Ok(resolution::Output::new(
558 represented.to_bytes(),
559 document::Metadata::default(),
560 resolution::Metadata::from_content_type(Some(content_type.to_string())),
561 ))
562 }
563}
564
565impl DIDMethod for DIDPeer {
566 const DID_METHOD_NAME: &'static str = "peer";
567}
568
569impl DIDPeer {
570 pub fn create_peer_did(
617 keys: &Vec<DIDPeerCreateKeys>,
618 services: Option<&Vec<DIDPeerService>>,
619 ) -> Result<(String, Vec<DIDPeerCreatedKeys>), DIDPeerError> {
620 let mut result = String::from("did:peer:2");
621
622 let mut private_keys: Vec<DIDPeerCreatedKeys> = vec![];
623 for key in keys {
624 let public_key = if let Some(key) = key.public_key_multibase.as_ref() {
626 key.clone()
627 } else {
628 let jwk = match &key.type_ {
629 Some(type_) => match type_ {
630 DIDPeerKeyType::Ed25519 => match JWK::generate_ed25519() {
631 Ok(k) => k,
632 Err(e) => {
633 return Err(DIDPeerError::InternalError(format!(
634 "Failed to generate ed25519 key. Reason: {}",
635 e
636 )));
637 }
638 },
639 DIDPeerKeyType::Secp256k1 => JWK::generate_secp256k1(),
640 DIDPeerKeyType::P256 => JWK::generate_p256(),
641 },
642 None => return Err(DIDPeerError::UnsupportedKeyType),
643 };
644 let did = if let Ok(output) = ssi::dids::DIDKey::generate(&jwk) {
645 output.to_string()
646 } else {
647 return Err(DIDPeerError::InternalError(
648 "Couldn't create did:key".to_string(),
649 ));
650 };
651
652 match jwk.params {
653 Params::OKP(map) => {
654 let d = if let Some(d) = &map.private_key {
655 d
656 } else {
657 return Err(DIDPeerError::KeyParsingError(
658 "Missing private key".to_string(),
659 ));
660 };
661 private_keys.push(DIDPeerCreatedKeys {
662 key_multibase: did[8..].to_string(),
663 curve: map.curve.clone(),
664 d: String::from(d),
665 x: String::from(map.public_key.clone()),
666 y: None,
667 })
668 }
669 Params::EC(map) => {
670 let curve = if let Some(curve) = &map.curve {
671 curve
672 } else {
673 return Err(DIDPeerError::KeyParsingError("Missing curve".to_string()));
674 };
675 let d = if let Some(d) = &map.ecc_private_key {
676 d
677 } else {
678 return Err(DIDPeerError::KeyParsingError(
679 "Missing private key".to_string(),
680 ));
681 };
682
683 let x = if let Some(x) = &map.x_coordinate {
684 x
685 } else {
686 return Err(DIDPeerError::KeyParsingError(
687 "Missing public key (x)".to_string(),
688 ));
689 };
690 let y = if let Some(y) = &map.y_coordinate {
691 y
692 } else {
693 return Err(DIDPeerError::KeyParsingError(
694 "Missing public key (y)".to_string(),
695 ));
696 };
697
698 private_keys.push(DIDPeerCreatedKeys {
699 key_multibase: did[8..].to_string(),
700 curve: curve.into(),
701 d: String::from(d),
702 x: String::from(x),
703 y: Some(String::from(y)),
704 })
705 }
706 _ => return Err(DIDPeerError::UnsupportedKeyType),
707 }
708
709 did[8..].to_string()
710 };
711
712 match key.purpose {
714 DIDPeerKeys::Verification => {
715 result.push_str(&format!(".V{}", public_key));
716 }
717 DIDPeerKeys::Encryption => {
718 result.push_str(&format!(".E{}", public_key));
719 }
720 }
721 }
722
723 if let Some(services) = services {
724 for service in services {
725 let service = serde_json::to_string(&service).map_err(|e| {
726 DIDPeerError::SyntaxErrorServiceDefinition(format!(
727 "Error parsing service: {}",
728 e
729 ))
730 })?;
731 result.push_str(&format!(".S{}", BASE64_URL_SAFE_NO_PAD.encode(service)));
732 }
733 }
734
735 Ok((result, private_keys))
736 }
737
738 pub async fn expand_keys(doc: &Document) -> Result<Document, DIDPeerError> {
742 let mut new_doc = doc.clone();
743
744 let mut new_vms: Vec<DIDVerificationMethod> = vec![];
745 for v_method in &doc.verification_method {
746 new_vms.push(Self::_convert_vm(v_method).await?);
747 }
748
749 new_doc.verification_method = new_vms;
750 Ok(new_doc)
751 }
752
753 async fn _convert_vm(
755 method: &DIDVerificationMethod,
756 ) -> Result<DIDVerificationMethod, DIDPeerError> {
757 let current_controller = method.controller.clone();
758 let current_id = method.id.clone();
759 let did_key = if let Some(key) = method.properties.get("publicKeyBase58") {
760 ["did:key:", key.as_str().unwrap()].concat()
761 } else if let Some(key) = method.properties.get("publicKeyMultibase") {
762 ["did:key:", key.as_str().unwrap()].concat()
763 } else {
764 return Err(DIDPeerError::KeyParsingError(
765 "Failed to convert verification_method. Reason: Missing publicKeyBase58"
766 .to_string(),
767 ));
768 };
769
770 let key_method = DIDKey;
771
772 let output = match key_method
773 .dereference_with(
774 DIDURL::new::<String>(&did_key.clone()).unwrap(),
775 Options {
776 accept: None,
777 parameters: Parameters {
778 public_key_format: Some("JsonWebKey2020".to_string()),
779 ..Default::default()
780 },
781 },
782 )
783 .await
784 {
785 Ok(output) => output.content,
786 Err(e) => {
787 return Err(DIDPeerError::KeyParsingError(format!(
788 "Failed to resolve key ({}). Reason: {}",
789 did_key, e
790 )));
791 }
792 };
793
794 if let Content::Resource(Resource::Document(doc)) = output {
795 if let Some(vm) = doc.into_any_verification_method() {
796 let mut new_vm = vm.clone();
797 new_vm.controller = current_controller;
798 new_vm.id = current_id;
799 return Ok(new_vm);
800 }
801 }
802
803 Err(DIDPeerError::KeyParsingError(
804 "Failed to convert verification_method. Reason: Missing verification_method"
805 .to_string(),
806 ))
807 }
808}
809
810#[cfg(test)]
811mod test {
812 use crate::{
813 DIDPeer, DIDPeerCreateKeys, DIDPeerKeyType, DIDPeerKeys, DIDPeerService,
814 PeerServiceEndPoint, PeerServiceEndPointLong, PeerServiceEndPointLongMap,
815 };
816
817 use ssi::{
818 JWK,
819 dids::{DID, DIDBuf, DIDResolver, document::DIDVerificationMethod},
820 };
821
822 const DID_PEER: &str = "did:peer:2.Vz6MkiToqovww7vYtxm1xNM15u9JzqzUFZ1k7s7MazYJUyAxv.EzQ3shQLqRUza6AMJFbPuMdvFRFWm1wKviQRnQSC1fScovJN4s.SeyJ0IjoiRElEQ29tbU1lc3NhZ2luZyIsInMiOnsidXJpIjoiaHR0cHM6Ly8xMjcuMC4wLjE6NzAzNyIsImEiOlsiZGlkY29tbS92MiJdLCJyIjpbXX19";
823
824 #[should_panic(
825 expected = "Failed to convert verification_method. Reason: Missing publicKeyBase58"
826 )]
827 #[tokio::test]
828 async fn expand_keys_throws_key_parsing_missing_pbk58_error() {
829 let peer = DIDPeer;
830 let output = peer
831 .resolve(DID::new::<String>(&DID_PEER.to_string()).unwrap())
832 .await
833 .unwrap();
834
835 let mut document = output.document.document().clone();
836 let mut new_vms: Vec<DIDVerificationMethod> = vec![];
837 for mut vm in document.verification_method {
838 vm.properties.remove("publicKeyMultibase");
839 new_vms.push(vm);
840 }
841
842 document.verification_method = new_vms;
843 let _expanded_doc = DIDPeer::expand_keys(&document).await.unwrap();
844 }
845
846 #[tokio::test]
847 async fn expand_keys_works() {
848 let peer = DIDPeer;
849 let document = peer
850 .resolve(DID::new::<String>(&DID_PEER.to_string()).unwrap())
851 .await
852 .expect("Couldn't resolve DID");
853
854 let vm_before_expansion = document.clone().document.verification_method.clone();
855 let expanded_doc = DIDPeer::expand_keys(&document.document).await.unwrap();
856 let vms_after_expansion = expanded_doc.verification_method;
857
858 for vm in vms_after_expansion.clone() {
859 assert!(vm.id.starts_with("did:peer"));
860 }
861 assert_eq!(vm_before_expansion.len(), vms_after_expansion.len())
862 }
863
864 #[tokio::test]
865 async fn create_peer_did_without_keys_and_services() {
866 let keys: Vec<DIDPeerCreateKeys> = vec![];
867 let services: Vec<DIDPeerService> = vec![];
868
869 let (did, _) = DIDPeer::create_peer_did(&keys, Some(&services)).unwrap();
870 let parts: Vec<&str> = did.split(":").collect();
871
872 assert_eq!(parts.len(), 3);
873 assert_eq!(parts[1], "peer");
874 assert!(parts[2].len() == 1);
875 }
876
877 #[tokio::test]
878 async fn create_peer_did_without_keys() {
879 let keys: Vec<DIDPeerCreateKeys> = vec![];
880 let services = vec![DIDPeerService {
881 _type: "dm".into(),
882 service_end_point: PeerServiceEndPoint::Long(PeerServiceEndPointLong::Map(
883 PeerServiceEndPointLongMap {
884 uri: "https://localhost:7037".into(),
885 accept: vec!["didcomm/v2".into()],
886 routing_keys: vec![],
887 },
888 )),
889 id: None,
890 }];
891
892 let (did, _) = DIDPeer::create_peer_did(&keys, Some(&services)).unwrap();
893 let parts: Vec<&str> = did.split(":").collect();
894 let method_ids: Vec<&str> = parts[2].split(".").collect();
895
896 assert_eq!(parts.len(), 3);
897 assert_eq!(parts[1], "peer");
898 assert!(method_ids.len() > 1);
899 assert!(method_ids[1].len() > 1);
900 }
901
902 #[tokio::test]
903 async fn create_peer_did_without_services() {
904 let (e_did_key, v_did_key, keys) = _get_keys(Some(DIDPeerKeyType::Ed25519), true);
905 let services: Vec<DIDPeerService> = vec![];
906
907 let (did, _) = DIDPeer::create_peer_did(&keys, Some(&services)).unwrap();
908 let parts: Vec<&str> = did.split(":").collect();
909 let mut method_ids: Vec<&str> = parts[2].split(".").collect();
910 method_ids = method_ids[1..].to_vec();
911 let keys_multibase = [v_did_key[8..].to_string(), e_did_key[8..].to_string()];
912
913 method_ids.iter().take(2).for_each(|id| {
914 assert!(keys_multibase.contains(&id[1..].to_string()));
915 });
916 assert_eq!(parts.len(), 3);
917 assert_eq!(parts[1], "peer");
918 }
919
920 #[should_panic(expected = "UnsupportedKeyType")]
921 #[tokio::test]
922 async fn create_peer_did_should_throw_unsupported_key_error_p384() {
923 let (_, _, keys) = _get_keys(None, false);
924 let services = vec![DIDPeerService {
926 _type: "dm".into(),
927 service_end_point: PeerServiceEndPoint::Long(PeerServiceEndPointLong::Map(
928 PeerServiceEndPointLongMap {
929 uri: "https://localhost:7037".into(),
930 accept: vec!["didcomm/v2".into()],
931 routing_keys: vec![],
932 },
933 )),
934 id: None,
935 }];
936
937 DIDPeer::create_peer_did(&keys, Some(&services)).unwrap();
938 }
939
940 #[tokio::test]
941 async fn create_peer_did_works_ed25519_without_passing_pub_key() {
942 let (_, _, keys) = _get_keys(Some(DIDPeerKeyType::Ed25519), false);
943
944 let services = vec![DIDPeerService {
946 _type: "dm".into(),
947 service_end_point: PeerServiceEndPoint::Long(PeerServiceEndPointLong::Map(
948 PeerServiceEndPointLongMap {
949 uri: "https://localhost:7037".into(),
950 accept: vec!["didcomm/v2".into()],
951 routing_keys: vec![],
952 },
953 )),
954 id: None,
955 }];
956
957 let (did, keys) = DIDPeer::create_peer_did(&keys, Some(&services)).unwrap();
958 let parts: Vec<&str> = did.split(":").collect();
959 let method_ids: Vec<&str> = parts[2].split(".").collect();
960
961 assert_eq!(keys.len(), 2);
962 assert_eq!(parts.len(), 3);
963 assert_eq!(parts[1], "peer");
964 assert_eq!(method_ids.first().unwrap().parse::<i32>().unwrap(), 2);
965 assert_eq!(method_ids.len(), 4);
966 }
967
968 #[tokio::test]
969 async fn create_peer_did_works_p256_without_passing_pub_key() {
970 let (_, _, keys) = _get_keys(Some(DIDPeerKeyType::P256), false);
971
972 let services = vec![DIDPeerService {
974 _type: "dm".into(),
975 service_end_point: PeerServiceEndPoint::Long(PeerServiceEndPointLong::Map(
976 PeerServiceEndPointLongMap {
977 uri: "https://localhost:7037".into(),
978 accept: vec!["didcomm/v2".into()],
979 routing_keys: vec![],
980 },
981 )),
982 id: None,
983 }];
984
985 let (did, keys) = DIDPeer::create_peer_did(&keys, Some(&services)).unwrap();
986 let parts: Vec<&str> = did.split(":").collect();
987 let method_ids: Vec<&str> = parts[2].split(".").collect();
988
989 assert_eq!(keys.len(), 2);
990 assert_eq!(parts.len(), 3);
991 assert_eq!(parts[1], "peer");
992 assert_eq!(method_ids.first().unwrap().parse::<i32>().unwrap(), 2);
993 assert_eq!(method_ids.len(), 4);
994 }
995
996 #[tokio::test]
997 async fn create_peer_did_works_secp256k1_without_passing_pub_key() {
998 let (_, _, keys) = _get_keys(Some(DIDPeerKeyType::Secp256k1), false);
999
1000 let services = vec![DIDPeerService {
1002 _type: "dm".into(),
1003 service_end_point: PeerServiceEndPoint::Long(PeerServiceEndPointLong::Map(
1004 PeerServiceEndPointLongMap {
1005 uri: "https://localhost:7037".into(),
1006 accept: vec!["didcomm/v2".into()],
1007 routing_keys: vec![],
1008 },
1009 )),
1010 id: None,
1011 }];
1012
1013 let (did, keys) = DIDPeer::create_peer_did(&keys, Some(&services)).unwrap();
1014
1015 let parts: Vec<&str> = did.split(":").collect();
1016 let method_ids: Vec<&str> = parts[2].split(".").collect();
1017
1018 assert_eq!(keys.len(), 2);
1019 assert_eq!(parts.len(), 3);
1020 assert_eq!(parts[1], "peer");
1021 assert_eq!(method_ids.first().unwrap().parse::<i32>().unwrap(), 2);
1022 assert_eq!(method_ids.len(), 4);
1023 }
1024
1025 #[tokio::test]
1026 async fn create_peer_did_works_ed25519() {
1027 let (e_did_key, v_did_key, keys) = _get_keys(Some(DIDPeerKeyType::Ed25519), true);
1028
1029 let services = vec![DIDPeerService {
1031 _type: "dm".into(),
1032 service_end_point: PeerServiceEndPoint::Long(PeerServiceEndPointLong::Map(
1033 PeerServiceEndPointLongMap {
1034 uri: "https://localhost:7037".into(),
1035 accept: vec!["didcomm/v2".into()],
1036 routing_keys: vec![],
1037 },
1038 )),
1039 id: None,
1040 }];
1041
1042 let (did, _) = DIDPeer::create_peer_did(&keys, Some(&services)).unwrap();
1043 let parts: Vec<&str> = did.split(":").collect();
1044 let mut method_ids: Vec<&str> = parts[2].split(".").collect();
1045 method_ids = method_ids[1..].to_vec();
1046 let keys_multibase = [v_did_key[8..].to_string(), e_did_key[8..].to_string()];
1047
1048 method_ids.iter().take(2).for_each(|id| {
1049 assert!(keys_multibase.contains(&id[1..].to_string()));
1050 });
1051
1052 assert_eq!(parts.len(), 3);
1053 assert_eq!(parts[1], "peer");
1054 }
1055
1056 #[tokio::test]
1057 async fn create_peer_did_works_p256() {
1058 let (e_did_key, v_did_key, keys) = _get_keys(Some(DIDPeerKeyType::P256), true);
1059 let services = vec![DIDPeerService {
1061 _type: "dm".into(),
1062 service_end_point: PeerServiceEndPoint::Long(PeerServiceEndPointLong::Map(
1063 PeerServiceEndPointLongMap {
1064 uri: "https://localhost:7037".into(),
1065 accept: vec!["didcomm/v2".into()],
1066 routing_keys: vec![],
1067 },
1068 )),
1069 id: None,
1070 }];
1071
1072 let (did, _) = DIDPeer::create_peer_did(&keys, Some(&services)).unwrap();
1073 let parts: Vec<&str> = did.split(":").collect();
1074 let mut method_ids: Vec<&str> = parts[2].split(".").collect();
1075 method_ids = method_ids[1..].to_vec();
1076 let keys_multibase = [v_did_key[8..].to_string(), e_did_key[8..].to_string()];
1077
1078 method_ids.iter().take(2).for_each(|id| {
1079 assert!(keys_multibase.contains(&id[1..].to_string()));
1080 });
1081 assert_eq!(parts.len(), 3);
1082 assert_eq!(parts[1], "peer");
1083 }
1084
1085 #[tokio::test]
1086 async fn create_peer_did_works_secp256k1() {
1087 let (e_did_key, v_did_key, keys) = _get_keys(Some(DIDPeerKeyType::Secp256k1), true);
1088 let services = vec![DIDPeerService {
1090 _type: "dm".into(),
1091 service_end_point: PeerServiceEndPoint::Long(PeerServiceEndPointLong::Map(
1092 PeerServiceEndPointLongMap {
1093 uri: "https://localhost:7037".into(),
1094 accept: vec!["didcomm/v2".into()],
1095 routing_keys: vec![],
1096 },
1097 )),
1098 id: None,
1099 }];
1100
1101 let (did, _) = DIDPeer::create_peer_did(&keys, Some(&services)).unwrap();
1102 let parts: Vec<&str> = did.split(":").collect();
1103 let mut method_ids: Vec<&str> = parts[2].split(".").collect();
1104 method_ids = method_ids[1..].to_vec();
1105 let keys_multibase = [v_did_key[8..].to_string(), e_did_key[8..].to_string()];
1106
1107 method_ids.iter().take(2).for_each(|id| {
1108 assert!(keys_multibase.contains(&id[1..].to_string()));
1109 });
1110 assert_eq!(parts.len(), 3);
1111 assert_eq!(parts[1], "peer");
1112 }
1113
1114 fn _get_keys(
1115 key_type: Option<DIDPeerKeyType>,
1116 with_pub_key: bool,
1117 ) -> (DIDBuf, DIDBuf, Vec<DIDPeerCreateKeys>) {
1118 let encryption_key = match key_type {
1119 Some(DIDPeerKeyType::Ed25519) => JWK::generate_ed25519().unwrap(),
1120 Some(DIDPeerKeyType::P256) => JWK::generate_p256(),
1121 Some(DIDPeerKeyType::Secp256k1) => JWK::generate_secp256k1(),
1122 None => JWK::generate_p384(),
1123 };
1124 let verification_key = match key_type {
1125 Some(DIDPeerKeyType::Ed25519) => JWK::generate_ed25519().unwrap(),
1126 Some(DIDPeerKeyType::P256) => JWK::generate_p256(),
1127 Some(DIDPeerKeyType::Secp256k1) => JWK::generate_secp256k1(),
1128 None => JWK::generate_p384(),
1129 };
1130 let e_did_key = ssi::dids::DIDKey::generate(&encryption_key).unwrap();
1132 let v_did_key = ssi::dids::DIDKey::generate(&verification_key).unwrap();
1133
1134 let keys = vec![
1136 DIDPeerCreateKeys {
1137 purpose: DIDPeerKeys::Verification,
1138 type_: key_type.clone(),
1139 public_key_multibase: if with_pub_key {
1140 Some(v_did_key[8..].to_string())
1141 } else {
1142 None
1143 },
1144 },
1145 DIDPeerCreateKeys {
1146 purpose: DIDPeerKeys::Encryption,
1147 type_: key_type.clone(),
1148 public_key_multibase: if with_pub_key {
1149 Some(e_did_key[8..].to_string())
1150 } else {
1151 None
1152 },
1153 },
1154 ];
1155
1156 (e_did_key, v_did_key, keys)
1157 }
1158}
1159
1160#[wasm_bindgen(getter_with_clone)]
1174#[derive(Clone, Serialize, Deserialize)]
1175pub struct DIDService {
1176 pub _type: Option<String>,
1177 pub uri: String,
1178 pub accept: Vec<String>,
1179 pub routing_keys: Vec<String>,
1180 pub id: Option<String>,
1181}
1182
1183#[wasm_bindgen]
1184impl DIDService {
1185 #[wasm_bindgen(constructor)]
1186 pub fn new(
1187 uri: String,
1188 accept: Vec<String>,
1189 routing_keys: Vec<String>,
1190 id: Option<String>,
1191 ) -> Self {
1192 DIDService {
1193 _type: None,
1194 uri,
1195 accept,
1196 routing_keys,
1197 id,
1198 }
1199 }
1200}
1201
1202impl From<DIDService> for DIDPeerService {
1203 fn from(service: DIDService) -> Self {
1204 DIDPeerService {
1205 _type: service._type.unwrap_or("DIDCommMessaging".into()),
1206 service_end_point: PeerServiceEndPoint::Short(PeerServiceEndPointShort::Map(
1207 PeerServiceEndPointShortMap {
1208 uri: service.uri,
1209 a: service.accept,
1210 r: service.routing_keys,
1211 },
1212 )),
1213 id: service.id,
1214 }
1215 }
1216}
1217
1218impl From<&DIDService> for DIDPeerService {
1219 fn from(service: &DIDService) -> Self {
1220 service.clone().into()
1221 }
1222}
1223
1224#[derive(Clone)]
1232#[wasm_bindgen(getter_with_clone)]
1233pub struct DidPeerCreate {
1234 pub keys: Vec<DIDPeerCreateKeys>,
1235 pub services: Option<Vec<DIDService>>,
1236}
1237
1238#[wasm_bindgen]
1239impl DidPeerCreate {
1240 #[wasm_bindgen(constructor)]
1241 pub fn new(keys: Vec<DIDPeerCreateKeys>, services: Option<Vec<DIDService>>) -> Self {
1242 DidPeerCreate { keys, services }
1243 }
1244}
1245
1246#[derive(Serialize, Deserialize)]
1247#[wasm_bindgen(getter_with_clone)]
1248pub struct DIDPeerResult {
1249 pub did: String,
1250 pub keys: Vec<DIDPeerCreatedKeys>,
1251}
1252
1253#[wasm_bindgen]
1254pub fn create_did_peer(input: &DidPeerCreate) -> Result<DIDPeerResult, DIDPeerError> {
1264 let mut new_services: Vec<DIDPeerService> = vec![];
1266 if let Some(services) = input.services.as_ref() {
1267 for service in services {
1268 new_services.push(service.into());
1269 }
1270 }
1271
1272 let response = DIDPeer::create_peer_did(&input.keys, Some(&new_services));
1274
1275 if let Ok((did, keys)) = response {
1276 Ok(DIDPeerResult { did, keys })
1277 } else {
1278 Err(response.unwrap_err())
1279 }
1280}
1281
1282#[wasm_bindgen]
1283pub async fn resolve_did_peer(did: &str) -> Result<String, DIDPeerError> {
1289 let peer = DIDPeer;
1290
1291 match peer
1292 .resolve(DID::new::<String>(&did.to_string()).unwrap())
1293 .await
1294 {
1295 Ok(output) => match serde_json::to_string_pretty(&output.document) {
1296 Ok(json) => Ok(json),
1297 Err(e) => Err(DIDPeerError::JsonParsingError(format!(
1298 "Couldn't convert DID Document to JSON. Reason: {}",
1299 e
1300 ))),
1301 },
1302 Err(e) => Err(DIDPeerError::KeyParsingError(format!(
1303 "Failed to resolve key ({}). Reason: {}",
1304 did, e
1305 ))),
1306 }
1307}