1use serde::{Deserialize, Serialize};
12
13#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
21#[serde(untagged)]
22pub enum DidController {
23 One(String),
24 Many(Vec<String>),
25}
26
27impl DidController {
28 pub fn iter(&self) -> impl Iterator<Item = &str> {
30 match self {
31 Self::One(s) => std::slice::from_ref(s).iter().map(String::as_str),
32 Self::Many(v) => v.iter().map(String::as_str),
33 }
34 }
35
36 pub fn contains(&self, did: &str) -> bool {
38 self.iter().any(|d| d == did)
39 }
40}
41
42impl From<String> for DidController {
43 fn from(s: String) -> Self {
44 Self::One(s)
45 }
46}
47
48impl From<Vec<String>> for DidController {
49 fn from(v: Vec<String>) -> Self {
50 if v.len() == 1 {
51 Self::One(v.into_iter().next().unwrap())
52 } else {
53 Self::Many(v)
54 }
55 }
56}
57
58#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
67pub struct VerificationMethod {
68 pub id: String,
70
71 #[serde(rename = "type")]
78 pub typ: String,
79
80 pub controller: String,
82
83 #[serde(rename = "publicKeyJwk", skip_serializing_if = "Option::is_none")]
85 pub public_key_jwk: Option<serde_json::Map<String, serde_json::Value>>,
86
87 #[serde(rename = "publicKeyMultibase", skip_serializing_if = "Option::is_none")]
91 pub public_key_multibase: Option<String>,
92}
93
94impl VerificationMethod {
95 pub fn ed25519_jwk(
97 id: impl Into<String>,
98 controller: impl Into<String>,
99 key_bytes: &[u8],
100 ) -> Self {
101 use base64::Engine;
102 let x = base64::engine::general_purpose::URL_SAFE_NO_PAD.encode(key_bytes);
103 let mut jwk = serde_json::Map::new();
104 jwk.insert("kty".to_string(), "OKP".into());
105 jwk.insert("crv".to_string(), "Ed25519".into());
106 jwk.insert("x".to_string(), x.into());
107 Self {
108 id: id.into(),
109 typ: "JsonWebKey2020".to_string(),
110 controller: controller.into(),
111 public_key_jwk: Some(jwk),
112 public_key_multibase: None,
113 }
114 }
115
116 pub fn x25519_jwk(
118 id: impl Into<String>,
119 controller: impl Into<String>,
120 key_bytes: &[u8],
121 ) -> Self {
122 use base64::Engine;
123 let x = base64::engine::general_purpose::URL_SAFE_NO_PAD.encode(key_bytes);
124 let mut jwk = serde_json::Map::new();
125 jwk.insert("kty".to_string(), "OKP".into());
126 jwk.insert("crv".to_string(), "X25519".into());
127 jwk.insert("x".to_string(), x.into());
128 Self {
129 id: id.into(),
130 typ: "JsonWebKey2020".to_string(),
131 controller: controller.into(),
132 public_key_jwk: Some(jwk),
133 public_key_multibase: None,
134 }
135 }
136
137 pub fn ed25519_key_bytes(&self) -> Option<[u8; 32]> {
139 use base64::Engine;
140 let jwk = self.public_key_jwk.as_ref()?;
141 if jwk.get("crv").and_then(|v| v.as_str()) != Some("Ed25519") {
142 return None;
143 }
144 let x = jwk.get("x")?.as_str()?;
145 let bytes = base64::engine::general_purpose::URL_SAFE_NO_PAD
146 .decode(x)
147 .ok()?;
148 if bytes.len() != 32 {
149 return None;
150 }
151 let mut arr = [0u8; 32];
152 arr.copy_from_slice(&bytes);
153 Some(arr)
154 }
155
156 pub fn x25519_key_bytes(&self) -> Option<[u8; 32]> {
158 use base64::Engine;
159 let jwk = self.public_key_jwk.as_ref()?;
160 if jwk.get("crv").and_then(|v| v.as_str()) != Some("X25519") {
161 return None;
162 }
163 let x = jwk.get("x")?.as_str()?;
164 let bytes = base64::engine::general_purpose::URL_SAFE_NO_PAD
165 .decode(x)
166 .ok()?;
167 if bytes.len() != 32 {
168 return None;
169 }
170 let mut arr = [0u8; 32];
171 arr.copy_from_slice(&bytes);
172 Some(arr)
173 }
174}
175
176#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
184#[serde(untagged)]
185pub enum VerificationRef {
186 Reference(String),
187 Embedded(VerificationMethod),
188}
189
190impl VerificationRef {
191 pub fn id(&self) -> &str {
193 match self {
194 Self::Reference(s) => s.as_str(),
195 Self::Embedded(vm) => vm.id.as_str(),
196 }
197 }
198}
199
200#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
207pub struct Service {
208 pub id: String,
210
211 #[serde(rename = "type")]
213 pub typ: String,
214
215 #[serde(rename = "serviceEndpoint")]
217 pub service_endpoint: ServiceEndpoint,
218}
219
220#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
222#[serde(untagged)]
223pub enum ServiceEndpoint {
224 Uri(String),
226 Map(serde_json::Map<String, serde_json::Value>),
228 Set(Vec<ServiceEndpoint>),
230}
231
232#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
242pub struct DidDocument {
243 #[serde(rename = "@context")]
245 pub context: Vec<String>,
246
247 pub id: String,
249
250 #[serde(skip_serializing_if = "Option::is_none")]
253 pub controller: Option<DidController>,
254
255 #[serde(
258 rename = "verificationMethod",
259 default,
260 skip_serializing_if = "Vec::is_empty"
261 )]
262 pub verification_methods: Vec<VerificationMethod>,
263
264 #[serde(default, skip_serializing_if = "Vec::is_empty")]
266 pub authentication: Vec<VerificationRef>,
267
268 #[serde(
271 rename = "assertionMethod",
272 default,
273 skip_serializing_if = "Vec::is_empty"
274 )]
275 pub assertion_method: Vec<VerificationRef>,
276
277 #[serde(
282 rename = "keyAgreement",
283 default,
284 skip_serializing_if = "Vec::is_empty"
285 )]
286 pub key_agreement: Vec<VerificationRef>,
287
288 #[serde(
293 rename = "capabilityInvocation",
294 default,
295 skip_serializing_if = "Vec::is_empty"
296 )]
297 pub capability_invocation: Vec<VerificationRef>,
298
299 #[serde(
301 rename = "capabilityDelegation",
302 default,
303 skip_serializing_if = "Vec::is_empty"
304 )]
305 pub capability_delegation: Vec<VerificationRef>,
306
307 #[serde(default, skip_serializing_if = "Vec::is_empty")]
309 pub service: Vec<Service>,
310
311 #[serde(rename = "alsoKnownAs", default, skip_serializing_if = "Vec::is_empty")]
314 pub also_known_as: Vec<String>,
315}
316
317impl DidDocument {
318 pub fn new_simple(
320 did: impl Into<String>,
321 key_id: impl Into<String>,
322 public_key: &[u8],
323 ) -> Self {
324 let did = did.into();
325 let key_id = key_id.into();
326 let vm = VerificationMethod::ed25519_jwk(&key_id, &did, public_key);
327 Self {
328 context: vec![
329 "https://www.w3.org/ns/did/v1".to_string(),
330 "https://w3id.org/security/suites/jws-2020/v1".to_string(),
331 ],
332 id: did.clone(),
333 controller: None,
334 verification_methods: vec![vm],
335 authentication: vec![VerificationRef::Reference(key_id.clone())],
336 assertion_method: vec![VerificationRef::Reference(key_id.clone())],
337 key_agreement: vec![],
338 capability_invocation: vec![VerificationRef::Reference(key_id.clone())],
339 capability_delegation: vec![VerificationRef::Reference(key_id)],
340 service: vec![],
341 also_known_as: vec![],
342 }
343 }
344
345 pub fn ed25519_public_key(&self) -> Option<[u8; 32]> {
347 for vm in &self.verification_methods {
348 if let Some(bytes) = vm.ed25519_key_bytes() {
349 return Some(bytes);
350 }
351 }
352 for vr in &self.authentication {
354 if let VerificationRef::Embedded(vm) = vr
355 && let Some(bytes) = vm.ed25519_key_bytes()
356 {
357 return Some(bytes);
358 }
359 }
360 None
361 }
362
363 pub fn x25519_key_agreement_key(&self) -> Option<[u8; 32]> {
365 for vr in &self.key_agreement {
366 match vr {
367 VerificationRef::Embedded(vm) => {
368 if let Some(bytes) = vm.x25519_key_bytes() {
369 return Some(bytes);
370 }
371 }
372 VerificationRef::Reference(id) => {
373 if let Some(vm) = self.find_vm(id)
375 && let Some(bytes) = vm.x25519_key_bytes()
376 {
377 return Some(bytes);
378 }
379 }
380 }
381 }
382 None
383 }
384
385 pub fn find_vm(&self, id: &str) -> Option<&VerificationMethod> {
387 self.verification_methods
388 .iter()
389 .find(|vm| vm.id == id)
390 .or_else(|| {
391 let fragment = id.split_once('#').map(|(_, f)| f).unwrap_or(id);
393 self.verification_methods.iter().find(|vm| {
394 vm.id == id
395 || vm
396 .id
397 .split_once('#')
398 .map(|(_, f)| f == fragment)
399 .unwrap_or(false)
400 })
401 })
402 }
403
404 pub fn is_controlled_by(&self, did: &str) -> bool {
408 match &self.controller {
409 None => self.id == did,
410 Some(ctrl) => ctrl.contains(did),
411 }
412 }
413}