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        // Determine the proper key ID based on DID method
1067        let kid = if key.did.starts_with("did:key:") {
1068            // For did:key, the key ID is the DID + fragment matching the multibase
1069            // Get the first verification method's ID which has the proper format
1070            key.did_doc
1071                .verification_method
1072                .first()
1073                .map(|vm| vm.id.clone())
1074                .unwrap_or_else(|| {
1075                    // Fallback: extract the multibase part and construct the ID
1076                    let multibase = key.did.strip_prefix("did:key:").unwrap_or("");
1077                    format!("{}#{}", key.did, multibase)
1078                })
1079        } else if key.did.starts_with("did:web:") {
1080            // For did:web, use #keys-1
1081            format!("{}#keys-1", key.did)
1082        } else {
1083            // For other DID methods, use a generic pattern
1084            format!("{}#key-1", key.did)
1085        };
1086
1087        match key.key_type {
1088            KeyType::Ed25519 => Secret {
1089                id: key.did.clone(),
1090                type_: SecretType::JsonWebKey2020,
1091                secret_material: SecretMaterial::JWK {
1092                    private_key_jwk: serde_json::json!({
1093                        "kty": "OKP",
1094                        "kid": kid,
1095                        "crv": "Ed25519",
1096                        "x": base64::engine::general_purpose::STANDARD.encode(&key.public_key),
1097                        "d": base64::engine::general_purpose::STANDARD.encode(&key.private_key)
1098                    }),
1099                },
1100            },
1101            KeyType::P256 => Secret {
1102                id: key.did.clone(),
1103                type_: SecretType::JsonWebKey2020,
1104                secret_material: SecretMaterial::JWK {
1105                    private_key_jwk: serde_json::json!({
1106                        "kty": "EC",
1107                        "kid": kid,
1108                        "crv": "P-256",
1109                        "x": base64::engine::general_purpose::STANDARD.encode(&key.public_key[0..32]),
1110                        "y": base64::engine::general_purpose::STANDARD.encode(&key.public_key[32..64]),
1111                        "d": base64::engine::general_purpose::STANDARD.encode(&key.private_key)
1112                    }),
1113                },
1114            },
1115            KeyType::Secp256k1 => Secret {
1116                id: key.did.clone(),
1117                type_: SecretType::JsonWebKey2020,
1118                secret_material: SecretMaterial::JWK {
1119                    private_key_jwk: serde_json::json!({
1120                        "kty": "EC",
1121                        "kid": kid,
1122                        "crv": "secp256k1",
1123                        "x": base64::engine::general_purpose::STANDARD.encode(&key.public_key[0..32]),
1124                        "y": base64::engine::general_purpose::STANDARD.encode(&key.public_key[32..64]),
1125                        "d": base64::engine::general_purpose::STANDARD.encode(&key.private_key)
1126                    }),
1127                },
1128            },
1129        }
1130    }
1131
1132    /// Generate a did:key identifier with the specified key type
1133    pub fn generate_did(&self, options: DIDGenerationOptions) -> Result<GeneratedKey> {
1134        match options.key_type {
1135            KeyType::Ed25519 => self.generate_ed25519_did(),
1136            KeyType::P256 => self.generate_p256_did(),
1137            KeyType::Secp256k1 => self.generate_secp256k1_did(),
1138        }
1139    }
1140
1141    /// Generate a did:key identifier with an Ed25519 key
1142    pub fn generate_ed25519_did(&self) -> Result<GeneratedKey> {
1143        // Generate a new Ed25519 keypair
1144        let mut csprng = OsRng;
1145        let signing_key = Ed25519SigningKey::generate(&mut csprng);
1146        let verifying_key = Ed25519VerifyingKey::from(&signing_key);
1147
1148        // Extract public and private keys
1149        let public_key = verifying_key.to_bytes().to_vec();
1150        let private_key = signing_key.to_bytes().to_vec();
1151
1152        // Create did:key identifier
1153        // Multicodec prefix for Ed25519: 0xed01
1154        let mut prefixed_key = vec![0xed, 0x01];
1155        prefixed_key.extend_from_slice(&public_key);
1156
1157        // Encode the key with multibase (base58btc with 'z' prefix)
1158        let multibase_encoded = encode(Base::Base58Btc, &prefixed_key);
1159        let did = format!("did:key:{}", multibase_encoded);
1160
1161        // Create the DID document
1162        let doc = self.create_did_doc(&did, &prefixed_key, KeyType::Ed25519)?;
1163
1164        // Return the generated key information
1165        Ok(GeneratedKey {
1166            key_type: KeyType::Ed25519,
1167            did,
1168            public_key,
1169            private_key,
1170            did_doc: doc,
1171        })
1172    }
1173
1174    /// Generate a did:key identifier with a P-256 key
1175    pub fn generate_p256_did(&self) -> Result<GeneratedKey> {
1176        // Generate a new P-256 keypair
1177        let mut rng = OsRng;
1178        let signing_key = P256SigningKey::random(&mut rng);
1179
1180        // Extract public and private keys
1181        let private_key = signing_key.to_bytes().to_vec();
1182        let public_key = signing_key
1183            .verifying_key()
1184            .to_encoded_point(false)
1185            .to_bytes()
1186            .to_vec();
1187
1188        // Create did:key identifier
1189        // Multicodec prefix for P-256: 0x1200
1190        let mut prefixed_key = vec![0x12, 0x00];
1191        prefixed_key.extend_from_slice(&public_key);
1192
1193        // Encode the key with multibase (base58btc with 'z' prefix)
1194        let multibase_encoded = encode(Base::Base58Btc, &prefixed_key);
1195        let did = format!("did:key:{}", multibase_encoded);
1196
1197        // Create the DID document
1198        let doc = self.create_did_doc(&did, &prefixed_key, KeyType::P256)?;
1199
1200        // Return the generated key information
1201        Ok(GeneratedKey {
1202            key_type: KeyType::P256,
1203            did,
1204            public_key,
1205            private_key,
1206            did_doc: doc,
1207        })
1208    }
1209
1210    /// Generate a did:key identifier with a Secp256k1 key
1211    pub fn generate_secp256k1_did(&self) -> Result<GeneratedKey> {
1212        // Generate a new Secp256k1 keypair
1213        let mut rng = OsRng;
1214        let signing_key = Secp256k1SigningKey::random(&mut rng);
1215
1216        // Extract public and private keys
1217        let private_key = signing_key.to_bytes().to_vec();
1218        let public_key = signing_key
1219            .verifying_key()
1220            .to_encoded_point(false)
1221            .to_bytes()
1222            .to_vec();
1223
1224        // Create did:key identifier
1225        // Multicodec prefix for Secp256k1: 0xe701
1226        let mut prefixed_key = vec![0xe7, 0x01];
1227        prefixed_key.extend_from_slice(&public_key);
1228
1229        // Encode the key with multibase (base58btc with 'z' prefix)
1230        let multibase_encoded = encode(Base::Base58Btc, &prefixed_key);
1231        let did = format!("did:key:{}", multibase_encoded);
1232
1233        // Create the DID document
1234        let doc = self.create_did_doc(&did, &prefixed_key, KeyType::Secp256k1)?;
1235
1236        // Return the generated key information
1237        Ok(GeneratedKey {
1238            key_type: KeyType::Secp256k1,
1239            did,
1240            public_key,
1241            private_key,
1242            did_doc: doc,
1243        })
1244    }
1245
1246    /// Generate a did:web identifier with the given domain and key type
1247    pub fn generate_web_did(
1248        &self,
1249        domain: &str,
1250        options: DIDGenerationOptions,
1251    ) -> Result<GeneratedKey> {
1252        // First, generate a key DID of the appropriate type
1253        let key_did = self.generate_did(options)?;
1254
1255        // Format the did:web identifier
1256        let did = format!("did:web:{}", domain);
1257
1258        // Create a new DID document based on the key DID document but with the web DID
1259        let verification_methods: Vec<VerificationMethod> = key_did
1260            .did_doc
1261            .verification_method
1262            .iter()
1263            .map(|vm| {
1264                let id = format!("{}#keys-1", did);
1265                VerificationMethod {
1266                    id: id.clone(),
1267                    type_: vm.type_.clone(),
1268                    controller: did.clone(),
1269                    verification_material: vm.verification_material.clone(),
1270                }
1271            })
1272            .collect();
1273
1274        let did_doc = DIDDoc {
1275            id: did.clone(),
1276            verification_method: verification_methods.clone(),
1277            authentication: verification_methods
1278                .iter()
1279                .map(|vm| vm.id.clone())
1280                .collect(),
1281            key_agreement: key_did.did_doc.key_agreement,
1282            assertion_method: Vec::new(),
1283            capability_invocation: Vec::new(),
1284            capability_delegation: Vec::new(),
1285            service: vec![],
1286        };
1287
1288        // Return the generated key information with the web DID
1289        Ok(GeneratedKey {
1290            key_type: key_did.key_type,
1291            did,
1292            public_key: key_did.public_key,
1293            private_key: key_did.private_key,
1294            did_doc,
1295        })
1296    }
1297
1298    /// Create a DID document for a did:key
1299    fn create_did_doc(
1300        &self,
1301        did: &str,
1302        prefixed_public_key: &[u8],
1303        key_type: KeyType,
1304    ) -> Result<DIDDoc> {
1305        // Determine verification method type based on key type
1306        let verification_method_type = match key_type {
1307            KeyType::Ed25519 => VerificationMethodType::Ed25519VerificationKey2018,
1308            KeyType::P256 => VerificationMethodType::EcdsaSecp256k1VerificationKey2019, // Using Secp256k1 type as P256 isn't available
1309            KeyType::Secp256k1 => VerificationMethodType::EcdsaSecp256k1VerificationKey2019,
1310        };
1311
1312        // Encode the prefixed public key with multibase
1313        let multibase_encoded = encode(Base::Base58Btc, prefixed_public_key);
1314
1315        // Create the verification method ID
1316        let vm_id = format!("{}#{}", did, multibase_encoded);
1317
1318        // Create the verification method
1319        let verification_method = VerificationMethod {
1320            id: vm_id.clone(),
1321            type_: verification_method_type.clone(),
1322            controller: did.to_string(),
1323            verification_material: VerificationMaterial::Multibase {
1324                public_key_multibase: multibase_encoded.clone(),
1325            },
1326        };
1327
1328        // For Ed25519, also generate an X25519 verification method for key agreement
1329        let mut verification_methods = vec![verification_method.clone()];
1330        let mut key_agreement = Vec::new();
1331
1332        if key_type == KeyType::Ed25519 {
1333            // Only Ed25519 keys have an X25519 key agreement method
1334            if let Some(x25519_bytes) = self.ed25519_to_x25519(&prefixed_public_key[2..]) {
1335                // Prefix for X25519: 0xEC01
1336                let mut x25519_prefixed = vec![0xEC, 0x01];
1337                x25519_prefixed.extend_from_slice(&x25519_bytes);
1338
1339                // Encode the prefixed X25519 key with multibase
1340                let x25519_multibase = encode(Base::Base58Btc, &x25519_prefixed);
1341
1342                // Create the X25519 verification method ID
1343                let x25519_vm_id = format!("{}#{}", did, x25519_multibase);
1344
1345                // Create the X25519 verification method
1346                let x25519_verification_method = VerificationMethod {
1347                    id: x25519_vm_id.clone(),
1348                    type_: VerificationMethodType::X25519KeyAgreementKey2019,
1349                    controller: did.to_string(),
1350                    verification_material: VerificationMaterial::Multibase {
1351                        public_key_multibase: x25519_multibase,
1352                    },
1353                };
1354
1355                // Add the X25519 verification method and key agreement method
1356                verification_methods.push(x25519_verification_method);
1357                key_agreement.push(x25519_vm_id);
1358            }
1359        }
1360
1361        // Create the DID document
1362        let did_doc = DIDDoc {
1363            id: did.to_string(),
1364            verification_method: verification_methods,
1365            authentication: vec![vm_id.clone()],
1366            key_agreement,
1367            assertion_method: Vec::new(),
1368            capability_invocation: Vec::new(),
1369            capability_delegation: Vec::new(),
1370            service: vec![],
1371        };
1372
1373        Ok(did_doc)
1374    }
1375
1376    /// Convert an Ed25519 public key to an X25519 public key
1377    ///
1378    /// This follows the conversion process described in RFC 7748
1379    /// https://datatracker.ietf.org/doc/html/rfc7748#section-5
1380    fn ed25519_to_x25519(&self, ed25519_pubkey: &[u8]) -> Option<[u8; 32]> {
1381        // The Ed25519 public key should be 32 bytes
1382        if ed25519_pubkey.len() != 32 {
1383            return None;
1384        }
1385
1386        // Try to create a CompressedEdwardsY from the bytes
1387        let edwards_y = match CompressedEdwardsY::from_slice(ed25519_pubkey) {
1388            Ok(point) => point,
1389            Err(_) => return None,
1390        };
1391
1392        // Try to decompress to get the Edwards point
1393        let edwards_point = edwards_y.decompress()?;
1394
1395        // Convert to Montgomery form
1396        let montgomery_point = edwards_point.to_montgomery();
1397
1398        // Get the raw bytes representation of the X25519 key
1399        Some(montgomery_point.to_bytes())
1400    }
1401
1402    // The create_secret_from_key method has been moved up
1403}
1404
1405#[derive(Debug)]
1406#[cfg(target_arch = "wasm32")]
1407pub struct MultiResolver {
1408    // WASM-specific implementation with no thread-safety requirements
1409    resolvers: HashMap<String, Box<dyn WasmDIDMethodResolver>>,
1410}
1411
1412#[cfg(target_arch = "wasm32")]
1413impl MultiResolver {
1414    pub fn new() -> Self {
1415        Self {
1416            resolvers: HashMap::new(),
1417        }
1418    }
1419
1420    pub fn default() -> Self {
1421        let mut resolver = Self::new();
1422        // Add default resolvers
1423        resolver.add_resolver(Box::new(KeyResolver::new()));
1424        resolver
1425    }
1426
1427    pub fn add_resolver(&mut self, resolver: Box<dyn WasmDIDMethodResolver>) {
1428        self.resolvers
1429            .insert(resolver.method().to_string(), resolver);
1430    }
1431}
1432
1433#[cfg(target_arch = "wasm32")]
1434impl WasmDIDResolver for MultiResolver {
1435    fn resolve(&self, did: &str) -> Result<Option<DIDDoc>> {
1436        // Extract the DID method
1437        let parts: Vec<&str> = did.split(':').collect();
1438        if parts.len() < 3 {
1439            return Err(Error::InvalidDID);
1440        }
1441
1442        let method = parts[1];
1443
1444        // Get the resolver from the map
1445        if let Some(resolver) = self.resolvers.get(method) {
1446            resolver.resolve_method(did)
1447        } else {
1448            Err(Error::UnsupportedDIDMethod(format!(
1449                "Method {} is not a WasmDIDMethodResolver",
1450                method
1451            )))
1452        }
1453    }
1454}
1455
1456#[cfg(not(target_arch = "wasm32"))]
1457#[async_trait]
1458#[cfg(not(target_arch = "wasm32"))]
1459impl SyncDIDResolver for MultiResolver {
1460    async fn resolve(&self, did: &str) -> Result<Option<DIDDoc>> {
1461        // Extract the DID method
1462        let parts: Vec<&str> = did.split(':').collect();
1463        if parts.len() < 3 {
1464            return Err(Error::InvalidDID);
1465        }
1466
1467        let method = parts[1];
1468
1469        // Get the resolver from the map first
1470        let resolver = {
1471            let resolver_guard = self
1472                .resolvers
1473                .read()
1474                .map_err(|_| Error::FailedToAcquireResolverReadLock)?;
1475            if let Some(resolver) = resolver_guard.get(method) {
1476                resolver.clone()
1477            } else {
1478                return Err(Error::UnsupportedDIDMethod(method.to_string()));
1479            }
1480            // Lock is dropped here when resolver_guard goes out of scope
1481        };
1482
1483        // Now use the resolver without holding the lock
1484        resolver.resolve_method(did).await
1485    }
1486}
1487
1488// DIDResolver trait from didcomm is no longer needed since we've removed the didcomm dependency
1489
1490#[cfg(target_arch = "wasm32")]
1491use wasm_bindgen::prelude::*;
1492
1493#[cfg(target_arch = "wasm32")]
1494use js_sys::{Function, Promise};
1495
1496#[cfg(all(target_arch = "wasm32", feature = "wasm"))]
1497use wasm_bindgen_futures::JsFuture;
1498
1499#[cfg(target_arch = "wasm32")]
1500#[wasm_bindgen]
1501extern "C" {
1502    #[wasm_bindgen(typescript_type = "Promise<string>")]
1503    pub type JsPromiseString;
1504
1505    #[wasm_bindgen(typescript_type = "Promise<string | null>")]
1506    pub type JsPromiseStringOrNull;
1507}
1508
1509#[cfg(target_arch = "wasm32")]
1510#[wasm_bindgen]
1511pub struct JsDIDResolver {
1512    method: String,
1513    resolve_fn: Function,
1514}
1515
1516#[cfg(target_arch = "wasm32")]
1517#[wasm_bindgen]
1518impl JsDIDResolver {
1519    #[wasm_bindgen(constructor)]
1520    pub fn new(resolve_fn: Function) -> Self {
1521        Self {
1522            method: "".to_string(),
1523            resolve_fn,
1524        }
1525    }
1526
1527    #[wasm_bindgen]
1528    pub fn method(&self) -> String {
1529        // The JS resolver should return its method
1530        let this = JsValue::null();
1531        let method = self
1532            .resolve_fn
1533            .call1(&this, &JsValue::from_str("method"))
1534            .unwrap_or_else(|_| JsValue::from_str("unknown"));
1535
1536        method.as_string().unwrap_or_else(|| "unknown".to_string())
1537    }
1538}
1539
1540// This is a duplicate trait that conflicts with the one defined above
1541// So we're removing it here to avoid the conflict
1542
1543/// A wrapper for JavaScript DID resolvers.
1544#[cfg(target_arch = "wasm32")]
1545#[derive(Debug)]
1546pub struct JsDIDMethodResolver {
1547    method: String,
1548    resolve_fn: Function,
1549}
1550
1551#[cfg(target_arch = "wasm32")]
1552impl JsDIDMethodResolver {
1553    /// Create a new JavaScript DID method resolver from a function in the global context
1554    pub fn new(method: &str, resolve_fn: Function) -> Self {
1555        Self {
1556            method: method.to_string(),
1557            resolve_fn,
1558        }
1559    }
1560}
1561
1562#[cfg(target_arch = "wasm32")]
1563impl WasmDIDMethodResolver for JsDIDMethodResolver {
1564    fn method(&self) -> &str {
1565        &self.method
1566    }
1567
1568    fn as_any(&self) -> &dyn std::any::Any {
1569        self
1570    }
1571
1572    fn resolve_method(&self, did: &str) -> Result<Option<DIDDoc>> {
1573        // Ensure the DID is for the method that this resolver is for
1574        let parts: Vec<&str> = did.split(':').collect();
1575        if parts.len() < 3 || parts[1] != self.method {
1576            return Err(Error::InvalidDID);
1577        }
1578
1579        // In WASM target mode, we can't use async/await in this interface
1580        // This implementation is a simplified version that just returns None
1581        // The proper implementation would be in the JavaScript binding
1582        Err(Error::NotImplemented(
1583            "JS resolver not supported in this context".to_string(),
1584        ))
1585    }
1586
1587    #[cfg(not(feature = "wasm"))]
1588    async fn resolve_method(&self, _did: &str) -> Result<Option<DIDDoc>> {
1589        Err(Error::NotImplemented(
1590            "JavaScript DID Method resolver is only available with the 'wasm' feature".to_string(),
1591        ))
1592    }
1593}
1594
1595#[cfg(test)]
1596mod tests {
1597    use super::*;
1598
1599    #[cfg(feature = "native")]
1600    #[tokio::test]
1601    async fn test_key_resolver() {
1602        let resolver = KeyResolver::new();
1603
1604        // Test a valid did:key for Ed25519
1605        let did = "did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK";
1606        let result = resolver.resolve_method(did).await.unwrap();
1607
1608        assert!(result.is_some());
1609        let doc = result.unwrap();
1610
1611        assert_eq!(doc.id, did);
1612        assert_eq!(doc.verification_method.len(), 2); // Should have both Ed25519 and X25519 methods
1613
1614        // Verify Ed25519 verification method is present
1615        let ed25519_method = doc
1616            .verification_method
1617            .iter()
1618            .find(|vm| matches!(vm.type_, VerificationMethodType::Ed25519VerificationKey2018))
1619            .expect("Should have an Ed25519 verification method");
1620
1621        // Verify X25519 verification method
1622        let x25519_method = doc
1623            .verification_method
1624            .iter()
1625            .find(|vm| matches!(vm.type_, VerificationMethodType::X25519KeyAgreementKey2019))
1626            .expect("Should have an X25519 key agreement method");
1627
1628        // Check that authentication uses the Ed25519 key
1629        assert!(doc.authentication.contains(&ed25519_method.id));
1630
1631        // Check that key agreement uses the X25519 key
1632        assert!(doc.key_agreement.contains(&x25519_method.id));
1633    }
1634
1635    #[cfg(feature = "native")]
1636    #[tokio::test]
1637    async fn test_multi_resolver() {
1638        let resolver = MultiResolver::default();
1639
1640        // Test resolving a valid did:key
1641        let did = "did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK";
1642        let result = <MultiResolver as SyncDIDResolver>::resolve(&resolver, did).await;
1643
1644        assert!(result.is_ok());
1645        let doc_option = result.unwrap();
1646        assert!(doc_option.is_some());
1647
1648        let doc = doc_option.unwrap();
1649        assert_eq!(doc.id, did);
1650        assert_eq!(doc.verification_method.len(), 2); // Should have both Ed25519 and X25519 methods
1651
1652        // Test resolving an unsupported DID method
1653        let did = "did:unsupported:123";
1654        let result = <MultiResolver as SyncDIDResolver>::resolve(&resolver, did).await;
1655
1656        // This should return an error since it's an unsupported method
1657        assert!(result.is_err());
1658        let err = result.unwrap_err();
1659        assert!(err.to_string().contains("Unsupported DID method"));
1660    }
1661
1662    #[test]
1663    fn test_did_key_generator_ed25519() {
1664        let generator = DIDKeyGenerator::new();
1665
1666        // Generate an Ed25519 DID
1667        let options = DIDGenerationOptions {
1668            key_type: KeyType::Ed25519,
1669        };
1670
1671        let key_result = generator.generate_did(options);
1672        assert!(key_result.is_ok());
1673
1674        let key = key_result.unwrap();
1675
1676        // Check the DID format
1677        assert!(key.did.starts_with("did:key:z"));
1678
1679        // Check that public and private keys have the correct length
1680        assert_eq!(key.public_key.len(), 32); // Ed25519 public key is 32 bytes
1681        assert_eq!(key.private_key.len(), 32); // Ed25519 private key is 32 bytes
1682
1683        // Check the DID document
1684        assert_eq!(key.did_doc.id, key.did);
1685        assert_eq!(key.did_doc.verification_method.len(), 2); // Should have both Ed25519 and X25519
1686
1687        // Verify Ed25519 verification method is present
1688        let ed25519_method = key
1689            .did_doc
1690            .verification_method
1691            .iter()
1692            .find(|vm| matches!(vm.type_, VerificationMethodType::Ed25519VerificationKey2018))
1693            .expect("Should have an Ed25519 verification method");
1694
1695        // Verify X25519 verification method
1696        let x25519_method = key
1697            .did_doc
1698            .verification_method
1699            .iter()
1700            .find(|vm| matches!(vm.type_, VerificationMethodType::X25519KeyAgreementKey2019))
1701            .expect("Should have an X25519 key agreement method");
1702
1703        // Check that authentication uses the Ed25519 key
1704        assert!(key.did_doc.authentication.contains(&ed25519_method.id));
1705
1706        // Check that key agreement uses the X25519 key
1707        assert!(key.did_doc.key_agreement.contains(&x25519_method.id));
1708
1709        // Create a secret from the key
1710        let secret = generator.create_secret_from_key(&key);
1711        assert_eq!(secret.id, key.did);
1712        assert!(matches!(secret.type_, SecretType::JsonWebKey2020));
1713    }
1714
1715    #[test]
1716    fn test_did_key_generator_p256() {
1717        let generator = DIDKeyGenerator::new();
1718
1719        // Generate a P-256 DID
1720        let options = DIDGenerationOptions {
1721            key_type: KeyType::P256,
1722        };
1723
1724        let key_result = generator.generate_did(options);
1725        assert!(key_result.is_ok());
1726
1727        let key = key_result.unwrap();
1728
1729        // Check the DID format
1730        assert!(key.did.starts_with("did:key:z"));
1731
1732        // Check the DID document
1733        assert_eq!(key.did_doc.id, key.did);
1734        assert_eq!(key.did_doc.verification_method.len(), 1); // P-256 has no key agreement
1735
1736        // Verify P-256 verification method is present
1737        let p256_method = key
1738            .did_doc
1739            .verification_method
1740            .iter()
1741            .find(|vm| {
1742                matches!(
1743                    vm.type_,
1744                    VerificationMethodType::EcdsaSecp256k1VerificationKey2019
1745                )
1746            }) // Use available type
1747            .expect("Should have a P-256 verification method");
1748
1749        // Check that authentication uses the P-256 key
1750        assert!(key.did_doc.authentication.contains(&p256_method.id));
1751
1752        // Create a secret from the key
1753        let secret = generator.create_secret_from_key(&key);
1754        assert_eq!(secret.id, key.did);
1755        assert!(matches!(secret.type_, SecretType::JsonWebKey2020));
1756    }
1757
1758    #[test]
1759    fn test_did_key_generator_secp256k1() {
1760        let generator = DIDKeyGenerator::new();
1761
1762        // Generate a Secp256k1 DID
1763        let options = DIDGenerationOptions {
1764            key_type: KeyType::Secp256k1,
1765        };
1766
1767        let key_result = generator.generate_did(options);
1768        assert!(key_result.is_ok());
1769
1770        let key = key_result.unwrap();
1771
1772        // Check the DID format
1773        assert!(key.did.starts_with("did:key:z"));
1774
1775        // Check the DID document
1776        assert_eq!(key.did_doc.id, key.did);
1777        assert_eq!(key.did_doc.verification_method.len(), 1); // Secp256k1 has no key agreement
1778
1779        // Verify Secp256k1 verification method is present
1780        let secp256k1_method = key
1781            .did_doc
1782            .verification_method
1783            .iter()
1784            .find(|vm| {
1785                matches!(
1786                    vm.type_,
1787                    VerificationMethodType::EcdsaSecp256k1VerificationKey2019
1788                )
1789            })
1790            .expect("Should have a Secp256k1 verification method");
1791
1792        // Check that authentication uses the Secp256k1 key
1793        assert!(key.did_doc.authentication.contains(&secp256k1_method.id));
1794
1795        // Create a secret from the key
1796        let secret = generator.create_secret_from_key(&key);
1797        assert_eq!(secret.id, key.did);
1798        assert!(matches!(secret.type_, SecretType::JsonWebKey2020));
1799    }
1800
1801    #[test]
1802    fn test_did_web_generator() {
1803        let generator = DIDKeyGenerator::new();
1804
1805        // Generate a did:web
1806        let domain = "example.com";
1807        let options = DIDGenerationOptions {
1808            key_type: KeyType::Ed25519,
1809        };
1810
1811        let key_result = generator.generate_web_did(domain, options);
1812        assert!(key_result.is_ok());
1813
1814        let key = key_result.unwrap();
1815
1816        // Check the DID format
1817        assert_eq!(key.did, format!("did:web:{}", domain));
1818
1819        // Check the DID document
1820        assert_eq!(key.did_doc.id, key.did);
1821        assert!(!key.did_doc.verification_method.is_empty());
1822
1823        // Verify that all verification methods have the correct controller
1824        for vm in &key.did_doc.verification_method {
1825            assert_eq!(vm.controller, key.did);
1826            assert!(vm.id.starts_with(&key.did));
1827        }
1828
1829        // Create a secret from the key
1830        let secret = generator.create_secret_from_key(&key);
1831        assert_eq!(secret.id, key.did);
1832        assert!(matches!(secret.type_, SecretType::JsonWebKey2020));
1833    }
1834}