1use 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#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
29pub struct DIDDoc {
30 pub id: String,
32
33 pub verification_method: Vec<VerificationMethod>,
35
36 pub authentication: Vec<String>,
38
39 pub key_agreement: Vec<String>,
41
42 #[serde(default)]
44 pub assertion_method: Vec<String>,
45
46 #[serde(default)]
48 pub capability_invocation: Vec<String>,
49
50 #[serde(default)]
52 pub capability_delegation: Vec<String>,
53
54 pub service: Vec<Service>,
56}
57
58#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
60pub struct Service {
61 pub id: String,
63
64 #[serde(rename = "type")]
66 pub type_: String,
67
68 pub service_endpoint: String,
70
71 #[serde(flatten)]
73 pub properties: HashMap<String, Value>,
74}
75
76#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
78pub struct VerificationMethod {
79 pub id: String,
81
82 #[serde(rename = "type")]
84 pub type_: VerificationMethodType,
85
86 pub controller: String,
88
89 #[serde(flatten)]
91 pub verification_material: VerificationMaterial,
92}
93
94#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
96#[serde(rename_all = "camelCase")]
97pub enum VerificationMethodType {
98 Ed25519VerificationKey2018,
100
101 X25519KeyAgreementKey2019,
103
104 EcdsaSecp256k1VerificationKey2019,
106
107 JsonWebKey2020,
109}
110
111#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
113#[serde(untagged)]
114pub enum VerificationMaterial {
115 Base58 {
117 public_key_base58: String,
119 },
120
121 Multibase {
123 public_key_multibase: String,
125 },
126
127 JWK {
129 public_key_jwk: Value,
131 },
132}
133
134#[derive(Debug, Clone, Copy, PartialEq, Eq)]
136pub enum KeyType {
137 Ed25519,
139 P256,
141 Secp256k1,
143}
144
145#[derive(Debug, Clone)]
147pub struct GeneratedKey {
148 pub key_type: KeyType,
150 pub did: String,
152 pub public_key: Vec<u8>,
154 pub private_key: Vec<u8>,
156 pub did_doc: DIDDoc,
158}
159
160#[derive(Debug, Clone)]
162pub struct DIDGenerationOptions {
163 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#[cfg(not(target_arch = "wasm32"))]
178#[async_trait]
179pub trait SyncDIDResolver: Send + Sync + Debug {
180 async fn resolve(&self, did: &str) -> Result<Option<DIDDoc>>;
188}
189
190#[cfg(not(target_arch = "wasm32"))]
193#[async_trait]
194#[cfg(not(target_arch = "wasm32"))]
195pub trait DIDMethodResolver: Send + Sync + Debug {
196 fn method(&self) -> &str;
198
199 async fn resolve_method(&self, did: &str) -> Result<Option<DIDDoc>>;
207}
208
209#[cfg(target_arch = "wasm32")]
211pub trait WasmDIDResolver: Debug {
212 fn resolve(&self, did: &str) -> Result<Option<DIDDoc>>;
214}
215
216#[cfg(target_arch = "wasm32")]
218pub trait WasmDIDMethodResolver: Debug {
219 fn method(&self) -> &str;
221
222 fn resolve_method(&self, did: &str) -> Result<Option<DIDDoc>>;
224
225 fn as_any(&self) -> &dyn std::any::Any;
227}
228
229#[derive(Debug, Default)]
231pub struct KeyResolver;
232
233impl KeyResolver {
234 pub fn new() -> Self {
236 Self
237 }
238
239 fn ed25519_to_x25519(ed25519_pubkey: &[u8]) -> Option<[u8; 32]> {
244 if ed25519_pubkey.len() != 32 {
246 return None;
247 }
248
249 println!("Ed25519 pubkey: {:?}", ed25519_pubkey);
251
252 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 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 let montgomery_point = edwards_point.to_montgomery();
272
273 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 if !did_key.starts_with("did:key:") {
292 return Ok(None);
293 }
294
295 let key_id = &did_key[8..]; let (_, key_bytes) = match decode(key_id) {
298 Ok(result) => result,
299 Err(_) => return Ok(None),
300 };
301
302 if key_bytes.len() < 2 {
304 return Ok(None);
305 }
306
307 if key_bytes[0] != 0xED || key_bytes[1] != 0x01 {
309 return Ok(None);
310 }
311
312 let ed25519_public_key = &key_bytes[2..];
314
315 let ed_vm_id = format!("{}#{}", did_key, key_id);
316
317 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 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 let mut x25519_bytes = vec![0xEC, 0x01]; x25519_bytes.extend_from_slice(&x25519_key);
335 let x25519_multibase = encode(Base::Base58Btc, x25519_bytes);
336
337 let x25519_vm_id = format!("{}#{}", did_key, x25519_multibase);
339
340 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 verification_methods.push(x25519_verification_method);
352 key_agreement.push(x25519_vm_id);
353 }
354
355 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 if !did_key.starts_with("did:key:") {
381 return Ok(None);
382 }
383
384 let key_id = &did_key[8..]; let (_, key_bytes) = match decode(key_id) {
387 Ok(result) => result,
388 Err(_) => return Ok(None),
389 };
390
391 if key_bytes.len() < 2 {
393 return Ok(None);
394 }
395
396 if key_bytes[0] != 0xED || key_bytes[1] != 0x01 {
398 return Ok(None);
399 }
400
401 let ed25519_public_key = &key_bytes[2..];
403
404 let ed_vm_id = format!("{}#{}", did_key, key_id);
405
406 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 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 let mut x25519_bytes = vec![0xEC, 0x01]; x25519_bytes.extend_from_slice(&x25519_key);
425 let x25519_multibase = encode(Base::Base58Btc, x25519_bytes);
426
427 let x25519_vm_id = format!("{}#{}", did_key, x25519_multibase);
429
430 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 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 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#[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 pub fn new() -> Self {
480 Self {
481 resolvers: RwLock::new(HashMap::new()),
482 }
483 }
484
485 pub fn new_with_resolvers(resolvers: Vec<Arc<dyn DIDMethodResolver>>) -> Self {
487 let resolver = Self::new();
488
489 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 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#[derive(Debug, Default)]
514pub struct WebResolver;
515
516impl WebResolver {
517 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 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 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 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 let domain_path = parts[2..].join(":");
582 let domain_path = domain_path.replace("%3A", ":");
583
584 let url = if domain_path.contains(":") {
589 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 format!("https://{}/.well-known/did.json", domain_path)
597 };
598
599 #[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 let parse_result = serde_json::from_str::<DIDDoc>(&text);
612 match parse_result {
613 Ok(doc) => {
614 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 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 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 println!("WARNING: Using partial DID document parsing due to format issues");
654 println!("Original parse error: {}", parse_error);
655
656 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 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 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 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 let services = Vec::new();
701
702 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 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 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 let mut opts = RequestInit::new();
787 opts.method("GET");
788 opts.mode(RequestMode::Cors);
789
790 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 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 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 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 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 if resp.ok() {
859 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 match serde_json::from_str::<DIDDoc>(&text) {
889 Ok(doc) => {
890 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 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 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 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 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 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 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 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 let services = Vec::new();
971
972 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 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 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#[derive(Debug, Default, Clone)]
1056pub struct DIDKeyGenerator;
1057
1058impl DIDKeyGenerator {
1059 pub fn new() -> Self {
1061 Self
1062 }
1063
1064 pub fn create_secret_from_key(&self, key: &GeneratedKey) -> Secret {
1066 let kid = if key.did.starts_with("did:key:") {
1068 key.did_doc
1071 .verification_method
1072 .first()
1073 .map(|vm| vm.id.clone())
1074 .unwrap_or_else(|| {
1075 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 format!("{}#keys-1", key.did)
1082 } else {
1083 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 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 pub fn generate_ed25519_did(&self) -> Result<GeneratedKey> {
1143 let mut csprng = OsRng;
1145 let signing_key = Ed25519SigningKey::generate(&mut csprng);
1146 let verifying_key = Ed25519VerifyingKey::from(&signing_key);
1147
1148 let public_key = verifying_key.to_bytes().to_vec();
1150 let private_key = signing_key.to_bytes().to_vec();
1151
1152 let mut prefixed_key = vec![0xed, 0x01];
1155 prefixed_key.extend_from_slice(&public_key);
1156
1157 let multibase_encoded = encode(Base::Base58Btc, &prefixed_key);
1159 let did = format!("did:key:{}", multibase_encoded);
1160
1161 let doc = self.create_did_doc(&did, &prefixed_key, KeyType::Ed25519)?;
1163
1164 Ok(GeneratedKey {
1166 key_type: KeyType::Ed25519,
1167 did,
1168 public_key,
1169 private_key,
1170 did_doc: doc,
1171 })
1172 }
1173
1174 pub fn generate_p256_did(&self) -> Result<GeneratedKey> {
1176 let mut rng = OsRng;
1178 let signing_key = P256SigningKey::random(&mut rng);
1179
1180 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 let mut prefixed_key = vec![0x12, 0x00];
1191 prefixed_key.extend_from_slice(&public_key);
1192
1193 let multibase_encoded = encode(Base::Base58Btc, &prefixed_key);
1195 let did = format!("did:key:{}", multibase_encoded);
1196
1197 let doc = self.create_did_doc(&did, &prefixed_key, KeyType::P256)?;
1199
1200 Ok(GeneratedKey {
1202 key_type: KeyType::P256,
1203 did,
1204 public_key,
1205 private_key,
1206 did_doc: doc,
1207 })
1208 }
1209
1210 pub fn generate_secp256k1_did(&self) -> Result<GeneratedKey> {
1212 let mut rng = OsRng;
1214 let signing_key = Secp256k1SigningKey::random(&mut rng);
1215
1216 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 let mut prefixed_key = vec![0xe7, 0x01];
1227 prefixed_key.extend_from_slice(&public_key);
1228
1229 let multibase_encoded = encode(Base::Base58Btc, &prefixed_key);
1231 let did = format!("did:key:{}", multibase_encoded);
1232
1233 let doc = self.create_did_doc(&did, &prefixed_key, KeyType::Secp256k1)?;
1235
1236 Ok(GeneratedKey {
1238 key_type: KeyType::Secp256k1,
1239 did,
1240 public_key,
1241 private_key,
1242 did_doc: doc,
1243 })
1244 }
1245
1246 pub fn generate_web_did(
1248 &self,
1249 domain: &str,
1250 options: DIDGenerationOptions,
1251 ) -> Result<GeneratedKey> {
1252 let key_did = self.generate_did(options)?;
1254
1255 let did = format!("did:web:{}", domain);
1257
1258 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 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 fn create_did_doc(
1300 &self,
1301 did: &str,
1302 prefixed_public_key: &[u8],
1303 key_type: KeyType,
1304 ) -> Result<DIDDoc> {
1305 let verification_method_type = match key_type {
1307 KeyType::Ed25519 => VerificationMethodType::Ed25519VerificationKey2018,
1308 KeyType::P256 => VerificationMethodType::EcdsaSecp256k1VerificationKey2019, KeyType::Secp256k1 => VerificationMethodType::EcdsaSecp256k1VerificationKey2019,
1310 };
1311
1312 let multibase_encoded = encode(Base::Base58Btc, prefixed_public_key);
1314
1315 let vm_id = format!("{}#{}", did, multibase_encoded);
1317
1318 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 let mut verification_methods = vec![verification_method.clone()];
1330 let mut key_agreement = Vec::new();
1331
1332 if key_type == KeyType::Ed25519 {
1333 if let Some(x25519_bytes) = self.ed25519_to_x25519(&prefixed_public_key[2..]) {
1335 let mut x25519_prefixed = vec![0xEC, 0x01];
1337 x25519_prefixed.extend_from_slice(&x25519_bytes);
1338
1339 let x25519_multibase = encode(Base::Base58Btc, &x25519_prefixed);
1341
1342 let x25519_vm_id = format!("{}#{}", did, x25519_multibase);
1344
1345 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 verification_methods.push(x25519_verification_method);
1357 key_agreement.push(x25519_vm_id);
1358 }
1359 }
1360
1361 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 fn ed25519_to_x25519(&self, ed25519_pubkey: &[u8]) -> Option<[u8; 32]> {
1381 if ed25519_pubkey.len() != 32 {
1383 return None;
1384 }
1385
1386 let edwards_y = match CompressedEdwardsY::from_slice(ed25519_pubkey) {
1388 Ok(point) => point,
1389 Err(_) => return None,
1390 };
1391
1392 let edwards_point = edwards_y.decompress()?;
1394
1395 let montgomery_point = edwards_point.to_montgomery();
1397
1398 Some(montgomery_point.to_bytes())
1400 }
1401
1402 }
1404
1405#[derive(Debug)]
1406#[cfg(target_arch = "wasm32")]
1407pub struct MultiResolver {
1408 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 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 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 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 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 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 };
1482
1483 resolver.resolve_method(did).await
1485 }
1486}
1487
1488#[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 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#[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 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 let parts: Vec<&str> = did.split(':').collect();
1575 if parts.len() < 3 || parts[1] != self.method {
1576 return Err(Error::InvalidDID);
1577 }
1578
1579 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 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); 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 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 assert!(doc.authentication.contains(&ed25519_method.id));
1630
1631 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 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); let did = "did:unsupported:123";
1654 let result = <MultiResolver as SyncDIDResolver>::resolve(&resolver, did).await;
1655
1656 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 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 assert!(key.did.starts_with("did:key:z"));
1678
1679 assert_eq!(key.public_key.len(), 32); assert_eq!(key.private_key.len(), 32); assert_eq!(key.did_doc.id, key.did);
1685 assert_eq!(key.did_doc.verification_method.len(), 2); 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 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 assert!(key.did_doc.authentication.contains(&ed25519_method.id));
1705
1706 assert!(key.did_doc.key_agreement.contains(&x25519_method.id));
1708
1709 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 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 assert!(key.did.starts_with("did:key:z"));
1731
1732 assert_eq!(key.did_doc.id, key.did);
1734 assert_eq!(key.did_doc.verification_method.len(), 1); 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 }) .expect("Should have a P-256 verification method");
1748
1749 assert!(key.did_doc.authentication.contains(&p256_method.id));
1751
1752 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 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 assert!(key.did.starts_with("did:key:z"));
1774
1775 assert_eq!(key.did_doc.id, key.did);
1777 assert_eq!(key.did_doc.verification_method.len(), 1); 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 assert!(key.did_doc.authentication.contains(&secp256k1_method.id));
1794
1795 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 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 assert_eq!(key.did, format!("did:web:{}", domain));
1818
1819 assert_eq!(key.did_doc.id, key.did);
1821 assert!(!key.did_doc.verification_method.is_empty());
1822
1823 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 let secret = generator.create_secret_from_key(&key);
1831 assert_eq!(secret.id, key.did);
1832 assert!(matches!(secret.type_, SecretType::JsonWebKey2020));
1833 }
1834}