credibil_did/key/
resolver.rs1use std::sync::LazyLock;
13
14use regex::Regex;
15use serde_json::json;
16
17use super::DidKey;
18use crate::document::{CreateOptions, MethodType};
19use crate::error::Error;
20use crate::resolution::{ContentType, Metadata, Resolved};
21use crate::{DidOperator, KeyPurpose, PublicKeyJwk};
22
23static DID_REGEX: LazyLock<Regex> = LazyLock::new(|| {
24 Regex::new("^did:key:(?<identifier>z[a-km-zA-HJ-NP-Z1-9]+)$").expect("should compile")
25});
26
27struct Operator(MethodType);
28impl DidOperator for Operator {
29 fn verification(&self, purpose: KeyPurpose) -> Option<PublicKeyJwk> {
30 match purpose {
31 KeyPurpose::VerificationMethod => self.0.jwk().ok(),
32 _ => panic!("unsupported purpose"),
33 }
34 }
35}
36
37impl DidKey {
38 pub fn resolve(did: &str) -> crate::Result<Resolved> {
44 let Some(caps) = DID_REGEX.captures(did) else {
46 return Err(Error::InvalidDid("DID is not a valid did:key".into()));
47 };
48 let multikey = &caps["identifier"];
49
50 let op = Operator(MethodType::Multikey {
51 public_key_multibase: multikey.to_string(),
52 });
53
54 let options = CreateOptions {
56 enable_encryption_key_derivation: true,
57 ..CreateOptions::default()
58 };
59
60 let document = Self::create(&op, options).map_err(|e| Error::InvalidDid(e.to_string()))?;
61
62 Ok(Resolved {
63 context: "https://w3id.org/did-resolution/v1".into(),
64 metadata: Metadata {
65 content_type: ContentType::DidLdJson,
66 additional: Some(json!({
67 "pattern": "^did:key:z[a-km-zA-HJ-NP-Z1-9]+$",
68 "did": {
69 "didString": did,
70 "methodSpecificId": did[8..],
71 "method": "key"
72 }
73 })),
74 ..Metadata::default()
75 },
76 document: Some(document),
77 ..Resolved::default()
78 })
79 }
80}
81
82#[cfg(test)]
83mod test {
84 use super::*;
85
86 const DID: &str = "did:key:z6Mkj8Jr1rg3YjVWWhg7ahEYJibqhjBgZt1pDCbT4Lv7D4HX";
88
89 #[tokio::test]
90 async fn resolve() {
91 let resolved = DidKey::resolve(DID).expect("should resolve");
92 println!("{}", serde_json::to_string_pretty(&resolved).unwrap());
93 }
95}