tap_agent/
did.rs

1//! DID resolution and generation functionality for the TAP Agent.
2//!
3//! This module provides a multi-resolver for Decentralized Identifiers (DIDs)
4//! that integrates with the didcomm library's DID resolution system. The multi-resolver
5//! currently supports the did:key method, with the architecture allowing for additional
6//! methods to be added in the future.
7//!
8//! It also provides functionality to generate new DIDs with different cryptographic curves.
9
10use crate::key_manager::{Secret, SecretMaterial, SecretType};
11use async_trait::async_trait;
12use base64::Engine;
13use curve25519_dalek::edwards::CompressedEdwardsY;
14use ed25519_dalek::{SigningKey as Ed25519SigningKey, VerifyingKey as Ed25519VerifyingKey};
15use k256::ecdsa::SigningKey as Secp256k1SigningKey;
16use multibase::{decode, encode, Base};
17use p256::ecdsa::SigningKey as P256SigningKey;
18use rand::rngs::OsRng;
19use serde::{Deserialize, Serialize};
20use serde_json::Value;
21use std::collections::HashMap;
22use std::fmt::Debug;
23use std::sync::{Arc, RwLock};
24
25use crate::error::{Error, Result};
26
27/// DID Document
28#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
29pub struct DIDDoc {
30    /// DID that this document describes
31    pub id: String,
32
33    /// List of verification methods
34    pub verification_method: Vec<VerificationMethod>,
35
36    /// List of authentication verification method references (id strings)
37    pub authentication: Vec<String>,
38
39    /// List of key agreement verification method references (id strings)
40    pub key_agreement: Vec<String>,
41
42    /// List of assertion method verification method references (id strings)
43    #[serde(default)]
44    pub assertion_method: Vec<String>,
45
46    /// List of capability invocation verification method references (id strings)
47    #[serde(default)]
48    pub capability_invocation: Vec<String>,
49
50    /// List of capability delegation verification method references (id strings)
51    #[serde(default)]
52    pub capability_delegation: Vec<String>,
53
54    /// List of services
55    pub service: Vec<Service>,
56}
57
58/// Service definition in a DID Document
59#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
60pub struct Service {
61    /// Service ID
62    pub id: String,
63
64    /// Service type
65    #[serde(rename = "type")]
66    pub type_: String,
67
68    /// Service endpoint URL
69    pub service_endpoint: String,
70
71    /// Additional properties
72    #[serde(flatten)]
73    pub properties: HashMap<String, Value>,
74}
75
76/// Verification method in a DID Document
77#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
78pub struct VerificationMethod {
79    /// Verification method ID
80    pub id: String,
81
82    /// Verification method type
83    #[serde(rename = "type")]
84    pub type_: VerificationMethodType,
85
86    /// Controller DID
87    pub controller: String,
88
89    /// Verification material
90    #[serde(flatten)]
91    pub verification_material: VerificationMaterial,
92}
93
94/// Verification method type
95#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
96#[serde(rename_all = "camelCase")]
97pub enum VerificationMethodType {
98    /// Ed25519 Verification Key 2018
99    Ed25519VerificationKey2018,
100
101    /// X25519 Key Agreement Key 2019
102    X25519KeyAgreementKey2019,
103
104    /// ECDSA Secp256k1 Verification Key 2019
105    EcdsaSecp256k1VerificationKey2019,
106
107    /// JSON Web Key 2020
108    JsonWebKey2020,
109}
110
111/// Verification material
112#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
113#[serde(untagged)]
114pub enum VerificationMaterial {
115    /// Base58 encoded public key
116    Base58 {
117        /// Public key encoded in base58
118        public_key_base58: String,
119    },
120
121    /// Multibase encoded public key
122    Multibase {
123        /// Public key encoded in multibase
124        public_key_multibase: String,
125    },
126
127    /// JSON Web Key
128    JWK {
129        /// Public key in JWK format
130        public_key_jwk: Value,
131    },
132}
133
134/// Key types supported for DID generation
135#[derive(Debug, Clone, Copy, PartialEq, Eq)]
136pub enum KeyType {
137    /// Ed25519 key type (EdDSA)
138    Ed25519,
139    /// P-256 key type (ECDSA secp256r1)
140    P256,
141    /// Secp256k1 key type (ECDSA secp256k1)
142    Secp256k1,
143}
144
145/// Generated key information
146#[derive(Debug, Clone)]
147pub struct GeneratedKey {
148    /// The key type
149    pub key_type: KeyType,
150    /// The generated DID
151    pub did: String,
152    /// The public key in binary form
153    pub public_key: Vec<u8>,
154    /// The private key in binary form
155    pub private_key: Vec<u8>,
156    /// The DID document
157    pub did_doc: DIDDoc,
158}
159
160/// Options for generating a DID
161#[derive(Debug, Clone)]
162pub struct DIDGenerationOptions {
163    /// Key type to use
164    pub key_type: KeyType,
165}
166
167impl Default for DIDGenerationOptions {
168    fn default() -> Self {
169        Self {
170            key_type: KeyType::Ed25519,
171        }
172    }
173}
174
175/// A trait for resolving DIDs to DID documents that is Send+Sync.
176/// This trait is only available in native builds.
177#[cfg(not(target_arch = "wasm32"))]
178#[async_trait]
179pub trait SyncDIDResolver: Send + Sync + Debug {
180    /// Resolve a DID to a DID document.
181    ///
182    /// # Parameters
183    /// * `did` - The DID to resolve
184    ///
185    /// # Returns
186    /// The DID document as an Option
187    async fn resolve(&self, did: &str) -> Result<Option<DIDDoc>>;
188}
189
190/// A resolver for a specific DID method.
191/// This trait is only available in native builds.
192#[cfg(not(target_arch = "wasm32"))]
193#[async_trait]
194#[cfg(not(target_arch = "wasm32"))]
195pub trait DIDMethodResolver: Send + Sync + Debug {
196    /// Returns the method name this resolver handles (e.g., "key", "web", "pkh").
197    fn method(&self) -> &str;
198
199    /// Resolve a DID to a DID document.
200    ///
201    /// # Parameters
202    /// * `did` - The DID to resolve
203    ///
204    /// # Returns
205    /// The DID document as an Option
206    async fn resolve_method(&self, did: &str) -> Result<Option<DIDDoc>>;
207}
208
209/// A simplified DID resolver for WebAssembly with no async or Send/Sync requirements.
210#[cfg(target_arch = "wasm32")]
211pub trait WasmDIDResolver: Debug {
212    /// Resolves a DID synchronously, returning the DID document.
213    fn resolve(&self, did: &str) -> Result<Option<DIDDoc>>;
214}
215
216/// A simplified method-specific DID resolver for WebAssembly.
217#[cfg(target_arch = "wasm32")]
218pub trait WasmDIDMethodResolver: Debug {
219    /// Returns the method name this resolver handles.
220    fn method(&self) -> &str;
221
222    /// Resolves a DID synchronously, returning the DID document.
223    fn resolve_method(&self, did: &str) -> Result<Option<DIDDoc>>;
224
225    /// Get this resolver as Any for downcasting
226    fn as_any(&self) -> &dyn std::any::Any;
227}
228
229/// A resolver for the did:key method.
230#[derive(Debug, Default)]
231pub struct KeyResolver;
232
233impl KeyResolver {
234    /// Create a new KeyResolver
235    pub fn new() -> Self {
236        Self
237    }
238
239    /// Convert an Ed25519 public key to an X25519 public key
240    ///
241    /// This follows the conversion process described in RFC 7748
242    /// https://datatracker.ietf.org/doc/html/rfc7748#section-5
243    fn ed25519_to_x25519(ed25519_pubkey: &[u8]) -> Option<[u8; 32]> {
244        // The Ed25519 public key should be 32 bytes
245        if ed25519_pubkey.len() != 32 {
246            return None;
247        }
248
249        // Add debugging
250        println!("Ed25519 pubkey: {:?}", ed25519_pubkey);
251
252        // Try to create a CompressedEdwardsY from the bytes
253        let edwards_y = match CompressedEdwardsY::try_from(ed25519_pubkey) {
254            Ok(point) => point,
255            Err(e) => {
256                println!("Error converting to CompressedEdwardsY: {:?}", e);
257                return None;
258            }
259        };
260
261        // Try to decompress to get the Edwards point
262        let edwards_point = match edwards_y.decompress() {
263            Some(point) => point,
264            None => {
265                println!("Failed to decompress Edwards point");
266                return None;
267            }
268        };
269
270        // Convert to Montgomery form
271        let montgomery_point = edwards_point.to_montgomery();
272
273        // Get the raw bytes representation of the X25519 key
274        Some(montgomery_point.to_bytes())
275    }
276}
277
278#[cfg(target_arch = "wasm32")]
279impl WasmDIDMethodResolver for KeyResolver {
280    fn method(&self) -> &str {
281        "key"
282    }
283
284    fn as_any(&self) -> &dyn std::any::Any {
285        self
286    }
287
288    fn resolve_method(&self, did_key: &str) -> Result<Option<DIDDoc>> {
289        // Same implementation but without async/await
290        // Validate that this is a did:key
291        if !did_key.starts_with("did:key:") {
292            return Ok(None);
293        }
294
295        // Parse the multibase-encoded public key
296        let key_id = &did_key[8..]; // Skip the "did:key:" prefix
297        let (_, key_bytes) = match decode(key_id) {
298            Ok(result) => result,
299            Err(_) => return Ok(None),
300        };
301
302        // Check the key prefix - for did:key only Ed25519 is supported
303        if key_bytes.len() < 2 {
304            return Ok(None);
305        }
306
307        // Verify the key type - 0xED01 for Ed25519
308        if key_bytes[0] != 0xED || key_bytes[1] != 0x01 {
309            return Ok(None);
310        }
311
312        // Create the DID Document with the Ed25519 public key
313        let ed25519_public_key = &key_bytes[2..];
314
315        let ed_vm_id = format!("{}#{}", did_key, key_id);
316
317        // Create the Ed25519 verification method
318        let ed_verification_method = VerificationMethod {
319            id: ed_vm_id.clone(),
320            type_: VerificationMethodType::Ed25519VerificationKey2018,
321            controller: did_key.to_string(),
322            verification_material: VerificationMaterial::Multibase {
323                public_key_multibase: key_id.to_string(),
324            },
325        };
326
327        // Convert the Ed25519 public key to X25519 for key agreement
328        let mut verification_methods = vec![ed_verification_method.clone()];
329        let mut key_agreement = Vec::new();
330
331        if let Some(x25519_key) = Self::ed25519_to_x25519(ed25519_public_key) {
332            // Encode the X25519 public key in multibase format
333            let mut x25519_bytes = vec![0xEC, 0x01]; // Prefix for X25519
334            x25519_bytes.extend_from_slice(&x25519_key);
335            let x25519_multibase = encode(Base::Base58Btc, x25519_bytes);
336
337            // Create the X25519 verification method ID
338            let x25519_vm_id = format!("{}#{}", did_key, x25519_multibase);
339
340            // Create the X25519 verification method
341            let x25519_verification_method = VerificationMethod {
342                id: x25519_vm_id.clone(),
343                type_: VerificationMethodType::X25519KeyAgreementKey2019,
344                controller: did_key.to_string(),
345                verification_material: VerificationMaterial::Multibase {
346                    public_key_multibase: x25519_multibase,
347                },
348            };
349
350            // Add the X25519 key agreement method
351            verification_methods.push(x25519_verification_method);
352            key_agreement.push(x25519_vm_id);
353        }
354
355        // Create the DID document
356        let did_doc = DIDDoc {
357            id: did_key.to_string(),
358            verification_method: verification_methods,
359            authentication: vec![ed_vm_id],
360            key_agreement,
361            assertion_method: Vec::new(),
362            capability_invocation: Vec::new(),
363            capability_delegation: Vec::new(),
364            service: Vec::new(),
365        };
366
367        Ok(Some(did_doc))
368    }
369}
370
371#[cfg(not(target_arch = "wasm32"))]
372#[async_trait]
373impl DIDMethodResolver for KeyResolver {
374    fn method(&self) -> &str {
375        "key"
376    }
377
378    async fn resolve_method(&self, did_key: &str) -> Result<Option<DIDDoc>> {
379        // Validate that this is a did:key
380        if !did_key.starts_with("did:key:") {
381            return Ok(None);
382        }
383
384        // Parse the multibase-encoded public key
385        let key_id = &did_key[8..]; // Skip the "did:key:" prefix
386        let (_, key_bytes) = match decode(key_id) {
387            Ok(result) => result,
388            Err(_) => return Ok(None),
389        };
390
391        // Check the key prefix - for did:key only Ed25519 is supported
392        if key_bytes.len() < 2 {
393            return Ok(None);
394        }
395
396        // Verify the key type - 0xED01 for Ed25519
397        if key_bytes[0] != 0xED || key_bytes[1] != 0x01 {
398            return Ok(None);
399        }
400
401        // Create the DID Document with the Ed25519 public key
402        let ed25519_public_key = &key_bytes[2..];
403
404        let ed_vm_id = format!("{}#{}", did_key, key_id);
405
406        // Create the Ed25519 verification method
407        let ed_verification_method = VerificationMethod {
408            id: ed_vm_id.clone(),
409            type_: VerificationMethodType::Ed25519VerificationKey2018,
410            controller: did_key.to_string(),
411            verification_material: VerificationMaterial::Multibase {
412                public_key_multibase: key_id.to_string(),
413            },
414        };
415
416        // Convert the Ed25519 public key to X25519 for key agreement
417        let mut verification_methods = vec![ed_verification_method.clone()];
418        let mut key_agreement = Vec::new();
419
420        if let Some(x25519_key) = Self::ed25519_to_x25519(ed25519_public_key) {
421            println!("Successfully converted Ed25519 to X25519!");
422            // Encode the X25519 public key in multibase format
423            let mut x25519_bytes = vec![0xEC, 0x01]; // Prefix for X25519
424            x25519_bytes.extend_from_slice(&x25519_key);
425            let x25519_multibase = encode(Base::Base58Btc, x25519_bytes);
426
427            // Create the X25519 verification method ID
428            let x25519_vm_id = format!("{}#{}", did_key, x25519_multibase);
429
430            // Create the X25519 verification method
431            let x25519_verification_method = VerificationMethod {
432                id: x25519_vm_id.clone(),
433                type_: VerificationMethodType::X25519KeyAgreementKey2019,
434                controller: did_key.to_string(),
435                verification_material: VerificationMaterial::Multibase {
436                    public_key_multibase: x25519_multibase,
437                },
438            };
439
440            // Add the X25519 key agreement method
441            verification_methods.push(x25519_verification_method);
442            key_agreement.push(x25519_vm_id);
443        } else {
444            println!("Failed to convert Ed25519 to X25519!");
445        }
446
447        // Create the DID document
448        let did_doc = DIDDoc {
449            id: did_key.to_string(),
450            verification_method: verification_methods,
451            authentication: vec![ed_vm_id],
452            key_agreement,
453            assertion_method: Vec::new(),
454            capability_invocation: Vec::new(),
455            capability_delegation: Vec::new(),
456            service: Vec::new(),
457        };
458
459        Ok(Some(did_doc))
460    }
461}
462
463/// A multi-resolver for DID methods. This resolver manages multiple
464/// method-specific resolver. New resolvers can be added at runtime.
465#[derive(Debug)]
466#[cfg(not(target_arch = "wasm32"))]
467pub struct MultiResolver {
468    resolvers: RwLock<HashMap<String, Arc<dyn DIDMethodResolver>>>,
469}
470
471#[cfg(not(target_arch = "wasm32"))]
472unsafe impl Send for MultiResolver {}
473#[cfg(not(target_arch = "wasm32"))]
474unsafe impl Sync for MultiResolver {}
475
476#[cfg(not(target_arch = "wasm32"))]
477impl MultiResolver {
478    /// Create a new empty MultiResolver
479    pub fn new() -> Self {
480        Self {
481            resolvers: RwLock::new(HashMap::new()),
482        }
483    }
484
485    /// Create a new MultiResolver with a list of resolvers
486    pub fn new_with_resolvers(resolvers: Vec<Arc<dyn DIDMethodResolver>>) -> Self {
487        let resolver = Self::new();
488
489        // Add each resolver to the map if we can acquire the write lock
490        if let Ok(mut resolver_map) = resolver.resolvers.write() {
491            for r in resolvers {
492                let method = r.method().to_string();
493                resolver_map.insert(method, r);
494            }
495        }
496
497        resolver
498    }
499
500    /// Register a new resolver for a specific DID method
501    pub fn register_method<R>(&mut self, method: &str, resolver: R) -> &mut Self
502    where
503        R: DIDMethodResolver + Send + Sync + 'static,
504    {
505        if let Ok(mut resolvers) = self.resolvers.write() {
506            resolvers.insert(method.to_string(), Arc::new(resolver));
507        }
508        self
509    }
510}
511
512/// DID Web Resolver for resolving did:web identifiers
513#[derive(Debug, Default)]
514pub struct WebResolver;
515
516impl WebResolver {
517    /// Create a new WebResolver
518    pub fn new() -> Self {
519        Self {}
520    }
521}
522
523#[cfg(target_arch = "wasm32")]
524impl WasmDIDMethodResolver for WebResolver {
525    fn method(&self) -> &str {
526        "web"
527    }
528
529    fn as_any(&self) -> &dyn std::any::Any {
530        self
531    }
532
533    fn resolve_method(&self, did: &str) -> Result<Option<DIDDoc>> {
534        // For WASM, return a simple placeholder DID document without actual resolution
535        // Because we lack the proper web-fetch capabilities at the moment
536        let parts: Vec<&str> = did.split(':').collect();
537        if parts.len() < 3 || parts[0] != "did" || parts[1] != "web" {
538            return Err(Error::InvalidDID);
539        }
540
541        // Create a minimal DID document for did:web
542        let verification_method = VerificationMethod {
543            id: format!("{}#keys-1", did),
544            type_: VerificationMethodType::Ed25519VerificationKey2018,
545            controller: did.to_string(),
546            verification_material: VerificationMaterial::Multibase {
547                public_key_multibase: "zMockPublicKey".to_string(),
548            },
549        };
550
551        let did_doc = DIDDoc {
552            id: did.to_string(),
553            verification_method: vec![verification_method.clone()],
554            authentication: vec![verification_method.id.clone()],
555            key_agreement: Vec::new(),
556            assertion_method: Vec::new(),
557            capability_invocation: Vec::new(),
558            capability_delegation: Vec::new(),
559            service: Vec::new(),
560        };
561
562        Ok(Some(did_doc))
563    }
564}
565
566#[cfg(not(target_arch = "wasm32"))]
567#[async_trait]
568impl DIDMethodResolver for WebResolver {
569    fn method(&self) -> &str {
570        "web"
571    }
572
573    async fn resolve_method(&self, did: &str) -> Result<Option<DIDDoc>> {
574        // Extract domain from did:web format
575        let parts: Vec<&str> = did.split(':').collect();
576        if parts.len() < 3 || parts[0] != "did" || parts[1] != "web" {
577            return Err(Error::InvalidDID);
578        }
579
580        // Extract the domain (and path if present)
581        let domain_path = parts[2..].join(":");
582        let domain_path = domain_path.replace("%3A", ":");
583
584        // Construct the URL to fetch the DID document
585        // did:web:example.com -> https://example.com/.well-known/did.json
586        // did:web:example.com:path:to:resource -> https://example.com/path/to/resource/did.json
587
588        let url = if domain_path.contains(":") {
589            // Convert additional colons to slashes for path components
590            let path_segments: Vec<&str> = domain_path.split(':').collect();
591            let domain = path_segments[0];
592            let path = path_segments[1..].join("/");
593            format!("https://{}/{}/did.json", domain, path)
594        } else {
595            // Standard case: did:web:example.com
596            format!("https://{}/.well-known/did.json", domain_path)
597        };
598
599        // Attempt to fetch and parse the DID document
600        #[cfg(feature = "native")]
601        {
602            use reqwest::Client;
603
604            let client = Client::new();
605            match client.get(&url).send().await {
606                Ok(response) => {
607                    if response.status().is_success() {
608                        match response.text().await {
609                            Ok(text) => {
610                                // First try normal parsing
611                                let parse_result = serde_json::from_str::<DIDDoc>(&text);
612                                match parse_result {
613                                    Ok(doc) => {
614                                        // Validate that the document ID matches the requested DID
615                                        if doc.id != did {
616                                            return Err(Error::DIDResolution(format!(
617                                                "DID Document ID ({}) does not match requested DID ({})",
618                                                doc.id, did
619                                            )));
620                                        }
621                                        Ok(Some(doc))
622                                    }
623                                    Err(parse_error) => {
624                                        // If normal parsing fails, try to parse as a generic JSON Value
625                                        // and manually construct a DIDDoc with the essential fields
626                                        match serde_json::from_str::<serde_json::Value>(&text) {
627                                            Ok(json_value) => {
628                                                let doc_id = match json_value.get("id") {
629                                                    Some(id) => match id.as_str() {
630                                                        Some(id_str) => id_str.to_string(),
631                                                        None => return Err(Error::DIDResolution(
632                                                            "DID Document has invalid 'id' field"
633                                                                .to_string(),
634                                                        )),
635                                                    },
636                                                    None => {
637                                                        return Err(Error::DIDResolution(
638                                                            "DID Document missing 'id' field"
639                                                                .to_string(),
640                                                        ))
641                                                    }
642                                                };
643
644                                                // Validate ID
645                                                if doc_id != did {
646                                                    return Err(Error::DIDResolution(format!(
647                                                        "DID Document ID ({}) does not match requested DID ({})",
648                                                        doc_id, did
649                                                    )));
650                                                }
651
652                                                // Try to extract verification methods and other fields
653                                                println!("WARNING: Using partial DID document parsing due to format issues");
654                                                println!("Original parse error: {}", parse_error);
655
656                                                // Extract verification methods if present
657                                                // Create a longer-lived empty vec to handle the None case
658                                                let empty_vec = Vec::new();
659                                                let vm_array = json_value
660                                                    .get("verificationMethod")
661                                                    .and_then(|v| v.as_array())
662                                                    .unwrap_or(&empty_vec);
663
664                                                // Attempt to parse each verification method
665                                                let mut verification_methods = Vec::new();
666                                                for vm_value in vm_array {
667                                                    if let Ok(vm) = serde_json::from_value::<
668                                                        VerificationMethod,
669                                                    >(
670                                                        vm_value.clone()
671                                                    ) {
672                                                        verification_methods.push(vm);
673                                                    }
674                                                }
675
676                                                // Extract authentication references
677                                                let authentication = json_value
678                                                    .get("authentication")
679                                                    .and_then(|v| v.as_array())
680                                                    .unwrap_or(&empty_vec)
681                                                    .iter()
682                                                    .filter_map(|v| {
683                                                        v.as_str().map(|s| s.to_string())
684                                                    })
685                                                    .collect();
686
687                                                // Extract key agreement references
688                                                let key_agreement = json_value
689                                                    .get("keyAgreement")
690                                                    .and_then(|v| v.as_array())
691                                                    .unwrap_or(&empty_vec)
692                                                    .iter()
693                                                    .filter_map(|v| {
694                                                        v.as_str().map(|s| s.to_string())
695                                                    })
696                                                    .collect();
697
698                                                // We'll create an empty services list for the DIDDoc
699                                                // But save service information separately for display purposes
700                                                let services = Vec::new();
701
702                                                // Extract raw service information for display
703                                                if let Some(svc_array) = json_value
704                                                    .get("service")
705                                                    .and_then(|v| v.as_array())
706                                                {
707                                                    println!("\nService endpoints (extracted from JSON):");
708                                                    for (i, svc_value) in
709                                                        svc_array.iter().enumerate()
710                                                    {
711                                                        if let (Some(id), Some(endpoint)) = (
712                                                            svc_value
713                                                                .get("id")
714                                                                .and_then(|v| v.as_str()),
715                                                            svc_value
716                                                                .get("serviceEndpoint")
717                                                                .and_then(|v| v.as_str()),
718                                                        ) {
719                                                            let type_value = svc_value
720                                                                .get("type")
721                                                                .and_then(|v| v.as_str())
722                                                                .unwrap_or("Unknown");
723
724                                                            println!("  [{}] ID: {}", i + 1, id);
725                                                            println!("      Type: {}", type_value);
726                                                            println!(
727                                                                "      Endpoint: {}",
728                                                                endpoint
729                                                            );
730                                                        }
731                                                    }
732                                                }
733
734                                                // Create a simplified DID document with whatever we could extract
735                                                let simplified_doc = DIDDoc {
736                                                    id: doc_id,
737                                                    verification_method: verification_methods,
738                                                    authentication,
739                                                    key_agreement,
740                                                    assertion_method: Vec::new(),
741                                                    capability_invocation: Vec::new(),
742                                                    capability_delegation: Vec::new(),
743                                                    service: services,
744                                                };
745
746                                                Ok(Some(simplified_doc))
747                                            }
748                                            Err(_) => Err(Error::DIDResolution(format!(
749                                                "Failed to parse DID document from {}: {}",
750                                                url, parse_error
751                                            ))),
752                                        }
753                                    }
754                                }
755                            }
756                            Err(e) => Err(Error::DIDResolution(format!(
757                                "Failed to read response body from {}: {}",
758                                url, e
759                            ))),
760                        }
761                    } else if response.status().as_u16() == 404 {
762                        // Not found is a valid response, just return None
763                        Ok(None)
764                    } else {
765                        Err(Error::DIDResolution(format!(
766                            "HTTP error fetching DID document from {}: {}",
767                            url,
768                            response.status()
769                        )))
770                    }
771                }
772                Err(e) => Err(Error::DIDResolution(format!(
773                    "Failed to fetch DID document from {}: {}",
774                    url, e
775                ))),
776            }
777        }
778
779        #[cfg(target_arch = "wasm32")]
780        {
781            use wasm_bindgen::JsValue;
782            use wasm_bindgen_futures::JsFuture;
783            use web_sys::{Headers, Request, RequestInit, RequestMode, Response};
784
785            // Create request options
786            let mut opts = RequestInit::new();
787            opts.method("GET");
788            opts.mode(RequestMode::Cors);
789
790            // Create the request
791            let request = match Request::new_with_str_and_init(&url, &opts) {
792                Ok(req) => req,
793                Err(e) => {
794                    return Err(Error::DIDResolution(format!(
795                        "Failed to create request for {}: {:?}",
796                        url, e
797                    )));
798                }
799            };
800
801            // Add Accept header
802            let headers = match Headers::new() {
803                Ok(h) => h,
804                Err(e) => {
805                    return Err(Error::DIDResolution(format!(
806                        "Failed to create headers: {:?}",
807                        e
808                    )));
809                }
810            };
811
812            if let Err(e) = headers.set("Accept", "application/json") {
813                return Err(Error::DIDResolution(format!(
814                    "Failed to set Accept header: {:?}",
815                    e
816                )));
817            }
818
819            if let Err(e) = request.headers().set("Accept", "application/json") {
820                return Err(Error::DIDResolution(format!(
821                    "Failed to set Accept header: {:?}",
822                    e
823                )));
824            }
825
826            // Get the window object
827            let window = match web_sys::window() {
828                Some(w) => w,
829                None => {
830                    return Err(Error::DIDResolution(
831                        "No window object available".to_string(),
832                    ));
833                }
834            };
835
836            // Send the request
837            let resp_value = match JsFuture::from(window.fetch_with_request(&request)).await {
838                Ok(response) => response,
839                Err(e) => {
840                    return Err(Error::DIDResolution(format!(
841                        "Failed to fetch DID document from {}: {:?}",
842                        url, e
843                    )));
844                }
845            };
846
847            // Convert response to Response object
848            let resp: Response = match resp_value.dyn_into() {
849                Ok(r) => r,
850                Err(_) => {
851                    return Err(Error::DIDResolution(
852                        "Failed to convert response".to_string(),
853                    ));
854                }
855            };
856
857            // Check if successful
858            if resp.ok() {
859                // Get the text content
860                let text_promise = match resp.text() {
861                    Ok(t) => t,
862                    Err(e) => {
863                        return Err(Error::DIDResolution(format!(
864                            "Failed to get text from response: {:?}",
865                            e
866                        )));
867                    }
868                };
869
870                let text_jsval = match JsFuture::from(text_promise).await {
871                    Ok(t) => t,
872                    Err(e) => {
873                        return Err(Error::DIDResolution(format!(
874                            "Failed to await text promise: {:?}",
875                            e
876                        )));
877                    }
878                };
879
880                let text = match text_jsval.as_string() {
881                    Some(t) => t,
882                    None => {
883                        return Err(Error::DIDResolution("Response is not a string".to_string()));
884                    }
885                };
886
887                // Parse the DID document
888                match serde_json::from_str::<DIDDoc>(&text) {
889                    Ok(doc) => {
890                        // Validate that the document ID matches the requested DID
891                        if doc.id != did {
892                            return Err(Error::DIDResolution(format!(
893                                "DID Document ID ({}) does not match requested DID ({})",
894                                doc.id, did
895                            )));
896                        }
897                        Ok(Some(doc))
898                    }
899                    Err(parse_error) => {
900                        // If normal parsing fails, try to parse as a generic JSON Value
901                        // and manually construct a DIDDoc with the essential fields
902                        match serde_json::from_str::<serde_json::Value>(&text) {
903                            Ok(json_value) => {
904                                let doc_id = match json_value.get("id") {
905                                    Some(id) => match id.as_str() {
906                                        Some(id_str) => id_str.to_string(),
907                                        None => {
908                                            return Err(Error::DIDResolution(
909                                                "DID Document has invalid 'id' field".to_string(),
910                                            ))
911                                        }
912                                    },
913                                    None => {
914                                        return Err(Error::DIDResolution(
915                                            "DID Document missing 'id' field".to_string(),
916                                        ))
917                                    }
918                                };
919
920                                // Validate ID
921                                if doc_id != did {
922                                    return Err(Error::DIDResolution(format!(
923                                        "DID Document ID ({}) does not match requested DID ({})",
924                                        doc_id, did
925                                    )));
926                                }
927
928                                // Try to extract verification methods and other fields
929                                web_sys::console::log_1(&JsValue::from_str(
930                                    &format!("WARNING: Using partial DID document parsing due to format issues\nOriginal parse error: {}", parse_error)
931                                ));
932
933                                // Extract verification methods if present
934                                // Create a longer-lived empty vec to handle the None case
935                                let empty_vec = Vec::new();
936                                let vm_array = json_value
937                                    .get("verificationMethod")
938                                    .and_then(|v| v.as_array())
939                                    .unwrap_or(&empty_vec);
940
941                                // Attempt to parse each verification method
942                                let mut verification_methods = Vec::new();
943                                for vm_value in vm_array {
944                                    if let Ok(vm) = serde_json::from_value::<VerificationMethod>(
945                                        vm_value.clone(),
946                                    ) {
947                                        verification_methods.push(vm);
948                                    }
949                                }
950
951                                // Extract authentication references
952                                let authentication = json_value
953                                    .get("authentication")
954                                    .and_then(|v| v.as_array())
955                                    .unwrap_or(&empty_vec)
956                                    .iter()
957                                    .filter_map(|v| v.as_str().map(|s| s.to_string()))
958                                    .collect();
959
960                                // Extract key agreement references
961                                let key_agreement = json_value
962                                    .get("keyAgreement")
963                                    .and_then(|v| v.as_array())
964                                    .unwrap_or(&empty_vec)
965                                    .iter()
966                                    .filter_map(|v| v.as_str().map(|s| s.to_string()))
967                                    .collect();
968
969                                // Create an empty services list for the DIDDoc
970                                let services = Vec::new();
971
972                                // Extract raw service information for console logging
973                                if let Some(svc_array) =
974                                    json_value.get("service").and_then(|v| v.as_array())
975                                {
976                                    web_sys::console::log_1(&JsValue::from_str(
977                                        "Service endpoints (extracted from JSON):",
978                                    ));
979                                    for (i, svc_value) in svc_array.iter().enumerate() {
980                                        if let (Some(id), Some(endpoint)) = (
981                                            svc_value.get("id").and_then(|v| v.as_str()),
982                                            svc_value
983                                                .get("serviceEndpoint")
984                                                .and_then(|v| v.as_str()),
985                                        ) {
986                                            let type_value = svc_value
987                                                .get("type")
988                                                .and_then(|v| v.as_str())
989                                                .unwrap_or("Unknown");
990
991                                            web_sys::console::log_1(&JsValue::from_str(&format!(
992                                                "[{}] ID: {}\nType: {}\nEndpoint: {}",
993                                                i + 1,
994                                                id,
995                                                type_value,
996                                                endpoint
997                                            )));
998                                        }
999                                    }
1000                                }
1001
1002                                // Create a simplified DID document with whatever we could extract
1003                                let simplified_doc = DIDDoc {
1004                                    id: doc_id,
1005                                    verification_method: verification_methods,
1006                                    authentication,
1007                                    key_agreement,
1008                                    assertion_method: Vec::new(),
1009                                    capability_invocation: Vec::new(),
1010                                    capability_delegation: Vec::new(),
1011                                    service: services,
1012                                };
1013
1014                                Ok(Some(simplified_doc))
1015                            }
1016                            Err(_) => Err(Error::DIDResolution(format!(
1017                                "Failed to parse DID document from {}: {}",
1018                                url, parse_error
1019                            ))),
1020                        }
1021                    }
1022                }
1023            } else if resp.status() == 404 {
1024                // Not found is a valid response, just return None
1025                Ok(None)
1026            } else {
1027                Err(Error::DIDResolution(format!(
1028                    "HTTP error fetching DID document from {}: {}",
1029                    url,
1030                    resp.status()
1031                )))
1032            }
1033        }
1034
1035        #[cfg(all(not(target_arch = "wasm32"), not(feature = "native")))]
1036        {
1037            Err(Error::DIDResolution(
1038                "Web DID resolution requires the 'native' feature or WASM".to_string(),
1039            ))
1040        }
1041    }
1042}
1043
1044#[cfg(not(target_arch = "wasm32"))]
1045impl Default for MultiResolver {
1046    fn default() -> Self {
1047        let mut resolver = Self::new();
1048        resolver.register_method("key", KeyResolver::new());
1049        resolver.register_method("web", WebResolver::new());
1050        resolver
1051    }
1052}
1053
1054/// DID Key Generator for creating DIDs with different key types
1055#[derive(Debug, Default, Clone)]
1056pub struct DIDKeyGenerator;
1057
1058impl DIDKeyGenerator {
1059    /// Create a new DID key generator
1060    pub fn new() -> Self {
1061        Self
1062    }
1063
1064    /// Create a Secret from a GeneratedKey for a DID
1065    pub fn create_secret_from_key(&self, key: &GeneratedKey) -> Secret {
1066        match key.key_type {
1067            KeyType::Ed25519 => Secret {
1068                id: key.did.clone(),
1069                type_: SecretType::JsonWebKey2020,
1070                secret_material: SecretMaterial::JWK {
1071                    private_key_jwk: serde_json::json!({
1072                        "kty": "OKP",
1073                        "kid": key.did,
1074                        "crv": "Ed25519",
1075                        "x": base64::engine::general_purpose::STANDARD.encode(&key.public_key),
1076                        "d": base64::engine::general_purpose::STANDARD.encode(&key.private_key)
1077                    }),
1078                },
1079            },
1080            KeyType::P256 => Secret {
1081                id: key.did.clone(),
1082                type_: SecretType::JsonWebKey2020,
1083                secret_material: SecretMaterial::JWK {
1084                    private_key_jwk: serde_json::json!({
1085                        "kty": "EC",
1086                        "kid": key.did,
1087                        "crv": "P-256",
1088                        "x": base64::engine::general_purpose::STANDARD.encode(&key.public_key[0..32]),
1089                        "y": base64::engine::general_purpose::STANDARD.encode(&key.public_key[32..64]),
1090                        "d": base64::engine::general_purpose::STANDARD.encode(&key.private_key)
1091                    }),
1092                },
1093            },
1094            KeyType::Secp256k1 => Secret {
1095                id: key.did.clone(),
1096                type_: SecretType::JsonWebKey2020,
1097                secret_material: SecretMaterial::JWK {
1098                    private_key_jwk: serde_json::json!({
1099                        "kty": "EC",
1100                        "kid": key.did,
1101                        "crv": "secp256k1",
1102                        "x": base64::engine::general_purpose::STANDARD.encode(&key.public_key[0..32]),
1103                        "y": base64::engine::general_purpose::STANDARD.encode(&key.public_key[32..64]),
1104                        "d": base64::engine::general_purpose::STANDARD.encode(&key.private_key)
1105                    }),
1106                },
1107            },
1108        }
1109    }
1110
1111    /// Generate a did:key identifier with the specified key type
1112    pub fn generate_did(&self, options: DIDGenerationOptions) -> Result<GeneratedKey> {
1113        match options.key_type {
1114            KeyType::Ed25519 => self.generate_ed25519_did(),
1115            KeyType::P256 => self.generate_p256_did(),
1116            KeyType::Secp256k1 => self.generate_secp256k1_did(),
1117        }
1118    }
1119
1120    /// Generate a did:key identifier with an Ed25519 key
1121    pub fn generate_ed25519_did(&self) -> Result<GeneratedKey> {
1122        // Generate a new Ed25519 keypair
1123        let mut csprng = OsRng;
1124        let signing_key = Ed25519SigningKey::generate(&mut csprng);
1125        let verifying_key = Ed25519VerifyingKey::from(&signing_key);
1126
1127        // Extract public and private keys
1128        let public_key = verifying_key.to_bytes().to_vec();
1129        let private_key = signing_key.to_bytes().to_vec();
1130
1131        // Create did:key identifier
1132        // Multicodec prefix for Ed25519: 0xed01
1133        let mut prefixed_key = vec![0xed, 0x01];
1134        prefixed_key.extend_from_slice(&public_key);
1135
1136        // Encode the key with multibase (base58btc with 'z' prefix)
1137        let multibase_encoded = encode(Base::Base58Btc, &prefixed_key);
1138        let did = format!("did:key:{}", multibase_encoded);
1139
1140        // Create the DID document
1141        let doc = self.create_did_doc(&did, &prefixed_key, KeyType::Ed25519)?;
1142
1143        // Return the generated key information
1144        Ok(GeneratedKey {
1145            key_type: KeyType::Ed25519,
1146            did,
1147            public_key,
1148            private_key,
1149            did_doc: doc,
1150        })
1151    }
1152
1153    /// Generate a did:key identifier with a P-256 key
1154    pub fn generate_p256_did(&self) -> Result<GeneratedKey> {
1155        // Generate a new P-256 keypair
1156        let mut rng = OsRng;
1157        let signing_key = P256SigningKey::random(&mut rng);
1158
1159        // Extract public and private keys
1160        let private_key = signing_key.to_bytes().to_vec();
1161        let public_key = signing_key
1162            .verifying_key()
1163            .to_encoded_point(false)
1164            .to_bytes()
1165            .to_vec();
1166
1167        // Create did:key identifier
1168        // Multicodec prefix for P-256: 0x1200
1169        let mut prefixed_key = vec![0x12, 0x00];
1170        prefixed_key.extend_from_slice(&public_key);
1171
1172        // Encode the key with multibase (base58btc with 'z' prefix)
1173        let multibase_encoded = encode(Base::Base58Btc, &prefixed_key);
1174        let did = format!("did:key:{}", multibase_encoded);
1175
1176        // Create the DID document
1177        let doc = self.create_did_doc(&did, &prefixed_key, KeyType::P256)?;
1178
1179        // Return the generated key information
1180        Ok(GeneratedKey {
1181            key_type: KeyType::P256,
1182            did,
1183            public_key,
1184            private_key,
1185            did_doc: doc,
1186        })
1187    }
1188
1189    /// Generate a did:key identifier with a Secp256k1 key
1190    pub fn generate_secp256k1_did(&self) -> Result<GeneratedKey> {
1191        // Generate a new Secp256k1 keypair
1192        let mut rng = OsRng;
1193        let signing_key = Secp256k1SigningKey::random(&mut rng);
1194
1195        // Extract public and private keys
1196        let private_key = signing_key.to_bytes().to_vec();
1197        let public_key = signing_key
1198            .verifying_key()
1199            .to_encoded_point(false)
1200            .to_bytes()
1201            .to_vec();
1202
1203        // Create did:key identifier
1204        // Multicodec prefix for Secp256k1: 0xe701
1205        let mut prefixed_key = vec![0xe7, 0x01];
1206        prefixed_key.extend_from_slice(&public_key);
1207
1208        // Encode the key with multibase (base58btc with 'z' prefix)
1209        let multibase_encoded = encode(Base::Base58Btc, &prefixed_key);
1210        let did = format!("did:key:{}", multibase_encoded);
1211
1212        // Create the DID document
1213        let doc = self.create_did_doc(&did, &prefixed_key, KeyType::Secp256k1)?;
1214
1215        // Return the generated key information
1216        Ok(GeneratedKey {
1217            key_type: KeyType::Secp256k1,
1218            did,
1219            public_key,
1220            private_key,
1221            did_doc: doc,
1222        })
1223    }
1224
1225    /// Generate a did:web identifier with the given domain and key type
1226    pub fn generate_web_did(
1227        &self,
1228        domain: &str,
1229        options: DIDGenerationOptions,
1230    ) -> Result<GeneratedKey> {
1231        // First, generate a key DID of the appropriate type
1232        let key_did = self.generate_did(options)?;
1233
1234        // Format the did:web identifier
1235        let did = format!("did:web:{}", domain);
1236
1237        // Create a new DID document based on the key DID document but with the web DID
1238        let verification_methods: Vec<VerificationMethod> = key_did
1239            .did_doc
1240            .verification_method
1241            .iter()
1242            .map(|vm| {
1243                let id = format!("{}#keys-1", did);
1244                VerificationMethod {
1245                    id: id.clone(),
1246                    type_: vm.type_.clone(),
1247                    controller: did.clone(),
1248                    verification_material: vm.verification_material.clone(),
1249                }
1250            })
1251            .collect();
1252
1253        let did_doc = DIDDoc {
1254            id: did.clone(),
1255            verification_method: verification_methods.clone(),
1256            authentication: verification_methods
1257                .iter()
1258                .map(|vm| vm.id.clone())
1259                .collect(),
1260            key_agreement: key_did.did_doc.key_agreement,
1261            assertion_method: Vec::new(),
1262            capability_invocation: Vec::new(),
1263            capability_delegation: Vec::new(),
1264            service: vec![],
1265        };
1266
1267        // Return the generated key information with the web DID
1268        Ok(GeneratedKey {
1269            key_type: key_did.key_type,
1270            did,
1271            public_key: key_did.public_key,
1272            private_key: key_did.private_key,
1273            did_doc,
1274        })
1275    }
1276
1277    /// Create a DID document for a did:key
1278    fn create_did_doc(
1279        &self,
1280        did: &str,
1281        prefixed_public_key: &[u8],
1282        key_type: KeyType,
1283    ) -> Result<DIDDoc> {
1284        // Determine verification method type based on key type
1285        let verification_method_type = match key_type {
1286            KeyType::Ed25519 => VerificationMethodType::Ed25519VerificationKey2018,
1287            KeyType::P256 => VerificationMethodType::EcdsaSecp256k1VerificationKey2019, // Using Secp256k1 type as P256 isn't available
1288            KeyType::Secp256k1 => VerificationMethodType::EcdsaSecp256k1VerificationKey2019,
1289        };
1290
1291        // Encode the prefixed public key with multibase
1292        let multibase_encoded = encode(Base::Base58Btc, prefixed_public_key);
1293
1294        // Create the verification method ID
1295        let vm_id = format!("{}#{}", did, multibase_encoded);
1296
1297        // Create the verification method
1298        let verification_method = VerificationMethod {
1299            id: vm_id.clone(),
1300            type_: verification_method_type.clone(),
1301            controller: did.to_string(),
1302            verification_material: VerificationMaterial::Multibase {
1303                public_key_multibase: multibase_encoded.clone(),
1304            },
1305        };
1306
1307        // For Ed25519, also generate an X25519 verification method for key agreement
1308        let mut verification_methods = vec![verification_method.clone()];
1309        let mut key_agreement = Vec::new();
1310
1311        if key_type == KeyType::Ed25519 {
1312            // Only Ed25519 keys have an X25519 key agreement method
1313            if let Some(x25519_bytes) = self.ed25519_to_x25519(&prefixed_public_key[2..]) {
1314                // Prefix for X25519: 0xEC01
1315                let mut x25519_prefixed = vec![0xEC, 0x01];
1316                x25519_prefixed.extend_from_slice(&x25519_bytes);
1317
1318                // Encode the prefixed X25519 key with multibase
1319                let x25519_multibase = encode(Base::Base58Btc, &x25519_prefixed);
1320
1321                // Create the X25519 verification method ID
1322                let x25519_vm_id = format!("{}#{}", did, x25519_multibase);
1323
1324                // Create the X25519 verification method
1325                let x25519_verification_method = VerificationMethod {
1326                    id: x25519_vm_id.clone(),
1327                    type_: VerificationMethodType::X25519KeyAgreementKey2019,
1328                    controller: did.to_string(),
1329                    verification_material: VerificationMaterial::Multibase {
1330                        public_key_multibase: x25519_multibase,
1331                    },
1332                };
1333
1334                // Add the X25519 verification method and key agreement method
1335                verification_methods.push(x25519_verification_method);
1336                key_agreement.push(x25519_vm_id);
1337            }
1338        }
1339
1340        // Create the DID document
1341        let did_doc = DIDDoc {
1342            id: did.to_string(),
1343            verification_method: verification_methods,
1344            authentication: vec![vm_id.clone()],
1345            key_agreement,
1346            assertion_method: Vec::new(),
1347            capability_invocation: Vec::new(),
1348            capability_delegation: Vec::new(),
1349            service: vec![],
1350        };
1351
1352        Ok(did_doc)
1353    }
1354
1355    /// Convert an Ed25519 public key to an X25519 public key
1356    ///
1357    /// This follows the conversion process described in RFC 7748
1358    /// https://datatracker.ietf.org/doc/html/rfc7748#section-5
1359    fn ed25519_to_x25519(&self, ed25519_pubkey: &[u8]) -> Option<[u8; 32]> {
1360        // The Ed25519 public key should be 32 bytes
1361        if ed25519_pubkey.len() != 32 {
1362            return None;
1363        }
1364
1365        // Try to create a CompressedEdwardsY from the bytes
1366        let edwards_y = match CompressedEdwardsY::from_slice(ed25519_pubkey) {
1367            Ok(point) => point,
1368            Err(_) => return None,
1369        };
1370
1371        // Try to decompress to get the Edwards point
1372        let edwards_point = edwards_y.decompress()?;
1373
1374        // Convert to Montgomery form
1375        let montgomery_point = edwards_point.to_montgomery();
1376
1377        // Get the raw bytes representation of the X25519 key
1378        Some(montgomery_point.to_bytes())
1379    }
1380
1381    // The create_secret_from_key method has been moved up
1382}
1383
1384#[derive(Debug)]
1385#[cfg(target_arch = "wasm32")]
1386pub struct MultiResolver {
1387    // WASM-specific implementation with no thread-safety requirements
1388    resolvers: HashMap<String, Box<dyn WasmDIDMethodResolver>>,
1389}
1390
1391#[cfg(target_arch = "wasm32")]
1392impl MultiResolver {
1393    pub fn new() -> Self {
1394        Self {
1395            resolvers: HashMap::new(),
1396        }
1397    }
1398
1399    pub fn default() -> Self {
1400        let mut resolver = Self::new();
1401        // Add default resolvers
1402        resolver.add_resolver(Box::new(KeyResolver::new()));
1403        resolver
1404    }
1405
1406    pub fn add_resolver(&mut self, resolver: Box<dyn WasmDIDMethodResolver>) {
1407        self.resolvers
1408            .insert(resolver.method().to_string(), resolver);
1409    }
1410}
1411
1412#[cfg(target_arch = "wasm32")]
1413impl WasmDIDResolver for MultiResolver {
1414    fn resolve(&self, did: &str) -> Result<Option<DIDDoc>> {
1415        // Extract the DID method
1416        let parts: Vec<&str> = did.split(':').collect();
1417        if parts.len() < 3 {
1418            return Err(Error::InvalidDID);
1419        }
1420
1421        let method = parts[1];
1422
1423        // Get the resolver from the map
1424        if let Some(resolver) = self.resolvers.get(method) {
1425            resolver.resolve_method(did)
1426        } else {
1427            Err(Error::UnsupportedDIDMethod(format!(
1428                "Method {} is not a WasmDIDMethodResolver",
1429                method
1430            )))
1431        }
1432    }
1433}
1434
1435#[cfg(not(target_arch = "wasm32"))]
1436#[async_trait]
1437#[cfg(not(target_arch = "wasm32"))]
1438impl SyncDIDResolver for MultiResolver {
1439    async fn resolve(&self, did: &str) -> Result<Option<DIDDoc>> {
1440        // Extract the DID method
1441        let parts: Vec<&str> = did.split(':').collect();
1442        if parts.len() < 3 {
1443            return Err(Error::InvalidDID);
1444        }
1445
1446        let method = parts[1];
1447
1448        // Get the resolver from the map first
1449        let resolver = {
1450            let resolver_guard = self
1451                .resolvers
1452                .read()
1453                .map_err(|_| Error::FailedToAcquireResolverReadLock)?;
1454            if let Some(resolver) = resolver_guard.get(method) {
1455                resolver.clone()
1456            } else {
1457                return Err(Error::UnsupportedDIDMethod(method.to_string()));
1458            }
1459            // Lock is dropped here when resolver_guard goes out of scope
1460        };
1461
1462        // Now use the resolver without holding the lock
1463        resolver.resolve_method(did).await
1464    }
1465}
1466
1467// DIDResolver trait from didcomm is no longer needed since we've removed the didcomm dependency
1468
1469#[cfg(target_arch = "wasm32")]
1470use wasm_bindgen::prelude::*;
1471
1472#[cfg(target_arch = "wasm32")]
1473use js_sys::{Function, Promise};
1474
1475#[cfg(all(target_arch = "wasm32", feature = "wasm"))]
1476use wasm_bindgen_futures::JsFuture;
1477
1478#[cfg(target_arch = "wasm32")]
1479#[wasm_bindgen]
1480extern "C" {
1481    #[wasm_bindgen(typescript_type = "Promise<string>")]
1482    pub type JsPromiseString;
1483
1484    #[wasm_bindgen(typescript_type = "Promise<string | null>")]
1485    pub type JsPromiseStringOrNull;
1486}
1487
1488#[cfg(target_arch = "wasm32")]
1489#[wasm_bindgen]
1490pub struct JsDIDResolver {
1491    method: String,
1492    resolve_fn: Function,
1493}
1494
1495#[cfg(target_arch = "wasm32")]
1496#[wasm_bindgen]
1497impl JsDIDResolver {
1498    #[wasm_bindgen(constructor)]
1499    pub fn new(resolve_fn: Function) -> Self {
1500        Self {
1501            method: "".to_string(),
1502            resolve_fn,
1503        }
1504    }
1505
1506    #[wasm_bindgen]
1507    pub fn method(&self) -> String {
1508        // The JS resolver should return its method
1509        let this = JsValue::null();
1510        let method = self
1511            .resolve_fn
1512            .call1(&this, &JsValue::from_str("method"))
1513            .unwrap_or_else(|_| JsValue::from_str("unknown"));
1514
1515        method.as_string().unwrap_or_else(|| "unknown".to_string())
1516    }
1517}
1518
1519// This is a duplicate trait that conflicts with the one defined above
1520// So we're removing it here to avoid the conflict
1521
1522/// A wrapper for JavaScript DID resolvers.
1523#[cfg(target_arch = "wasm32")]
1524#[derive(Debug)]
1525pub struct JsDIDMethodResolver {
1526    method: String,
1527    resolve_fn: Function,
1528}
1529
1530#[cfg(target_arch = "wasm32")]
1531impl JsDIDMethodResolver {
1532    /// Create a new JavaScript DID method resolver from a function in the global context
1533    pub fn new(method: &str, resolve_fn: Function) -> Self {
1534        Self {
1535            method: method.to_string(),
1536            resolve_fn,
1537        }
1538    }
1539}
1540
1541#[cfg(target_arch = "wasm32")]
1542impl WasmDIDMethodResolver for JsDIDMethodResolver {
1543    fn method(&self) -> &str {
1544        &self.method
1545    }
1546
1547    fn as_any(&self) -> &dyn std::any::Any {
1548        self
1549    }
1550
1551    fn resolve_method(&self, did: &str) -> Result<Option<DIDDoc>> {
1552        // Ensure the DID is for the method that this resolver is for
1553        let parts: Vec<&str> = did.split(':').collect();
1554        if parts.len() < 3 || parts[1] != self.method {
1555            return Err(Error::InvalidDID);
1556        }
1557
1558        // In WASM target mode, we can't use async/await in this interface
1559        // This implementation is a simplified version that just returns None
1560        // The proper implementation would be in the JavaScript binding
1561        Err(Error::NotImplemented(
1562            "JS resolver not supported in this context".to_string(),
1563        ))
1564    }
1565
1566    #[cfg(not(feature = "wasm"))]
1567    async fn resolve_method(&self, _did: &str) -> Result<Option<DIDDoc>> {
1568        Err(Error::NotImplemented(
1569            "JavaScript DID Method resolver is only available with the 'wasm' feature".to_string(),
1570        ))
1571    }
1572}
1573
1574#[cfg(test)]
1575mod tests {
1576    use super::*;
1577
1578    #[cfg(feature = "native")]
1579    #[tokio::test]
1580    async fn test_key_resolver() {
1581        let resolver = KeyResolver::new();
1582
1583        // Test a valid did:key for Ed25519
1584        let did = "did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK";
1585        let result = resolver.resolve_method(did).await.unwrap();
1586
1587        assert!(result.is_some());
1588        let doc = result.unwrap();
1589
1590        assert_eq!(doc.id, did);
1591        assert_eq!(doc.verification_method.len(), 2); // Should have both Ed25519 and X25519 methods
1592
1593        // Verify Ed25519 verification method is present
1594        let ed25519_method = doc
1595            .verification_method
1596            .iter()
1597            .find(|vm| matches!(vm.type_, VerificationMethodType::Ed25519VerificationKey2018))
1598            .expect("Should have an Ed25519 verification method");
1599
1600        // Verify X25519 verification method
1601        let x25519_method = doc
1602            .verification_method
1603            .iter()
1604            .find(|vm| matches!(vm.type_, VerificationMethodType::X25519KeyAgreementKey2019))
1605            .expect("Should have an X25519 key agreement method");
1606
1607        // Check that authentication uses the Ed25519 key
1608        assert!(doc.authentication.contains(&ed25519_method.id));
1609
1610        // Check that key agreement uses the X25519 key
1611        assert!(doc.key_agreement.contains(&x25519_method.id));
1612    }
1613
1614    #[cfg(feature = "native")]
1615    #[tokio::test]
1616    async fn test_multi_resolver() {
1617        let resolver = MultiResolver::default();
1618
1619        // Test resolving a valid did:key
1620        let did = "did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK";
1621        let result = <MultiResolver as SyncDIDResolver>::resolve(&resolver, did).await;
1622
1623        assert!(result.is_ok());
1624        let doc_option = result.unwrap();
1625        assert!(doc_option.is_some());
1626
1627        let doc = doc_option.unwrap();
1628        assert_eq!(doc.id, did);
1629        assert_eq!(doc.verification_method.len(), 2); // Should have both Ed25519 and X25519 methods
1630
1631        // Test resolving an unsupported DID method
1632        let did = "did:unsupported:123";
1633        let result = <MultiResolver as SyncDIDResolver>::resolve(&resolver, did).await;
1634
1635        // This should return an error since it's an unsupported method
1636        assert!(result.is_err());
1637        let err = result.unwrap_err();
1638        assert!(err.to_string().contains("Unsupported DID method"));
1639    }
1640
1641    #[test]
1642    fn test_did_key_generator_ed25519() {
1643        let generator = DIDKeyGenerator::new();
1644
1645        // Generate an Ed25519 DID
1646        let options = DIDGenerationOptions {
1647            key_type: KeyType::Ed25519,
1648        };
1649
1650        let key_result = generator.generate_did(options);
1651        assert!(key_result.is_ok());
1652
1653        let key = key_result.unwrap();
1654
1655        // Check the DID format
1656        assert!(key.did.starts_with("did:key:z"));
1657
1658        // Check that public and private keys have the correct length
1659        assert_eq!(key.public_key.len(), 32); // Ed25519 public key is 32 bytes
1660        assert_eq!(key.private_key.len(), 32); // Ed25519 private key is 32 bytes
1661
1662        // Check the DID document
1663        assert_eq!(key.did_doc.id, key.did);
1664        assert_eq!(key.did_doc.verification_method.len(), 2); // Should have both Ed25519 and X25519
1665
1666        // Verify Ed25519 verification method is present
1667        let ed25519_method = key
1668            .did_doc
1669            .verification_method
1670            .iter()
1671            .find(|vm| matches!(vm.type_, VerificationMethodType::Ed25519VerificationKey2018))
1672            .expect("Should have an Ed25519 verification method");
1673
1674        // Verify X25519 verification method
1675        let x25519_method = key
1676            .did_doc
1677            .verification_method
1678            .iter()
1679            .find(|vm| matches!(vm.type_, VerificationMethodType::X25519KeyAgreementKey2019))
1680            .expect("Should have an X25519 key agreement method");
1681
1682        // Check that authentication uses the Ed25519 key
1683        assert!(key.did_doc.authentication.contains(&ed25519_method.id));
1684
1685        // Check that key agreement uses the X25519 key
1686        assert!(key.did_doc.key_agreement.contains(&x25519_method.id));
1687
1688        // Create a secret from the key
1689        let secret = generator.create_secret_from_key(&key);
1690        assert_eq!(secret.id, key.did);
1691        assert!(matches!(secret.type_, SecretType::JsonWebKey2020));
1692    }
1693
1694    #[test]
1695    fn test_did_key_generator_p256() {
1696        let generator = DIDKeyGenerator::new();
1697
1698        // Generate a P-256 DID
1699        let options = DIDGenerationOptions {
1700            key_type: KeyType::P256,
1701        };
1702
1703        let key_result = generator.generate_did(options);
1704        assert!(key_result.is_ok());
1705
1706        let key = key_result.unwrap();
1707
1708        // Check the DID format
1709        assert!(key.did.starts_with("did:key:z"));
1710
1711        // Check the DID document
1712        assert_eq!(key.did_doc.id, key.did);
1713        assert_eq!(key.did_doc.verification_method.len(), 1); // P-256 has no key agreement
1714
1715        // Verify P-256 verification method is present
1716        let p256_method = key
1717            .did_doc
1718            .verification_method
1719            .iter()
1720            .find(|vm| {
1721                matches!(
1722                    vm.type_,
1723                    VerificationMethodType::EcdsaSecp256k1VerificationKey2019
1724                )
1725            }) // Use available type
1726            .expect("Should have a P-256 verification method");
1727
1728        // Check that authentication uses the P-256 key
1729        assert!(key.did_doc.authentication.contains(&p256_method.id));
1730
1731        // Create a secret from the key
1732        let secret = generator.create_secret_from_key(&key);
1733        assert_eq!(secret.id, key.did);
1734        assert!(matches!(secret.type_, SecretType::JsonWebKey2020));
1735    }
1736
1737    #[test]
1738    fn test_did_key_generator_secp256k1() {
1739        let generator = DIDKeyGenerator::new();
1740
1741        // Generate a Secp256k1 DID
1742        let options = DIDGenerationOptions {
1743            key_type: KeyType::Secp256k1,
1744        };
1745
1746        let key_result = generator.generate_did(options);
1747        assert!(key_result.is_ok());
1748
1749        let key = key_result.unwrap();
1750
1751        // Check the DID format
1752        assert!(key.did.starts_with("did:key:z"));
1753
1754        // Check the DID document
1755        assert_eq!(key.did_doc.id, key.did);
1756        assert_eq!(key.did_doc.verification_method.len(), 1); // Secp256k1 has no key agreement
1757
1758        // Verify Secp256k1 verification method is present
1759        let secp256k1_method = key
1760            .did_doc
1761            .verification_method
1762            .iter()
1763            .find(|vm| {
1764                matches!(
1765                    vm.type_,
1766                    VerificationMethodType::EcdsaSecp256k1VerificationKey2019
1767                )
1768            })
1769            .expect("Should have a Secp256k1 verification method");
1770
1771        // Check that authentication uses the Secp256k1 key
1772        assert!(key.did_doc.authentication.contains(&secp256k1_method.id));
1773
1774        // Create a secret from the key
1775        let secret = generator.create_secret_from_key(&key);
1776        assert_eq!(secret.id, key.did);
1777        assert!(matches!(secret.type_, SecretType::JsonWebKey2020));
1778    }
1779
1780    #[test]
1781    fn test_did_web_generator() {
1782        let generator = DIDKeyGenerator::new();
1783
1784        // Generate a did:web
1785        let domain = "example.com";
1786        let options = DIDGenerationOptions {
1787            key_type: KeyType::Ed25519,
1788        };
1789
1790        let key_result = generator.generate_web_did(domain, options);
1791        assert!(key_result.is_ok());
1792
1793        let key = key_result.unwrap();
1794
1795        // Check the DID format
1796        assert_eq!(key.did, format!("did:web:{}", domain));
1797
1798        // Check the DID document
1799        assert_eq!(key.did_doc.id, key.did);
1800        assert!(!key.did_doc.verification_method.is_empty());
1801
1802        // Verify that all verification methods have the correct controller
1803        for vm in &key.did_doc.verification_method {
1804            assert_eq!(vm.controller, key.did);
1805            assert!(vm.id.starts_with(&key.did));
1806        }
1807
1808        // Create a secret from the key
1809        let secret = generator.create_secret_from_key(&key);
1810        assert_eq!(secret.id, key.did);
1811        assert!(matches!(secret.type_, SecretType::JsonWebKey2020));
1812    }
1813}