typesec_integrations/did/
document.rs1use std::collections::HashMap;
4
5use serde::{Deserialize, Serialize};
6
7use super::crypto::{hex_decode, hex_encode};
8use super::error::DidError;
9use super::identifier::Did;
10
11#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
13pub struct VerificationMethod {
14 pub id: String,
16 #[serde(rename = "type")]
18 pub method_type: String,
19 pub controller: Did,
21 pub public_key_hex: String,
23 #[serde(default, skip_serializing_if = "Option::is_none")]
25 pub key_version: Option<u64>,
26 #[serde(default, skip_serializing_if = "Option::is_none")]
28 pub key_status: Option<String>,
29}
30
31impl VerificationMethod {
32 pub fn local(id: impl Into<String>, controller: Did, public_key: impl AsRef<[u8]>) -> Self {
34 Self {
35 id: id.into(),
36 method_type: "TypesecDemoKey2026".to_owned(),
37 controller,
38 public_key_hex: hex_encode(public_key.as_ref()),
39 key_version: None,
40 key_status: None,
41 }
42 }
43
44 pub(super) fn public_key(&self) -> Result<Vec<u8>, DidError> {
45 hex_decode(&self.public_key_hex)
46 }
47}
48
49#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
51pub struct DidService {
52 pub id: String,
54 #[serde(rename = "type")]
56 pub service_type: String,
57 pub service_endpoint: String,
59}
60
61#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
63pub struct DidDocument {
64 pub id: Did,
66 #[serde(default)]
68 pub verification_method: Vec<VerificationMethod>,
69 #[serde(default)]
71 pub authentication: Vec<String>,
72 #[serde(default)]
74 pub key_agreement: Vec<String>,
75 #[serde(default)]
77 pub service: Vec<DidService>,
78}
79
80impl DidDocument {
81 pub fn single_key(did: Did, public_key: impl AsRef<[u8]>) -> Self {
83 let key_id = format!("{did}#key-1");
84 Self {
85 id: did.clone(),
86 verification_method: vec![VerificationMethod::local(&key_id, did, public_key)],
87 authentication: vec![key_id.clone()],
88 key_agreement: vec![key_id],
89 service: Vec::new(),
90 }
91 }
92
93 pub fn with_signing_and_agreement_keys(
98 did: Did,
99 signing_public: impl AsRef<[u8]>,
100 agreement_public: impl AsRef<[u8]>,
101 ) -> Self {
102 let signing_id = format!("{did}#key-1");
103 let agreement_id = format!("{did}#key-2");
104 Self {
105 id: did.clone(),
106 verification_method: vec![
107 VerificationMethod {
108 id: signing_id.clone(),
109 method_type: "Ed25519VerificationKey2020".to_owned(),
110 controller: did.clone(),
111 public_key_hex: hex_encode(signing_public.as_ref()),
112 key_version: Some(1),
113 key_status: Some("active".to_owned()),
114 },
115 VerificationMethod {
116 id: agreement_id.clone(),
117 method_type: "X25519KeyAgreementKey2020".to_owned(),
118 controller: did,
119 public_key_hex: hex_encode(agreement_public.as_ref()),
120 key_version: Some(1),
121 key_status: Some("active".to_owned()),
122 },
123 ],
124 authentication: vec![signing_id],
125 key_agreement: vec![agreement_id],
126 service: Vec::new(),
127 }
128 }
129
130 fn method(&self, id: &str) -> Option<&VerificationMethod> {
131 self.verification_method
132 .iter()
133 .find(|method| method.id == id)
134 }
135
136 pub(super) fn authentication_key(&self, kid: &str) -> Result<&VerificationMethod, DidError> {
137 if !self.authentication.iter().any(|id| id == kid) {
138 return Err(DidError::MissingVerificationMethod(kid.to_owned()));
139 }
140 self.method(kid)
141 .ok_or_else(|| DidError::MissingVerificationMethod(kid.to_owned()))
142 }
143
144 pub(super) fn key_agreement_key(&self) -> Result<&VerificationMethod, DidError> {
145 let kid = self
146 .key_agreement
147 .first()
148 .ok_or(DidError::MissingKeyAgreement)?;
149 self.method(kid)
150 .ok_or_else(|| DidError::MissingVerificationMethod(kid.clone()))
151 }
152
153 pub(super) fn key_agreement_keys(&self) -> Result<Vec<&VerificationMethod>, DidError> {
154 if self.key_agreement.is_empty() {
155 return Err(DidError::MissingKeyAgreement);
156 }
157
158 self.key_agreement
159 .iter()
160 .map(|kid| {
161 self.method(kid)
162 .ok_or_else(|| DidError::MissingVerificationMethod(kid.clone()))
163 })
164 .collect()
165 }
166}
167
168pub trait DidResolver: Send + Sync {
170 fn resolve(&self, did: &Did) -> Result<DidDocument, DidError>;
172}
173
174#[derive(Debug, Default, Clone)]
176pub struct StaticDidResolver {
177 documents: HashMap<Did, DidDocument>,
178}
179
180impl StaticDidResolver {
181 pub fn new() -> Self {
183 Self::default()
184 }
185
186 pub fn with_document(mut self, document: DidDocument) -> Self {
188 self.documents.insert(document.id.clone(), document);
189 self
190 }
191}
192
193impl DidResolver for StaticDidResolver {
194 fn resolve(&self, did: &Did) -> Result<DidDocument, DidError> {
195 self.documents
196 .get(did)
197 .cloned()
198 .ok_or_else(|| DidError::Unresolved(did.to_string()))
199 }
200}