did_peer/
lib.rs

1//! # DID Peer Method
2//!
3//! The `did-peer` method is a DID method that is designed to be used for peer-to-peer communication.
4//! It is based on did:key which can be used for Verification (V) and Encryption (E) purposes.
5//! It also supports services (S) which can be used to define endpoints for communication.
6//!
7//! Example:
8//! ```ignore
9//! let peer = DIDPeer;
10//! match peer.resolve(DID::new::<str>("did:peer:2.Vabc...").unwrap()).await {
11//!    Ok(res) => {
12//!        println!("DID DOcument: {:#?}", res.document.into_document()),
13//!    },
14//!    Err(e) => {
15//!      println!("Error: {:?}", e);
16//!   }
17//! }
18//! ```
19//!
20use 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
70// Converts DIDPeerError to JsValue which is required for propagating errors to WASM
71impl From<DIDPeerError> for JsValue {
72    fn from(err: DIDPeerError) -> JsValue {
73        JsValue::from(err.to_string())
74    }
75}
76
77pub struct DIDPeer;
78
79/// DID Peer Service supports two formats:
80/// 1. Short format - uses `a` and `r` for accept and routing keys
81/// 2. Long format - uses `accept` and `routing_keys` for accept and routing keys
82#[derive(Debug, Serialize, Deserialize)]
83#[serde(untagged)]
84pub enum PeerServiceEndPoint {
85    Short(PeerServiceEndPointShort),
86    Long(PeerServiceEndPointLong),
87}
88
89impl PeerServiceEndPoint {
90    pub fn to_short(&self) -> PeerServiceEndPointShort {
91        match self {
92            PeerServiceEndPoint::Short(short) => short.clone(),
93            PeerServiceEndPoint::Long(long) => match long {
94                PeerServiceEndPointLong::URI(uri) => PeerServiceEndPointShort::URI(uri.to_string()),
95                PeerServiceEndPointLong::Map(map) => match map {
96                    OneOrMany::One(single) => {
97                        PeerServiceEndPointShort::Map(OneOrMany::One(PeerServiceEndPointShortMap {
98                            uri: single.uri.to_string(),
99                            a: single.accept.clone(),
100                            r: single.routing_keys.clone(),
101                        }))
102                    }
103                    OneOrMany::Many(many) => PeerServiceEndPointShort::Map(OneOrMany::Many(
104                        many.iter()
105                            .map(|m| PeerServiceEndPointShortMap {
106                                uri: m.uri.to_string(),
107                                a: m.accept.clone(),
108                                r: m.routing_keys.clone(),
109                            })
110                            .collect(),
111                    )),
112                },
113            },
114        }
115    }
116
117    pub fn to_long(&self) -> PeerServiceEndPointLong {
118        match self {
119            PeerServiceEndPoint::Short(short) => PeerServiceEndPointLong::from(short.clone()),
120            PeerServiceEndPoint::Long(long) => long.clone(),
121        }
122    }
123}
124
125/// DID serviceEndPoint structure in short format
126#[derive(Debug, Clone, Serialize, Deserialize)]
127#[serde(untagged)]
128pub enum PeerServiceEndPointShort {
129    URI(String),
130    Map(OneOrMany<PeerServiceEndPointShortMap>),
131}
132
133#[derive(Debug, Clone, Serialize, Deserialize)]
134pub struct PeerServiceEndPointShortMap {
135    pub uri: String,
136    pub a: Vec<String>,
137    pub r: Vec<String>,
138}
139
140/// DID serviceEndPoint structure in long format
141#[derive(Debug, Clone, Serialize, Deserialize)]
142#[serde(untagged)]
143pub enum PeerServiceEndPointLong {
144    URI(String),
145    Map(OneOrMany<PeerServiceEndPointLongMap>),
146}
147
148#[derive(Debug, Clone, Serialize, Deserialize)]
149pub struct PeerServiceEndPointLongMap {
150    pub uri: String,
151    pub accept: Vec<String>,
152    pub routing_keys: Vec<String>,
153}
154
155impl From<PeerServiceEndPointShort> for PeerServiceEndPointLong {
156    fn from(service: PeerServiceEndPointShort) -> Self {
157        match service {
158            PeerServiceEndPointShort::URI(uri) => PeerServiceEndPointLong::URI(uri),
159            PeerServiceEndPointShort::Map(map) => match map {
160                OneOrMany::One(single) => {
161                    PeerServiceEndPointLong::Map(OneOrMany::One(PeerServiceEndPointLongMap {
162                        uri: single.uri,
163                        accept: single.a,
164                        routing_keys: single.r,
165                    }))
166                }
167                OneOrMany::Many(many) => PeerServiceEndPointLong::Map(OneOrMany::Many(
168                    many.iter()
169                        .map(|m| PeerServiceEndPointLongMap {
170                            uri: m.uri.clone(),
171                            accept: m.a.clone(),
172                            routing_keys: m.r.clone(),
173                        })
174                        .collect(),
175                )),
176            },
177        }
178    }
179}
180/// DID Service structure in abbreviated format
181#[derive(Debug, Serialize, Deserialize)]
182pub struct DIDPeerService {
183    #[serde(rename = "t")]
184    #[serde(alias = "t")]
185    pub _type: String,
186    #[serde(rename = "s")]
187    #[serde(alias = "s")]
188    pub service_end_point: PeerServiceEndPoint, // serviceEndPoint
189
190    /// id is optional, if not provided, it will be set to #service, #service-1, #service-2, etc
191    #[serde(skip_serializing_if = "Option::is_none")]
192    pub id: Option<String>,
193}
194
195impl DIDPeerService {
196    fn convert(did: &str, service: DIDPeerService) -> Result<Service, DIDPeerError> {
197        let service_endpoint = match serde_json::to_value(PeerServiceEndPoint::to_long(
198            &service.service_end_point,
199        )) {
200            Ok(value) => {
201                if value.is_string() {
202                    if let Some(value) = value.as_str() {
203                        if let Ok(uri) = UriBuf::new(value.as_bytes().to_vec()) {
204                            Some(OneOrMany::One(Endpoint::Uri(uri)))
205                        } else {
206                            return Err(DIDPeerError::SyntaxErrorServiceDefinition(format!(
207                                "Couldn't convert ServiceEndPoint to a valid URI: {value}",
208                            )));
209                        }
210                    } else {
211                        return Err(DIDPeerError::SyntaxErrorServiceDefinition(format!(
212                            "Service URI appears to be a string, but can't parse as a string: {value}",
213                        )));
214                    }
215                } else {
216                    Some(OneOrMany::One(Endpoint::Map(value)))
217                }
218            }
219            Err(err) => {
220                return Err(DIDPeerError::SyntaxErrorServiceDefinition(format!(
221                    "Couldn't convert ServiceEndPoint to a valid representation. Reason: {err}",
222                )));
223            }
224        };
225
226        let id = if let Some(id) = service.id {
227            [did, &id].concat()
228        } else {
229            [did, "#service"].concat()
230        };
231
232        let id = match UriBuf::new(id.as_bytes().to_vec()) {
233            Ok(uri) => uri,
234            Err(e) => {
235                return Err(DIDPeerError::SyntaxErrorServiceDefinition(format!(
236                    "Error parsing service id: {id}. Reason: {e:?}",
237                )));
238            }
239        };
240
241        Ok(Service {
242            id,
243            type_: OneOrMany::One("DIDCommMessaging".into()),
244            service_endpoint,
245            property_set: BTreeMap::new(),
246        })
247    }
248}
249
250#[derive(Clone)]
251#[wasm_bindgen]
252/// DID Peer Key Purpose (used to create a new did:peer: string)
253///   Verification: Keys are referenced in the authentication and assertionMethod fields
254///   Encryption: Keys are referenced in the keyAgreement field
255pub enum DIDPeerKeys {
256    Verification,
257    Encryption,
258}
259
260impl fmt::Display for DIDPeerKeys {
261    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
262        match *self {
263            DIDPeerKeys::Verification => write!(f, "verification"),
264            DIDPeerKeys::Encryption => write!(f, "encryption"),
265        }
266    }
267}
268
269#[derive(Clone)]
270#[wasm_bindgen]
271/// Supported DID Peer Key Types (used to create a new did:peer: string)
272pub enum DIDPeerKeyType {
273    Ed25519,
274    Secp256k1,
275    P256,
276}
277
278impl fmt::Display for DIDPeerKeyType {
279    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
280        match *self {
281            DIDPeerKeyType::Ed25519 => write!(f, "ed25519"),
282            DIDPeerKeyType::Secp256k1 => write!(f, "secp256k1"),
283            DIDPeerKeyType::P256 => write!(f, "p256"),
284        }
285    }
286}
287
288#[derive(Clone)]
289#[wasm_bindgen(getter_with_clone)]
290/// Structure to help with creating a new did:peer: string
291///    purpose: ENUM (DIDPeerKeys) - Verification or Encryption
292///    public_key_multibase: String - Optional: Multibase encoded public key (did:key:(.*))
293///                                   If None, then auto-create and return the private key
294pub struct DIDPeerCreateKeys {
295    pub purpose: DIDPeerKeys,
296    pub type_: Option<DIDPeerKeyType>,
297    pub public_key_multibase: Option<String>,
298}
299
300#[wasm_bindgen]
301impl DIDPeerCreateKeys {
302    #[wasm_bindgen(constructor)]
303    pub fn new(
304        purpose: DIDPeerKeys,
305        type_: Option<DIDPeerKeyType>,
306        public_key_multibase: Option<String>,
307    ) -> Self {
308        DIDPeerCreateKeys {
309            purpose,
310            type_,
311            public_key_multibase,
312        }
313    }
314}
315
316/// DIDPeerCreatedKeys, contains information related to any keys that were created
317///
318/// key_multibase: `String`, the multibase_58 encoded key value (e.g. did:key:(.*))
319/// curve: `String`, the elliptic curve method used
320/// d: `String`, private key value in Base64URL_NOPAD
321/// x: `String`, public key value in Base64URL_NOPAD
322/// y: `Option<String>`, Optional: Y coordinate for EC keys in Base64URL_NOPAD
323#[derive(Clone, Debug, Serialize, Deserialize)]
324#[wasm_bindgen(getter_with_clone)]
325pub struct DIDPeerCreatedKeys {
326    pub key_multibase: String,
327    pub curve: String,
328    pub d: String,
329    pub x: String,
330    pub y: Option<String>,
331}
332
333/// Converts a public key into a DID VerificationMethod
334fn process_key(did: &str, id: &str, public_key: &str) -> Result<DIDVerificationMethod, Error> {
335    let mut properties = BTreeMap::new();
336
337    properties.insert(
338        "publicKeyMultibase".to_string(),
339        Value::String(public_key.to_string()),
340    );
341
342    Ok(DIDVerificationMethod {
343        id: DIDURLBuf::from_string(["did:peer:", did, id].concat()).unwrap(),
344        type_: "Multikey".to_string(),
345        controller: DIDBuf::from_string(["did:peer:", did].concat()).unwrap(),
346        properties,
347    })
348}
349
350impl DIDMethodResolver for DIDPeer {
351    async fn resolve_method_representation<'a>(
352        &'a self,
353        method_specific_id: &'a str,
354        options: Options,
355    ) -> Result<Output<Vec<u8>>, Error> {
356        let did = ["did:peer:", method_specific_id].concat();
357
358        // If did:peer is type 0, then treat it as a did:key
359        if let Some(id) = method_specific_id.strip_prefix('0') {
360            return DIDKey.resolve_method_representation(id, options).await;
361        }
362
363        // Only supports method 2 for did:peer
364        if !method_specific_id.starts_with('2') {
365            return Err(Error::MethodNotSupported(
366                "did:peer version 2 supported only".to_string(),
367            ));
368        }
369
370        let mut context = BTreeMap::new();
371        context.insert("@base".to_string(), serde_json::json!(method_specific_id));
372
373        let mut verification_methods: Vec<DIDVerificationMethod> = Vec::new();
374        let mut verification_relationships: VerificationRelationships =
375            VerificationRelationships::default();
376
377        //let mut key_agreements: Vec<DIDVerificationMethod> = Vec::new();
378        //let mut key_authentications: Vec<DIDVerificationMethod> = Vec::new();
379        //let mut key_assertion_methods: Vec<DIDVerificationMethod> = Vec::new();
380        let mut services: Vec<Service> = Vec::new();
381
382        // Split the DID for peer on '.'s, we skip the first one
383        // did:peer:2.(process from here)
384        let parts: Vec<&str> = method_specific_id[2..].split('.').collect();
385        let mut key_count: u32 = 1;
386        let mut service_idx: u32 = 0;
387
388        for part in parts {
389            let ch = part.chars().next();
390            match ch {
391                Some(e) => {
392                    match e {
393                        'A' => {
394                            // Assertion Method
395                            verification_methods.push(process_key(
396                                method_specific_id,
397                                &["#key-", &key_count.to_string()].concat(),
398                                &part[1..],
399                            )?);
400
401                            verification_relationships.assertion_method.push(
402                                verification_method::ValueOrReference::Reference(
403                                    DIDURLReferenceBuf::Relative(
404                                        RelativeDIDURLBuf::new(
405                                            ["#key-", &key_count.to_string()]
406                                                .concat()
407                                                .as_bytes()
408                                                .to_vec(),
409                                        )
410                                        .unwrap(),
411                                    ),
412                                ),
413                            );
414                            key_count += 1;
415                        }
416                        'D' => {
417                            // Capability Delegation
418                            verification_methods.push(process_key(
419                                method_specific_id,
420                                &["#key-", &key_count.to_string()].concat(),
421                                &part[1..],
422                            )?);
423
424                            verification_relationships.capability_delegation.push(
425                                verification_method::ValueOrReference::Reference(
426                                    DIDURLReferenceBuf::Relative(
427                                        RelativeDIDURLBuf::new(
428                                            ["#key-", &key_count.to_string()]
429                                                .concat()
430                                                .as_bytes()
431                                                .to_vec(),
432                                        )
433                                        .unwrap(),
434                                    ),
435                                ),
436                            );
437                            key_count += 1;
438                        }
439                        'E' => {
440                            // Key Agreement (Encryption)
441                            verification_methods.push(process_key(
442                                method_specific_id,
443                                &["#key-", &key_count.to_string()].concat(),
444                                &part[1..],
445                            )?);
446                            verification_relationships.key_agreement.push(
447                                verification_method::ValueOrReference::Reference(
448                                    DIDURLReferenceBuf::Relative(
449                                        RelativeDIDURLBuf::new(
450                                            ["#key-", &key_count.to_string()]
451                                                .concat()
452                                                .as_bytes()
453                                                .to_vec(),
454                                        )
455                                        .unwrap(),
456                                    ),
457                                ),
458                            );
459                            key_count += 1;
460                        }
461                        'I' => {
462                            // Capability Invocation
463                            verification_methods.push(process_key(
464                                method_specific_id,
465                                &["#key-", &key_count.to_string()].concat(),
466                                &part[1..],
467                            )?);
468
469                            verification_relationships.capability_invocation.push(
470                                verification_method::ValueOrReference::Reference(
471                                    DIDURLReferenceBuf::Relative(
472                                        RelativeDIDURLBuf::new(
473                                            ["#key-", &key_count.to_string()]
474                                                .concat()
475                                                .as_bytes()
476                                                .to_vec(),
477                                        )
478                                        .unwrap(),
479                                    ),
480                                ),
481                            );
482                            key_count += 1;
483                        }
484                        'V' => {
485                            // Authentication (Verification)
486                            verification_methods.push(process_key(
487                                method_specific_id,
488                                &["#key-", &key_count.to_string()].concat(),
489                                &part[1..],
490                            )?);
491
492                            verification_relationships.authentication.push(
493                                verification_method::ValueOrReference::Reference(
494                                    DIDURLReferenceBuf::Relative(
495                                        RelativeDIDURLBuf::new(
496                                            ["#key-", &key_count.to_string()]
497                                                .concat()
498                                                .as_bytes()
499                                                .to_vec(),
500                                        )
501                                        .unwrap(),
502                                    ),
503                                ),
504                            );
505                            verification_relationships.assertion_method.push(
506                                verification_method::ValueOrReference::Reference(
507                                    DIDURLReferenceBuf::Relative(
508                                        RelativeDIDURLBuf::new(
509                                            ["#key-", &key_count.to_string()]
510                                                .concat()
511                                                .as_bytes()
512                                                .to_vec(),
513                                        )
514                                        .unwrap(),
515                                    ),
516                                ),
517                            );
518
519                            key_count += 1;
520                        }
521                        'S' => {
522                            // Service
523                            let service = convert_service(&did, part, service_idx)
524                                .map_err(|e| Error::Internal(e.to_string()))?;
525                            services.push(service);
526                            service_idx += 1;
527                        }
528                        other => {
529                            return Err(Error::RepresentationNotSupported(format!(
530                                "An invalid Purpose Code ({other}) was found in the DID",
531                            )));
532                        }
533                    }
534                }
535                None => {
536                    // We shouldn't really get here
537                    // But it is ok if we do, we just skip it
538                }
539            }
540        }
541
542        let vm_type = match options.parameters.public_key_format {
543            Some(name) => VerificationMethodType::from_name(&name).ok_or_else(|| {
544                Error::Internal(format!(
545                    "verification method type `{name}` unsupported by did:peer"
546                ))
547            })?,
548            None => VerificationMethodType::Multikey,
549        };
550
551        let mut doc =
552            Document::new(DIDBuf::from_string(["did:peer:", method_specific_id].concat()).unwrap());
553        doc.verification_method = verification_methods;
554        doc.verification_relationships = verification_relationships;
555        doc.service = services;
556
557        let mut json_ld_context = Vec::new();
558        if let Some(context) = vm_type.context_entry() {
559            json_ld_context.push(context)
560        }
561
562        let content_type = options.accept.unwrap_or(MediaType::JsonLd);
563
564        let represented = doc.into_representation(representation::Options::from_media_type(
565            content_type,
566            move || representation::json_ld::Options {
567                context: representation::json_ld::Context::array(
568                    representation::json_ld::DIDContext::V1,
569                    json_ld_context,
570                ),
571            },
572        ));
573
574        Ok(resolution::Output::new(
575            represented.to_bytes(),
576            document::Metadata::default(),
577            resolution::Metadata::from_content_type(Some(content_type.to_string())),
578        ))
579    }
580}
581
582impl DIDMethod for DIDPeer {
583    const DID_METHOD_NAME: &'static str = "peer";
584}
585
586impl DIDPeer {
587    /// Creates a new did:peer DID
588    ///
589    /// This will preserve the order of the keys and services in creating the did:peer string
590    ///
591    /// # Examples
592    /// ```ignore
593    ///
594    /// // Create a did:peer with pre-existing encryption key (Multibase base58-btc e.g: z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK)
595    /// let keys = vec![DIDPeerCreateKeys {
596    ///     type_: Some(DIDPeerKeyType::Ed25519),
597    ///     purpose: DIDPeerKeys::Encryption,
598    ///     public_key_multibase: Some("z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK".into()),
599    /// }];
600    /// let did_peer = DIDPeer::create_peer_did(&keys, None).expect("Failed to create did:peer");
601    ///
602    /// // Create a random did:peer with services
603    /// let keys = vec![DIDPeerCreateKeys {
604    ///    type_: Some(DIDPeerKeyType::Secp256k1),
605    ///    purpose: DIDPeerKeys::Encryption,
606    ///    public_key_multibase: Some("z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK".into()),
607    ///  }];
608    /// let services: Vec<DIDPeerService> = vec![DIDPeerService {
609    ///    _type: "dm".into(),
610    ///    id: None,
611    ///    service_end_point: PeerServiceEndPoint::Long(PeerServiceEndPointLong {
612    ///        uri: "http://example.com/didcomm".into(),
613    ///        accept: vec!["didcomm/v2".into()],
614    ///        routing_keys: vec!["did:example:123456789abcdefghi#key-1".into()],
615    ///    }),
616    /// }];
617    ///
618    /// let did_peer =
619    ///    DIDPeer::create_peer_did(&keys, Some(&services)).expect("Failed to create did:peer");
620    ///
621    /// // How to create a key prior to creating a did:peer
622    /// let did =
623    ///     DIDKey::generate(&JWK::generate_ed25519().unwrap()).expect("Failed to create did:key");
624    ///
625    /// let keys = vec![DIDPeerCreateKeys {
626    ///     type_: Some(DIDPeerKeyType::Ed25519),
627    ///     purpose: DIDPeerKeys::Verification,
628    ///     public_key_multibase: Some(did[8..].to_string()),
629    /// }];
630    ///
631    /// let did_peer = DIDPeer::create_peer_did(&keys, None).expect("Failed to create did:peer");
632    /// ```
633    pub fn create_peer_did(
634        keys: &Vec<DIDPeerCreateKeys>,
635        services: Option<&Vec<DIDPeerService>>,
636    ) -> Result<(String, Vec<DIDPeerCreatedKeys>), DIDPeerError> {
637        let mut result = String::from("did:peer:2");
638
639        let mut private_keys: Vec<DIDPeerCreatedKeys> = vec![];
640        for key in keys {
641            // Create new keys if not provided
642            let public_key = if let Some(key) = key.public_key_multibase.as_ref() {
643                key.clone()
644            } else {
645                let jwk = match &key.type_ {
646                    Some(type_) => match type_ {
647                        DIDPeerKeyType::Ed25519 => match JWK::generate_ed25519() {
648                            Ok(k) => k,
649                            Err(e) => {
650                                return Err(DIDPeerError::InternalError(format!(
651                                    "Failed to generate ed25519 key. Reason: {e}",
652                                )));
653                            }
654                        },
655                        DIDPeerKeyType::Secp256k1 => JWK::generate_secp256k1(),
656                        DIDPeerKeyType::P256 => JWK::generate_p256(),
657                    },
658                    None => return Err(DIDPeerError::UnsupportedKeyType),
659                };
660                let did = if let Ok(output) = ssi::dids::DIDKey::generate(&jwk) {
661                    output.to_string()
662                } else {
663                    return Err(DIDPeerError::InternalError(
664                        "Couldn't create did:key".to_string(),
665                    ));
666                };
667
668                match jwk.params {
669                    Params::OKP(map) => {
670                        let d = if let Some(d) = &map.private_key {
671                            d
672                        } else {
673                            return Err(DIDPeerError::KeyParsingError(
674                                "Missing private key".to_string(),
675                            ));
676                        };
677                        private_keys.push(DIDPeerCreatedKeys {
678                            key_multibase: did[8..].to_string(),
679                            curve: map.curve.clone(),
680                            d: String::from(d),
681                            x: String::from(map.public_key.clone()),
682                            y: None,
683                        })
684                    }
685                    Params::EC(map) => {
686                        let curve = if let Some(curve) = &map.curve {
687                            curve
688                        } else {
689                            return Err(DIDPeerError::KeyParsingError("Missing curve".to_string()));
690                        };
691                        let d = if let Some(d) = &map.ecc_private_key {
692                            d
693                        } else {
694                            return Err(DIDPeerError::KeyParsingError(
695                                "Missing private key".to_string(),
696                            ));
697                        };
698
699                        let x = if let Some(x) = &map.x_coordinate {
700                            x
701                        } else {
702                            return Err(DIDPeerError::KeyParsingError(
703                                "Missing public key (x)".to_string(),
704                            ));
705                        };
706                        let y = if let Some(y) = &map.y_coordinate {
707                            y
708                        } else {
709                            return Err(DIDPeerError::KeyParsingError(
710                                "Missing public key (y)".to_string(),
711                            ));
712                        };
713
714                        private_keys.push(DIDPeerCreatedKeys {
715                            key_multibase: did[8..].to_string(),
716                            curve: curve.into(),
717                            d: String::from(d),
718                            x: String::from(x),
719                            y: Some(String::from(y)),
720                        })
721                    }
722                    _ => return Err(DIDPeerError::UnsupportedKeyType),
723                }
724
725                did[8..].to_string()
726            };
727
728            // Place based on key types
729            match key.purpose {
730                DIDPeerKeys::Verification => {
731                    result.push_str(&format!(".V{public_key}",));
732                }
733                DIDPeerKeys::Encryption => {
734                    result.push_str(&format!(".E{public_key}",));
735                }
736            }
737        }
738
739        if let Some(services) = services {
740            for service in services {
741                let service = serde_json::to_string(&service).map_err(|e| {
742                    DIDPeerError::SyntaxErrorServiceDefinition(format!(
743                        "Error parsing service: {e}",
744                    ))
745                })?;
746                result.push_str(&format!(".S{}", BASE64_URL_SAFE_NO_PAD.encode(service)));
747            }
748        }
749
750        Ok((result, private_keys))
751    }
752
753    /// Expands an existing DID Document from the did:key Multikeys to full JWT keys
754    /// This is useful for when you want to resolve a did:peer DID Document to a full JWT included DID Document
755    /// Converts base58 multi-keys to full JWTs in verificationMethod
756    pub async fn expand_keys(doc: &Document) -> Result<Document, DIDPeerError> {
757        let mut new_doc = doc.clone();
758
759        let mut new_vms: Vec<DIDVerificationMethod> = vec![];
760        for v_method in &doc.verification_method {
761            new_vms.push(Self::_convert_vm(v_method).await?);
762        }
763
764        new_doc.verification_method = new_vms;
765        Ok(new_doc)
766    }
767
768    // Converts
769    async fn _convert_vm(
770        method: &DIDVerificationMethod,
771    ) -> Result<DIDVerificationMethod, DIDPeerError> {
772        let current_controller = method.controller.clone();
773        let current_id = method.id.clone();
774        let did_key = if let Some(key) = method.properties.get("publicKeyBase58") {
775            ["did:key:", key.as_str().unwrap()].concat()
776        } else if let Some(key) = method.properties.get("publicKeyMultibase") {
777            ["did:key:", key.as_str().unwrap()].concat()
778        } else {
779            return Err(DIDPeerError::KeyParsingError(
780                "Failed to convert verification_method. Reason: Missing publicKeyBase58"
781                    .to_string(),
782            ));
783        };
784
785        let key_method = DIDKey;
786
787        let output = match key_method
788            .dereference_with(
789                DIDURL::new::<String>(&did_key.clone()).unwrap(),
790                Options {
791                    accept: None,
792                    parameters: Parameters {
793                        public_key_format: Some("JsonWebKey2020".to_string()),
794                        ..Default::default()
795                    },
796                },
797            )
798            .await
799        {
800            Ok(output) => output.content,
801            Err(e) => {
802                return Err(DIDPeerError::KeyParsingError(format!(
803                    "Failed to resolve key ({did_key}). Reason: {e}",
804                )));
805            }
806        };
807
808        if let Content::Resource(Resource::Document(doc)) = output
809            && let Some(vm) = doc.into_any_verification_method()
810        {
811            let mut new_vm = vm.clone();
812            new_vm.controller = current_controller;
813            new_vm.id = current_id;
814            return Ok(new_vm);
815        }
816
817        Err(DIDPeerError::KeyParsingError(
818            "Failed to convert verification_method. Reason: Missing verification_method"
819                .to_string(),
820        ))
821    }
822}
823
824#[cfg(test)]
825mod test {
826    use crate::{
827        DIDPeer, DIDPeerCreateKeys, DIDPeerKeyType, DIDPeerKeys, DIDPeerService,
828        PeerServiceEndPoint, PeerServiceEndPointLong, PeerServiceEndPointLongMap,
829    };
830
831    use ssi::{
832        JWK,
833        dids::{DID, DIDBuf, DIDResolver, document::DIDVerificationMethod},
834        verification_methods::ssi_core::OneOrMany,
835    };
836
837    const DID_PEER: &str = "did:peer:2.Vz6MkiToqovww7vYtxm1xNM15u9JzqzUFZ1k7s7MazYJUyAxv.EzQ3shQLqRUza6AMJFbPuMdvFRFWm1wKviQRnQSC1fScovJN4s.SeyJ0IjoiRElEQ29tbU1lc3NhZ2luZyIsInMiOnsidXJpIjoiaHR0cHM6Ly8xMjcuMC4wLjE6NzAzNyIsImEiOlsiZGlkY29tbS92MiJdLCJyIjpbXX19";
838
839    #[should_panic(
840        expected = "Failed to convert verification_method. Reason: Missing publicKeyBase58"
841    )]
842    #[tokio::test]
843    async fn expand_keys_throws_key_parsing_missing_pbk58_error() {
844        let peer = DIDPeer;
845        let output = peer
846            .resolve(DID::new::<String>(&DID_PEER.to_string()).unwrap())
847            .await
848            .unwrap();
849
850        let mut document = output.document.document().clone();
851        let mut new_vms: Vec<DIDVerificationMethod> = vec![];
852        for mut vm in document.verification_method {
853            vm.properties.remove("publicKeyMultibase");
854            new_vms.push(vm);
855        }
856
857        document.verification_method = new_vms;
858        let _expanded_doc = DIDPeer::expand_keys(&document).await.unwrap();
859    }
860
861    #[tokio::test]
862    async fn expand_keys_works() {
863        let peer = DIDPeer;
864        let document = peer
865            .resolve(DID::new::<String>(&DID_PEER.to_string()).unwrap())
866            .await
867            .expect("Couldn't resolve DID");
868
869        let vm_before_expansion = document.clone().document.verification_method.clone();
870        let expanded_doc = DIDPeer::expand_keys(&document.document).await.unwrap();
871        let vms_after_expansion = expanded_doc.verification_method;
872
873        for vm in vms_after_expansion.clone() {
874            assert!(vm.id.starts_with("did:peer"));
875        }
876        assert_eq!(vm_before_expansion.len(), vms_after_expansion.len())
877    }
878
879    #[tokio::test]
880    async fn create_peer_did_without_keys_and_services() {
881        let keys: Vec<DIDPeerCreateKeys> = vec![];
882        let services: Vec<DIDPeerService> = vec![];
883
884        let (did, _) = DIDPeer::create_peer_did(&keys, Some(&services)).unwrap();
885        let parts: Vec<&str> = did.split(":").collect();
886
887        assert_eq!(parts.len(), 3);
888        assert_eq!(parts[1], "peer");
889        assert!(parts[2].len() == 1);
890    }
891
892    #[tokio::test]
893    async fn create_peer_did_without_keys() {
894        let keys: Vec<DIDPeerCreateKeys> = vec![];
895        let services = vec![DIDPeerService {
896            _type: "dm".into(),
897            service_end_point: PeerServiceEndPoint::Long(PeerServiceEndPointLong::Map(
898                OneOrMany::One(PeerServiceEndPointLongMap {
899                    uri: "https://localhost:7037".into(),
900                    accept: vec!["didcomm/v2".into()],
901                    routing_keys: vec![],
902                }),
903            )),
904            id: None,
905        }];
906
907        let (did, _) = DIDPeer::create_peer_did(&keys, Some(&services)).unwrap();
908        let parts: Vec<&str> = did.split(":").collect();
909        let method_ids: Vec<&str> = parts[2].split(".").collect();
910
911        assert_eq!(parts.len(), 3);
912        assert_eq!(parts[1], "peer");
913        assert!(method_ids.len() > 1);
914        assert!(method_ids[1].len() > 1);
915    }
916
917    #[tokio::test]
918    async fn create_peer_did_without_services() {
919        let (e_did_key, v_did_key, keys) = _get_keys(Some(DIDPeerKeyType::Ed25519), true);
920        let services: Vec<DIDPeerService> = vec![];
921
922        let (did, _) = DIDPeer::create_peer_did(&keys, Some(&services)).unwrap();
923        let parts: Vec<&str> = did.split(":").collect();
924        let mut method_ids: Vec<&str> = parts[2].split(".").collect();
925        method_ids = method_ids[1..].to_vec();
926        let keys_multibase = [v_did_key[8..].to_string(), e_did_key[8..].to_string()];
927
928        method_ids.iter().take(2).for_each(|id| {
929            assert!(keys_multibase.contains(&id[1..].to_string()));
930        });
931        assert_eq!(parts.len(), 3);
932        assert_eq!(parts[1], "peer");
933    }
934
935    #[should_panic(expected = "UnsupportedKeyType")]
936    #[tokio::test]
937    async fn create_peer_did_should_throw_unsupported_key_error_p384() {
938        let (_, _, keys) = _get_keys(None, false);
939        // Create a service definition
940        let services = vec![DIDPeerService {
941            _type: "dm".into(),
942            service_end_point: PeerServiceEndPoint::Long(PeerServiceEndPointLong::Map(
943                OneOrMany::One(PeerServiceEndPointLongMap {
944                    uri: "https://localhost:7037".into(),
945                    accept: vec!["didcomm/v2".into()],
946                    routing_keys: vec![],
947                }),
948            )),
949            id: None,
950        }];
951
952        DIDPeer::create_peer_did(&keys, Some(&services)).unwrap();
953    }
954
955    #[tokio::test]
956    async fn create_peer_did_works_ed25519_without_passing_pub_key() {
957        let (_, _, keys) = _get_keys(Some(DIDPeerKeyType::Ed25519), false);
958
959        // Create a service definition
960        let services = vec![DIDPeerService {
961            _type: "dm".into(),
962            service_end_point: PeerServiceEndPoint::Long(PeerServiceEndPointLong::Map(
963                OneOrMany::One(PeerServiceEndPointLongMap {
964                    uri: "https://localhost:7037".into(),
965                    accept: vec!["didcomm/v2".into()],
966                    routing_keys: vec![],
967                }),
968            )),
969            id: None,
970        }];
971
972        let (did, keys) = DIDPeer::create_peer_did(&keys, Some(&services)).unwrap();
973        let parts: Vec<&str> = did.split(":").collect();
974        let method_ids: Vec<&str> = parts[2].split(".").collect();
975
976        assert_eq!(keys.len(), 2);
977        assert_eq!(parts.len(), 3);
978        assert_eq!(parts[1], "peer");
979        assert_eq!(method_ids.first().unwrap().parse::<i32>().unwrap(), 2);
980        assert_eq!(method_ids.len(), 4);
981    }
982
983    #[tokio::test]
984    async fn create_peer_did_works_p256_without_passing_pub_key() {
985        let (_, _, keys) = _get_keys(Some(DIDPeerKeyType::P256), false);
986
987        // Create a service definition
988        let services = vec![DIDPeerService {
989            _type: "dm".into(),
990            service_end_point: PeerServiceEndPoint::Long(PeerServiceEndPointLong::Map(
991                OneOrMany::One(PeerServiceEndPointLongMap {
992                    uri: "https://localhost:7037".into(),
993                    accept: vec!["didcomm/v2".into()],
994                    routing_keys: vec![],
995                }),
996            )),
997            id: None,
998        }];
999
1000        let (did, keys) = DIDPeer::create_peer_did(&keys, Some(&services)).unwrap();
1001        let parts: Vec<&str> = did.split(":").collect();
1002        let method_ids: Vec<&str> = parts[2].split(".").collect();
1003
1004        assert_eq!(keys.len(), 2);
1005        assert_eq!(parts.len(), 3);
1006        assert_eq!(parts[1], "peer");
1007        assert_eq!(method_ids.first().unwrap().parse::<i32>().unwrap(), 2);
1008        assert_eq!(method_ids.len(), 4);
1009    }
1010
1011    #[tokio::test]
1012    async fn create_peer_did_works_secp256k1_without_passing_pub_key() {
1013        let (_, _, keys) = _get_keys(Some(DIDPeerKeyType::Secp256k1), false);
1014
1015        // Create a service definition
1016        let services = vec![DIDPeerService {
1017            _type: "dm".into(),
1018            service_end_point: PeerServiceEndPoint::Long(PeerServiceEndPointLong::Map(
1019                OneOrMany::One(PeerServiceEndPointLongMap {
1020                    uri: "https://localhost:7037".into(),
1021                    accept: vec!["didcomm/v2".into()],
1022                    routing_keys: vec![],
1023                }),
1024            )),
1025            id: None,
1026        }];
1027
1028        let (did, keys) = DIDPeer::create_peer_did(&keys, Some(&services)).unwrap();
1029
1030        let parts: Vec<&str> = did.split(":").collect();
1031        let method_ids: Vec<&str> = parts[2].split(".").collect();
1032
1033        assert_eq!(keys.len(), 2);
1034        assert_eq!(parts.len(), 3);
1035        assert_eq!(parts[1], "peer");
1036        assert_eq!(method_ids.first().unwrap().parse::<i32>().unwrap(), 2);
1037        assert_eq!(method_ids.len(), 4);
1038    }
1039
1040    #[tokio::test]
1041    async fn create_peer_did_works_ed25519() {
1042        let (e_did_key, v_did_key, keys) = _get_keys(Some(DIDPeerKeyType::Ed25519), true);
1043
1044        // Create a service definition
1045        let services = vec![DIDPeerService {
1046            _type: "dm".into(),
1047            service_end_point: PeerServiceEndPoint::Long(PeerServiceEndPointLong::Map(
1048                OneOrMany::One(PeerServiceEndPointLongMap {
1049                    uri: "https://localhost:7037".into(),
1050                    accept: vec!["didcomm/v2".into()],
1051                    routing_keys: vec![],
1052                }),
1053            )),
1054            id: None,
1055        }];
1056
1057        let (did, _) = DIDPeer::create_peer_did(&keys, Some(&services)).unwrap();
1058        let parts: Vec<&str> = did.split(":").collect();
1059        let mut method_ids: Vec<&str> = parts[2].split(".").collect();
1060        method_ids = method_ids[1..].to_vec();
1061        let keys_multibase = [v_did_key[8..].to_string(), e_did_key[8..].to_string()];
1062
1063        method_ids.iter().take(2).for_each(|id| {
1064            assert!(keys_multibase.contains(&id[1..].to_string()));
1065        });
1066
1067        assert_eq!(parts.len(), 3);
1068        assert_eq!(parts[1], "peer");
1069    }
1070
1071    #[tokio::test]
1072    async fn create_peer_did_works_p256() {
1073        let (e_did_key, v_did_key, keys) = _get_keys(Some(DIDPeerKeyType::P256), true);
1074        // Create a service definition
1075        let services = vec![DIDPeerService {
1076            _type: "dm".into(),
1077            service_end_point: PeerServiceEndPoint::Long(PeerServiceEndPointLong::Map(
1078                OneOrMany::One(PeerServiceEndPointLongMap {
1079                    uri: "https://localhost:7037".into(),
1080                    accept: vec!["didcomm/v2".into()],
1081                    routing_keys: vec![],
1082                }),
1083            )),
1084            id: None,
1085        }];
1086
1087        let (did, _) = DIDPeer::create_peer_did(&keys, Some(&services)).unwrap();
1088        let parts: Vec<&str> = did.split(":").collect();
1089        let mut method_ids: Vec<&str> = parts[2].split(".").collect();
1090        method_ids = method_ids[1..].to_vec();
1091        let keys_multibase = [v_did_key[8..].to_string(), e_did_key[8..].to_string()];
1092
1093        method_ids.iter().take(2).for_each(|id| {
1094            assert!(keys_multibase.contains(&id[1..].to_string()));
1095        });
1096        assert_eq!(parts.len(), 3);
1097        assert_eq!(parts[1], "peer");
1098    }
1099
1100    #[tokio::test]
1101    async fn create_peer_did_works_secp256k1() {
1102        let (e_did_key, v_did_key, keys) = _get_keys(Some(DIDPeerKeyType::Secp256k1), true);
1103        // Create a service definition
1104        let services = vec![DIDPeerService {
1105            _type: "dm".into(),
1106            service_end_point: PeerServiceEndPoint::Long(PeerServiceEndPointLong::Map(
1107                OneOrMany::One(PeerServiceEndPointLongMap {
1108                    uri: "https://localhost:7037".into(),
1109                    accept: vec!["didcomm/v2".into()],
1110                    routing_keys: vec![],
1111                }),
1112            )),
1113            id: None,
1114        }];
1115
1116        let (did, _) = DIDPeer::create_peer_did(&keys, Some(&services)).unwrap();
1117        let parts: Vec<&str> = did.split(":").collect();
1118        let mut method_ids: Vec<&str> = parts[2].split(".").collect();
1119        method_ids = method_ids[1..].to_vec();
1120        let keys_multibase = [v_did_key[8..].to_string(), e_did_key[8..].to_string()];
1121
1122        method_ids.iter().take(2).for_each(|id| {
1123            assert!(keys_multibase.contains(&id[1..].to_string()));
1124        });
1125        assert_eq!(parts.len(), 3);
1126        assert_eq!(parts[1], "peer");
1127    }
1128
1129    fn _get_keys(
1130        key_type: Option<DIDPeerKeyType>,
1131        with_pub_key: bool,
1132    ) -> (DIDBuf, DIDBuf, Vec<DIDPeerCreateKeys>) {
1133        let encryption_key = match key_type {
1134            Some(DIDPeerKeyType::Ed25519) => JWK::generate_ed25519().unwrap(),
1135            Some(DIDPeerKeyType::P256) => JWK::generate_p256(),
1136            Some(DIDPeerKeyType::Secp256k1) => JWK::generate_secp256k1(),
1137            None => JWK::generate_p384(),
1138        };
1139        let verification_key = match key_type {
1140            Some(DIDPeerKeyType::Ed25519) => JWK::generate_ed25519().unwrap(),
1141            Some(DIDPeerKeyType::P256) => JWK::generate_p256(),
1142            Some(DIDPeerKeyType::Secp256k1) => JWK::generate_secp256k1(),
1143            None => JWK::generate_p384(),
1144        };
1145        //  Create the did:key DID's for each key above
1146        let e_did_key = ssi::dids::DIDKey::generate(&encryption_key).unwrap();
1147        let v_did_key = ssi::dids::DIDKey::generate(&verification_key).unwrap();
1148
1149        // Put these keys in order and specify the type of each key (we strip the did:key: from the front)
1150        let keys = vec![
1151            DIDPeerCreateKeys {
1152                purpose: DIDPeerKeys::Verification,
1153                type_: key_type.clone(),
1154                public_key_multibase: if with_pub_key {
1155                    Some(v_did_key[8..].to_string())
1156                } else {
1157                    None
1158                },
1159            },
1160            DIDPeerCreateKeys {
1161                purpose: DIDPeerKeys::Encryption,
1162                type_: key_type.clone(),
1163                public_key_multibase: if with_pub_key {
1164                    Some(e_did_key[8..].to_string())
1165                } else {
1166                    None
1167                },
1168            },
1169        ];
1170
1171        (e_did_key, v_did_key, keys)
1172    }
1173}
1174
1175// **********************************************************************************************************************************
1176// WASM Specific structs and code
1177// **********************************************************************************************************************************
1178
1179/// DIDService structure, input into the DidPeerCreate structure
1180///
1181/// DIDService {
1182///         _type: `Option<String>` (Optional: If not specified, defaults to 'DIDCommMessaging')
1183///           uri: `String`         (Required: Service endpoint URI. E.g. https://localhost:7130/)
1184///        accept: `Vec<String>`    (Array of possible message types this service accepts)
1185///  routing_keys: `Vec<String>`    (Array of possible keys this Service endpoint can use)
1186///            id: `Option<String>` (Optional: ID of the service. If not specified, defaults to #service)
1187/// }
1188#[wasm_bindgen(getter_with_clone)]
1189#[derive(Clone, Serialize, Deserialize)]
1190pub struct DIDService {
1191    pub _type: Option<String>,
1192    pub uri: String,
1193    pub accept: Vec<String>,
1194    pub routing_keys: Vec<String>,
1195    pub id: Option<String>,
1196}
1197
1198#[wasm_bindgen]
1199impl DIDService {
1200    #[wasm_bindgen(constructor)]
1201    pub fn new(
1202        uri: String,
1203        accept: Vec<String>,
1204        routing_keys: Vec<String>,
1205        id: Option<String>,
1206    ) -> Self {
1207        DIDService {
1208            _type: None,
1209            uri,
1210            accept,
1211            routing_keys,
1212            id,
1213        }
1214    }
1215}
1216
1217impl From<DIDService> for DIDPeerService {
1218    fn from(service: DIDService) -> Self {
1219        DIDPeerService {
1220            _type: service._type.unwrap_or("DIDCommMessaging".into()),
1221            service_end_point: PeerServiceEndPoint::Short(PeerServiceEndPointShort::Map(
1222                OneOrMany::One(PeerServiceEndPointShortMap {
1223                    uri: service.uri,
1224                    a: service.accept,
1225                    r: service.routing_keys,
1226                }),
1227            )),
1228            id: service.id,
1229        }
1230    }
1231}
1232
1233impl From<&DIDService> for DIDPeerService {
1234    fn from(service: &DIDService) -> Self {
1235        service.clone().into()
1236    }
1237}
1238
1239/// DidPeerCreate structure,  input from JS into [create_did_peer] call
1240/// Contains the required keys and optional services to create a new did:peer DID
1241///
1242/// DIDPeerCreate {
1243///       keys: Vec<[DIDPeerCreateKeys]> (Required: Must contain at least one key for Encryption and another key for Verification)
1244///   services: Option<Vec<[DIDService]> (Optional: Array of DIDService structs to add to the DID Document)
1245/// }
1246#[derive(Clone)]
1247#[wasm_bindgen(getter_with_clone)]
1248pub struct DidPeerCreate {
1249    pub keys: Vec<DIDPeerCreateKeys>,
1250    pub services: Option<Vec<DIDService>>,
1251}
1252
1253#[wasm_bindgen]
1254impl DidPeerCreate {
1255    #[wasm_bindgen(constructor)]
1256    pub fn new(keys: Vec<DIDPeerCreateKeys>, services: Option<Vec<DIDService>>) -> Self {
1257        DidPeerCreate { keys, services }
1258    }
1259}
1260
1261#[derive(Serialize, Deserialize)]
1262#[wasm_bindgen(getter_with_clone)]
1263pub struct DIDPeerResult {
1264    pub did: String,
1265    pub keys: Vec<DIDPeerCreatedKeys>,
1266}
1267
1268#[wasm_bindgen]
1269/// create_did_peer() wasm wrapper for [DIDPeer::create_peer_did]
1270/// Input: reference to [DidPeerCreate] struct
1271/// Returns: Error or String of the newly created did:peer DID
1272///
1273/// Notes:
1274///   [DidPeerCreate] contains an array of keys and an optional array of Services
1275///   These arrays are processed in order (as in element 0 is processed first, then element 1, etc)
1276///   This means the key and service identifiers are auto-generated in the order they are provided
1277///   i.e. #service, #service-1, #service-2 and #key-1, #key-2, #key-3 ...
1278pub fn create_did_peer(input: &DidPeerCreate) -> Result<DIDPeerResult, DIDPeerError> {
1279    // Convert DIDService to DIDPeerService
1280    let mut new_services: Vec<DIDPeerService> = vec![];
1281    if let Some(services) = input.services.as_ref() {
1282        for service in services {
1283            new_services.push(service.into());
1284        }
1285    }
1286
1287    // Create the did:peer DID
1288    let response = DIDPeer::create_peer_did(&input.keys, Some(&new_services));
1289
1290    if let Ok((did, keys)) = response {
1291        Ok(DIDPeerResult { did, keys })
1292    } else {
1293        Err(response.unwrap_err())
1294    }
1295}
1296
1297#[wasm_bindgen]
1298/// resolve_did_peer() resolves a DID Peer method DID to a full DID Document represented by a JS object
1299/// Input: String of the DID Peer method DID (did:peer:2...)
1300/// Returns: Error or JSON String of the resolved DID Document
1301///
1302/// NOTE: This is an async call, so you must await the result
1303pub async fn resolve_did_peer(did: &str) -> Result<String, DIDPeerError> {
1304    let peer = DIDPeer;
1305
1306    match peer
1307        .resolve(DID::new::<String>(&did.to_string()).unwrap())
1308        .await
1309    {
1310        Ok(output) => match serde_json::to_string_pretty(&output.document) {
1311            Ok(json) => Ok(json),
1312            Err(e) => Err(DIDPeerError::JsonParsingError(format!(
1313                "Couldn't convert DID Document to JSON. Reason: {e}",
1314            ))),
1315        },
1316        Err(e) => Err(DIDPeerError::KeyParsingError(format!(
1317            "Failed to resolve key ({did}). Reason: {e}",
1318        ))),
1319    }
1320}