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 match key.key_type {
1067 KeyType::Ed25519 => Secret {
1068 id: key.did.clone(),
1069 type_: SecretType::JsonWebKey2020,
1070 secret_material: SecretMaterial::JWK {
1071 private_key_jwk: serde_json::json!({
1072 "kty": "OKP",
1073 "kid": key.did,
1074 "crv": "Ed25519",
1075 "x": base64::engine::general_purpose::STANDARD.encode(&key.public_key),
1076 "d": base64::engine::general_purpose::STANDARD.encode(&key.private_key)
1077 }),
1078 },
1079 },
1080 KeyType::P256 => Secret {
1081 id: key.did.clone(),
1082 type_: SecretType::JsonWebKey2020,
1083 secret_material: SecretMaterial::JWK {
1084 private_key_jwk: serde_json::json!({
1085 "kty": "EC",
1086 "kid": key.did,
1087 "crv": "P-256",
1088 "x": base64::engine::general_purpose::STANDARD.encode(&key.public_key[0..32]),
1089 "y": base64::engine::general_purpose::STANDARD.encode(&key.public_key[32..64]),
1090 "d": base64::engine::general_purpose::STANDARD.encode(&key.private_key)
1091 }),
1092 },
1093 },
1094 KeyType::Secp256k1 => Secret {
1095 id: key.did.clone(),
1096 type_: SecretType::JsonWebKey2020,
1097 secret_material: SecretMaterial::JWK {
1098 private_key_jwk: serde_json::json!({
1099 "kty": "EC",
1100 "kid": key.did,
1101 "crv": "secp256k1",
1102 "x": base64::engine::general_purpose::STANDARD.encode(&key.public_key[0..32]),
1103 "y": base64::engine::general_purpose::STANDARD.encode(&key.public_key[32..64]),
1104 "d": base64::engine::general_purpose::STANDARD.encode(&key.private_key)
1105 }),
1106 },
1107 },
1108 }
1109 }
1110
1111 pub fn generate_did(&self, options: DIDGenerationOptions) -> Result<GeneratedKey> {
1113 match options.key_type {
1114 KeyType::Ed25519 => self.generate_ed25519_did(),
1115 KeyType::P256 => self.generate_p256_did(),
1116 KeyType::Secp256k1 => self.generate_secp256k1_did(),
1117 }
1118 }
1119
1120 pub fn generate_ed25519_did(&self) -> Result<GeneratedKey> {
1122 let mut csprng = OsRng;
1124 let signing_key = Ed25519SigningKey::generate(&mut csprng);
1125 let verifying_key = Ed25519VerifyingKey::from(&signing_key);
1126
1127 let public_key = verifying_key.to_bytes().to_vec();
1129 let private_key = signing_key.to_bytes().to_vec();
1130
1131 let mut prefixed_key = vec![0xed, 0x01];
1134 prefixed_key.extend_from_slice(&public_key);
1135
1136 let multibase_encoded = encode(Base::Base58Btc, &prefixed_key);
1138 let did = format!("did:key:{}", multibase_encoded);
1139
1140 let doc = self.create_did_doc(&did, &prefixed_key, KeyType::Ed25519)?;
1142
1143 Ok(GeneratedKey {
1145 key_type: KeyType::Ed25519,
1146 did,
1147 public_key,
1148 private_key,
1149 did_doc: doc,
1150 })
1151 }
1152
1153 pub fn generate_p256_did(&self) -> Result<GeneratedKey> {
1155 let mut rng = OsRng;
1157 let signing_key = P256SigningKey::random(&mut rng);
1158
1159 let private_key = signing_key.to_bytes().to_vec();
1161 let public_key = signing_key
1162 .verifying_key()
1163 .to_encoded_point(false)
1164 .to_bytes()
1165 .to_vec();
1166
1167 let mut prefixed_key = vec![0x12, 0x00];
1170 prefixed_key.extend_from_slice(&public_key);
1171
1172 let multibase_encoded = encode(Base::Base58Btc, &prefixed_key);
1174 let did = format!("did:key:{}", multibase_encoded);
1175
1176 let doc = self.create_did_doc(&did, &prefixed_key, KeyType::P256)?;
1178
1179 Ok(GeneratedKey {
1181 key_type: KeyType::P256,
1182 did,
1183 public_key,
1184 private_key,
1185 did_doc: doc,
1186 })
1187 }
1188
1189 pub fn generate_secp256k1_did(&self) -> Result<GeneratedKey> {
1191 let mut rng = OsRng;
1193 let signing_key = Secp256k1SigningKey::random(&mut rng);
1194
1195 let private_key = signing_key.to_bytes().to_vec();
1197 let public_key = signing_key
1198 .verifying_key()
1199 .to_encoded_point(false)
1200 .to_bytes()
1201 .to_vec();
1202
1203 let mut prefixed_key = vec![0xe7, 0x01];
1206 prefixed_key.extend_from_slice(&public_key);
1207
1208 let multibase_encoded = encode(Base::Base58Btc, &prefixed_key);
1210 let did = format!("did:key:{}", multibase_encoded);
1211
1212 let doc = self.create_did_doc(&did, &prefixed_key, KeyType::Secp256k1)?;
1214
1215 Ok(GeneratedKey {
1217 key_type: KeyType::Secp256k1,
1218 did,
1219 public_key,
1220 private_key,
1221 did_doc: doc,
1222 })
1223 }
1224
1225 pub fn generate_web_did(
1227 &self,
1228 domain: &str,
1229 options: DIDGenerationOptions,
1230 ) -> Result<GeneratedKey> {
1231 let key_did = self.generate_did(options)?;
1233
1234 let did = format!("did:web:{}", domain);
1236
1237 let verification_methods: Vec<VerificationMethod> = key_did
1239 .did_doc
1240 .verification_method
1241 .iter()
1242 .map(|vm| {
1243 let id = format!("{}#keys-1", did);
1244 VerificationMethod {
1245 id: id.clone(),
1246 type_: vm.type_.clone(),
1247 controller: did.clone(),
1248 verification_material: vm.verification_material.clone(),
1249 }
1250 })
1251 .collect();
1252
1253 let did_doc = DIDDoc {
1254 id: did.clone(),
1255 verification_method: verification_methods.clone(),
1256 authentication: verification_methods
1257 .iter()
1258 .map(|vm| vm.id.clone())
1259 .collect(),
1260 key_agreement: key_did.did_doc.key_agreement,
1261 assertion_method: Vec::new(),
1262 capability_invocation: Vec::new(),
1263 capability_delegation: Vec::new(),
1264 service: vec![],
1265 };
1266
1267 Ok(GeneratedKey {
1269 key_type: key_did.key_type,
1270 did,
1271 public_key: key_did.public_key,
1272 private_key: key_did.private_key,
1273 did_doc,
1274 })
1275 }
1276
1277 fn create_did_doc(
1279 &self,
1280 did: &str,
1281 prefixed_public_key: &[u8],
1282 key_type: KeyType,
1283 ) -> Result<DIDDoc> {
1284 let verification_method_type = match key_type {
1286 KeyType::Ed25519 => VerificationMethodType::Ed25519VerificationKey2018,
1287 KeyType::P256 => VerificationMethodType::EcdsaSecp256k1VerificationKey2019, KeyType::Secp256k1 => VerificationMethodType::EcdsaSecp256k1VerificationKey2019,
1289 };
1290
1291 let multibase_encoded = encode(Base::Base58Btc, prefixed_public_key);
1293
1294 let vm_id = format!("{}#{}", did, multibase_encoded);
1296
1297 let verification_method = VerificationMethod {
1299 id: vm_id.clone(),
1300 type_: verification_method_type.clone(),
1301 controller: did.to_string(),
1302 verification_material: VerificationMaterial::Multibase {
1303 public_key_multibase: multibase_encoded.clone(),
1304 },
1305 };
1306
1307 let mut verification_methods = vec![verification_method.clone()];
1309 let mut key_agreement = Vec::new();
1310
1311 if key_type == KeyType::Ed25519 {
1312 if let Some(x25519_bytes) = self.ed25519_to_x25519(&prefixed_public_key[2..]) {
1314 let mut x25519_prefixed = vec![0xEC, 0x01];
1316 x25519_prefixed.extend_from_slice(&x25519_bytes);
1317
1318 let x25519_multibase = encode(Base::Base58Btc, &x25519_prefixed);
1320
1321 let x25519_vm_id = format!("{}#{}", did, x25519_multibase);
1323
1324 let x25519_verification_method = VerificationMethod {
1326 id: x25519_vm_id.clone(),
1327 type_: VerificationMethodType::X25519KeyAgreementKey2019,
1328 controller: did.to_string(),
1329 verification_material: VerificationMaterial::Multibase {
1330 public_key_multibase: x25519_multibase,
1331 },
1332 };
1333
1334 verification_methods.push(x25519_verification_method);
1336 key_agreement.push(x25519_vm_id);
1337 }
1338 }
1339
1340 let did_doc = DIDDoc {
1342 id: did.to_string(),
1343 verification_method: verification_methods,
1344 authentication: vec![vm_id.clone()],
1345 key_agreement,
1346 assertion_method: Vec::new(),
1347 capability_invocation: Vec::new(),
1348 capability_delegation: Vec::new(),
1349 service: vec![],
1350 };
1351
1352 Ok(did_doc)
1353 }
1354
1355 fn ed25519_to_x25519(&self, ed25519_pubkey: &[u8]) -> Option<[u8; 32]> {
1360 if ed25519_pubkey.len() != 32 {
1362 return None;
1363 }
1364
1365 let edwards_y = match CompressedEdwardsY::from_slice(ed25519_pubkey) {
1367 Ok(point) => point,
1368 Err(_) => return None,
1369 };
1370
1371 let edwards_point = edwards_y.decompress()?;
1373
1374 let montgomery_point = edwards_point.to_montgomery();
1376
1377 Some(montgomery_point.to_bytes())
1379 }
1380
1381 }
1383
1384#[derive(Debug)]
1385#[cfg(target_arch = "wasm32")]
1386pub struct MultiResolver {
1387 resolvers: HashMap<String, Box<dyn WasmDIDMethodResolver>>,
1389}
1390
1391#[cfg(target_arch = "wasm32")]
1392impl MultiResolver {
1393 pub fn new() -> Self {
1394 Self {
1395 resolvers: HashMap::new(),
1396 }
1397 }
1398
1399 pub fn default() -> Self {
1400 let mut resolver = Self::new();
1401 resolver.add_resolver(Box::new(KeyResolver::new()));
1403 resolver
1404 }
1405
1406 pub fn add_resolver(&mut self, resolver: Box<dyn WasmDIDMethodResolver>) {
1407 self.resolvers
1408 .insert(resolver.method().to_string(), resolver);
1409 }
1410}
1411
1412#[cfg(target_arch = "wasm32")]
1413impl WasmDIDResolver for MultiResolver {
1414 fn resolve(&self, did: &str) -> Result<Option<DIDDoc>> {
1415 let parts: Vec<&str> = did.split(':').collect();
1417 if parts.len() < 3 {
1418 return Err(Error::InvalidDID);
1419 }
1420
1421 let method = parts[1];
1422
1423 if let Some(resolver) = self.resolvers.get(method) {
1425 resolver.resolve_method(did)
1426 } else {
1427 Err(Error::UnsupportedDIDMethod(format!(
1428 "Method {} is not a WasmDIDMethodResolver",
1429 method
1430 )))
1431 }
1432 }
1433}
1434
1435#[cfg(not(target_arch = "wasm32"))]
1436#[async_trait]
1437#[cfg(not(target_arch = "wasm32"))]
1438impl SyncDIDResolver for MultiResolver {
1439 async fn resolve(&self, did: &str) -> Result<Option<DIDDoc>> {
1440 let parts: Vec<&str> = did.split(':').collect();
1442 if parts.len() < 3 {
1443 return Err(Error::InvalidDID);
1444 }
1445
1446 let method = parts[1];
1447
1448 let resolver = {
1450 let resolver_guard = self
1451 .resolvers
1452 .read()
1453 .map_err(|_| Error::FailedToAcquireResolverReadLock)?;
1454 if let Some(resolver) = resolver_guard.get(method) {
1455 resolver.clone()
1456 } else {
1457 return Err(Error::UnsupportedDIDMethod(method.to_string()));
1458 }
1459 };
1461
1462 resolver.resolve_method(did).await
1464 }
1465}
1466
1467#[cfg(target_arch = "wasm32")]
1470use wasm_bindgen::prelude::*;
1471
1472#[cfg(target_arch = "wasm32")]
1473use js_sys::{Function, Promise};
1474
1475#[cfg(all(target_arch = "wasm32", feature = "wasm"))]
1476use wasm_bindgen_futures::JsFuture;
1477
1478#[cfg(target_arch = "wasm32")]
1479#[wasm_bindgen]
1480extern "C" {
1481 #[wasm_bindgen(typescript_type = "Promise<string>")]
1482 pub type JsPromiseString;
1483
1484 #[wasm_bindgen(typescript_type = "Promise<string | null>")]
1485 pub type JsPromiseStringOrNull;
1486}
1487
1488#[cfg(target_arch = "wasm32")]
1489#[wasm_bindgen]
1490pub struct JsDIDResolver {
1491 method: String,
1492 resolve_fn: Function,
1493}
1494
1495#[cfg(target_arch = "wasm32")]
1496#[wasm_bindgen]
1497impl JsDIDResolver {
1498 #[wasm_bindgen(constructor)]
1499 pub fn new(resolve_fn: Function) -> Self {
1500 Self {
1501 method: "".to_string(),
1502 resolve_fn,
1503 }
1504 }
1505
1506 #[wasm_bindgen]
1507 pub fn method(&self) -> String {
1508 let this = JsValue::null();
1510 let method = self
1511 .resolve_fn
1512 .call1(&this, &JsValue::from_str("method"))
1513 .unwrap_or_else(|_| JsValue::from_str("unknown"));
1514
1515 method.as_string().unwrap_or_else(|| "unknown".to_string())
1516 }
1517}
1518
1519#[cfg(target_arch = "wasm32")]
1524#[derive(Debug)]
1525pub struct JsDIDMethodResolver {
1526 method: String,
1527 resolve_fn: Function,
1528}
1529
1530#[cfg(target_arch = "wasm32")]
1531impl JsDIDMethodResolver {
1532 pub fn new(method: &str, resolve_fn: Function) -> Self {
1534 Self {
1535 method: method.to_string(),
1536 resolve_fn,
1537 }
1538 }
1539}
1540
1541#[cfg(target_arch = "wasm32")]
1542impl WasmDIDMethodResolver for JsDIDMethodResolver {
1543 fn method(&self) -> &str {
1544 &self.method
1545 }
1546
1547 fn as_any(&self) -> &dyn std::any::Any {
1548 self
1549 }
1550
1551 fn resolve_method(&self, did: &str) -> Result<Option<DIDDoc>> {
1552 let parts: Vec<&str> = did.split(':').collect();
1554 if parts.len() < 3 || parts[1] != self.method {
1555 return Err(Error::InvalidDID);
1556 }
1557
1558 Err(Error::NotImplemented(
1562 "JS resolver not supported in this context".to_string(),
1563 ))
1564 }
1565
1566 #[cfg(not(feature = "wasm"))]
1567 async fn resolve_method(&self, _did: &str) -> Result<Option<DIDDoc>> {
1568 Err(Error::NotImplemented(
1569 "JavaScript DID Method resolver is only available with the 'wasm' feature".to_string(),
1570 ))
1571 }
1572}
1573
1574#[cfg(test)]
1575mod tests {
1576 use super::*;
1577
1578 #[cfg(feature = "native")]
1579 #[tokio::test]
1580 async fn test_key_resolver() {
1581 let resolver = KeyResolver::new();
1582
1583 let did = "did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK";
1585 let result = resolver.resolve_method(did).await.unwrap();
1586
1587 assert!(result.is_some());
1588 let doc = result.unwrap();
1589
1590 assert_eq!(doc.id, did);
1591 assert_eq!(doc.verification_method.len(), 2); let ed25519_method = doc
1595 .verification_method
1596 .iter()
1597 .find(|vm| matches!(vm.type_, VerificationMethodType::Ed25519VerificationKey2018))
1598 .expect("Should have an Ed25519 verification method");
1599
1600 let x25519_method = doc
1602 .verification_method
1603 .iter()
1604 .find(|vm| matches!(vm.type_, VerificationMethodType::X25519KeyAgreementKey2019))
1605 .expect("Should have an X25519 key agreement method");
1606
1607 assert!(doc.authentication.contains(&ed25519_method.id));
1609
1610 assert!(doc.key_agreement.contains(&x25519_method.id));
1612 }
1613
1614 #[cfg(feature = "native")]
1615 #[tokio::test]
1616 async fn test_multi_resolver() {
1617 let resolver = MultiResolver::default();
1618
1619 let did = "did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK";
1621 let result = <MultiResolver as SyncDIDResolver>::resolve(&resolver, did).await;
1622
1623 assert!(result.is_ok());
1624 let doc_option = result.unwrap();
1625 assert!(doc_option.is_some());
1626
1627 let doc = doc_option.unwrap();
1628 assert_eq!(doc.id, did);
1629 assert_eq!(doc.verification_method.len(), 2); let did = "did:unsupported:123";
1633 let result = <MultiResolver as SyncDIDResolver>::resolve(&resolver, did).await;
1634
1635 assert!(result.is_err());
1637 let err = result.unwrap_err();
1638 assert!(err.to_string().contains("Unsupported DID method"));
1639 }
1640
1641 #[test]
1642 fn test_did_key_generator_ed25519() {
1643 let generator = DIDKeyGenerator::new();
1644
1645 let options = DIDGenerationOptions {
1647 key_type: KeyType::Ed25519,
1648 };
1649
1650 let key_result = generator.generate_did(options);
1651 assert!(key_result.is_ok());
1652
1653 let key = key_result.unwrap();
1654
1655 assert!(key.did.starts_with("did:key:z"));
1657
1658 assert_eq!(key.public_key.len(), 32); assert_eq!(key.private_key.len(), 32); assert_eq!(key.did_doc.id, key.did);
1664 assert_eq!(key.did_doc.verification_method.len(), 2); let ed25519_method = key
1668 .did_doc
1669 .verification_method
1670 .iter()
1671 .find(|vm| matches!(vm.type_, VerificationMethodType::Ed25519VerificationKey2018))
1672 .expect("Should have an Ed25519 verification method");
1673
1674 let x25519_method = key
1676 .did_doc
1677 .verification_method
1678 .iter()
1679 .find(|vm| matches!(vm.type_, VerificationMethodType::X25519KeyAgreementKey2019))
1680 .expect("Should have an X25519 key agreement method");
1681
1682 assert!(key.did_doc.authentication.contains(&ed25519_method.id));
1684
1685 assert!(key.did_doc.key_agreement.contains(&x25519_method.id));
1687
1688 let secret = generator.create_secret_from_key(&key);
1690 assert_eq!(secret.id, key.did);
1691 assert!(matches!(secret.type_, SecretType::JsonWebKey2020));
1692 }
1693
1694 #[test]
1695 fn test_did_key_generator_p256() {
1696 let generator = DIDKeyGenerator::new();
1697
1698 let options = DIDGenerationOptions {
1700 key_type: KeyType::P256,
1701 };
1702
1703 let key_result = generator.generate_did(options);
1704 assert!(key_result.is_ok());
1705
1706 let key = key_result.unwrap();
1707
1708 assert!(key.did.starts_with("did:key:z"));
1710
1711 assert_eq!(key.did_doc.id, key.did);
1713 assert_eq!(key.did_doc.verification_method.len(), 1); let p256_method = key
1717 .did_doc
1718 .verification_method
1719 .iter()
1720 .find(|vm| {
1721 matches!(
1722 vm.type_,
1723 VerificationMethodType::EcdsaSecp256k1VerificationKey2019
1724 )
1725 }) .expect("Should have a P-256 verification method");
1727
1728 assert!(key.did_doc.authentication.contains(&p256_method.id));
1730
1731 let secret = generator.create_secret_from_key(&key);
1733 assert_eq!(secret.id, key.did);
1734 assert!(matches!(secret.type_, SecretType::JsonWebKey2020));
1735 }
1736
1737 #[test]
1738 fn test_did_key_generator_secp256k1() {
1739 let generator = DIDKeyGenerator::new();
1740
1741 let options = DIDGenerationOptions {
1743 key_type: KeyType::Secp256k1,
1744 };
1745
1746 let key_result = generator.generate_did(options);
1747 assert!(key_result.is_ok());
1748
1749 let key = key_result.unwrap();
1750
1751 assert!(key.did.starts_with("did:key:z"));
1753
1754 assert_eq!(key.did_doc.id, key.did);
1756 assert_eq!(key.did_doc.verification_method.len(), 1); let secp256k1_method = key
1760 .did_doc
1761 .verification_method
1762 .iter()
1763 .find(|vm| {
1764 matches!(
1765 vm.type_,
1766 VerificationMethodType::EcdsaSecp256k1VerificationKey2019
1767 )
1768 })
1769 .expect("Should have a Secp256k1 verification method");
1770
1771 assert!(key.did_doc.authentication.contains(&secp256k1_method.id));
1773
1774 let secret = generator.create_secret_from_key(&key);
1776 assert_eq!(secret.id, key.did);
1777 assert!(matches!(secret.type_, SecretType::JsonWebKey2020));
1778 }
1779
1780 #[test]
1781 fn test_did_web_generator() {
1782 let generator = DIDKeyGenerator::new();
1783
1784 let domain = "example.com";
1786 let options = DIDGenerationOptions {
1787 key_type: KeyType::Ed25519,
1788 };
1789
1790 let key_result = generator.generate_web_did(domain, options);
1791 assert!(key_result.is_ok());
1792
1793 let key = key_result.unwrap();
1794
1795 assert_eq!(key.did, format!("did:web:{}", domain));
1797
1798 assert_eq!(key.did_doc.id, key.did);
1800 assert!(!key.did_doc.verification_method.is_empty());
1801
1802 for vm in &key.did_doc.verification_method {
1804 assert_eq!(vm.controller, key.did);
1805 assert!(vm.id.starts_with(&key.did));
1806 }
1807
1808 let secret = generator.create_secret_from_key(&key);
1810 assert_eq!(secret.id, key.did);
1811 assert!(matches!(secret.type_, SecretType::JsonWebKey2020));
1812 }
1813}