1use std::error::Error;
2use serde::{Deserialize, Serialize};
7use std::collections::HashMap;
8use std::sync::{Arc, Mutex};
9use std::time::{SystemTime, UNIX_EPOCH};
10
11pub type Web5Result<T> = Result<T, Web5Error>;
13
14#[derive(Debug, thiserror::Error)]
16pub enum Web5Error {
17 #[error("Identity error: {0}")]
18 Identity(String),
19
20 #[error("Protocol error: {0}")]
21 Protocol(String),
22
23 #[error("Communication error: {0}")]
24 Communication(String),
25
26 #[error("Storage error: {0}")]
27 Storage(String),
28
29 #[error("Credential error: {0}")]
30 Credential(String),
31
32 #[error("Not found: {0}")]
33 NotFound(String),
34
35 #[error("DWN error: {0}")]
36 DWNError(String),
37
38 #[error("Serialization error: {0}")]
39 SerializationError(String),
40}
41
42impl From<Box<dyn std::error::Error>> for Web5Error {
45 fn from(err: Box<dyn std::error::Error>) -> Self {
46 Web5Error::Protocol(err.to_string())
47 }
48}
49
50impl From<String> for Web5Error {
53 fn from(err: String) -> Self {
54 Web5Error::Protocol(err)
55 }
56}
57
58impl From<&str> for Web5Error {
61 fn from(err: &str) -> Self {
62 Web5Error::Protocol(err.to_string())
63 }
64}
65
66#[derive(Clone, Debug)]
71pub struct DIDManager {
72 dids: Arc<Mutex<HashMap<String, DID>>>,
74 default_did: Option<String>,
76 method: String,
78}
79
80#[derive(Clone, Debug, Serialize, Deserialize)]
84pub struct DID {
85 pub id: String,
87 pub document: DIDDocument,
89 #[serde(skip_serializing)]
91 pub private_keys: HashMap<String, Vec<u8>>,
92}
93
94#[derive(Clone, Debug, Serialize, Deserialize)]
99pub struct DIDDocument {
100 #[serde(rename = "@context")]
102 pub context: Vec<String>,
103 pub id: String,
105 #[serde(default)]
107 pub verification_method: Vec<VerificationMethod>,
108 #[serde(default)]
110 pub authentication: Vec<String>,
111 #[serde(default)]
113 pub assertion_method: Vec<String>,
114 #[serde(default)]
116 pub service: Vec<Service>,
117}
118
119#[derive(Clone, Debug, Serialize, Deserialize)]
124pub struct VerificationMethod {
125 pub id: String,
127 #[serde(rename = "type")]
129 pub vm_type: String,
130 pub controller: String,
132 #[serde(skip_serializing_if = "Option::is_none")]
134 pub public_key_jwk: Option<JWK>,
135}
136
137#[derive(Clone, Debug, Serialize, Deserialize)]
141pub struct JWK {
142 pub kty: String,
144 #[serde(skip_serializing_if = "Option::is_none")]
146 pub crv: Option<String>,
147 #[serde(skip_serializing_if = "Option::is_none")]
149 pub x: Option<String>,
150 #[serde(skip_serializing_if = "Option::is_none")]
152 pub y: Option<String>,
153 #[serde(skip_serializing_if = "Option::is_none")]
155 pub kid: Option<String>,
156}
157
158#[derive(Clone, Debug, Serialize, Deserialize)]
162pub struct Service {
163 pub id: String,
165 #[serde(rename = "type")]
167 pub service_type: String,
168 pub service_endpoint: String,
170}
171
172impl DIDManager {
173 pub fn new(method: &str) -> Self {
175 Self {
176 dids: Arc::new(Mutex::new(HashMap::new())),
177 default_did: None,
178 method: method.to_string(),
179 }
180 }
181
182 pub fn create_did(&self) -> Web5Result<DID> {
184 let id = format!("did:{}:{}", self.method, generate_random_id());
186
187 let private_key = generate_private_key();
189 let public_key_jwk = generate_public_key_jwk(&private_key);
190
191 let verification_method = VerificationMethod {
193 id: format!("{id}#key-1"),
194 vm_type: "JsonWebKey2020".to_string(),
195 controller: id.clone(),
196 public_key_jwk: Some(public_key_jwk),
197 };
198
199 let document = DIDDocument {
201 context: vec!["https://www.w3.org/ns/did/v1".to_string()],
202 id: id.clone(),
203 verification_method: vec![verification_method],
204 authentication: vec![format!("{}#key-1", id)],
205 assertion_method: vec![format!("{}#key-1", id)],
206 service: Vec::new(),
207 };
208
209 let mut private_keys = HashMap::new();
211 private_keys.insert("key-1".to_string(), private_key);
212
213 let did = DID {
214 id: id.clone(),
215 document,
216 private_keys,
217 };
218
219 {
221 let mut dids = self
222 .dids
223 .lock()
224 .map_err(|e| format!("Mutex lock error: {e}"))?;
225 dids.insert(id.clone(), did.clone());
226 }
227
228 Ok(did)
229 }
230
231 pub fn resolve_did(&self, did: &str) -> Result<DIDDocument, Box<dyn Error>> {
233 let dids = self
235 .dids
236 .lock()
237 .map_err(|e| format!("Mutex lock error: {e}"))?;
238 if let Some(did_obj) = dids.get(did) {
239 return Ok(did_obj.document.clone());
240 }
241
242 Err(format!("DID not found: {did}").into())
244 }
245
246 pub fn set_default_did(&mut self, did: &str) -> Result<(), Box<dyn Error>> {
248 let dids = self
249 .dids
250 .lock()
251 .map_err(|e| format!("Mutex lock error: {e}"))?;
252 if dids.contains_key(did) {
253 self.default_did = Some(did.to_string());
254 Ok(())
255 } else {
256 Err(format!("DID {did} not found").into())
257 }
258 }
259
260 pub fn get_default_did(&self) -> Result<Option<String>, Box<dyn Error>> {
262 Ok(self.default_did.clone())
263 }
264
265 pub fn sign(&self, did: &str, data: &[u8]) -> Result<Vec<u8>, Box<dyn Error>> {
267 let dids = self
269 .dids
270 .lock()
271 .map_err(|e| format!("Mutex lock error: {e}"))?;
272 let did_obj = dids
273 .get(did)
274 .ok_or_else(|| format!("DID not found: {did}"))?;
275
276 if let Some((_, private_key_bytes)) = did_obj.private_keys.iter().next() {
278 let private_key = secp256k1::SecretKey::from_slice(private_key_bytes)
280 .map_err(|e| format!("Invalid private key: {e}"))?;
281
282 let secp = secp256k1::Secp256k1::signing_only();
284
285 let hash = {
287 use sha2::{Digest, Sha256};
288 let mut hasher = Sha256::new();
289 hasher.update(data);
290 hasher.finalize()
291 };
292
293 let message = secp256k1::Message::from_digest_slice(&hash)
295 .map_err(|e| format!("Failed to create message: {e}"))?;
296
297 let signature = secp.sign_ecdsa(&message, &private_key);
299
300 Ok(signature.serialize_compact().to_vec())
302 } else {
303 Err("No private keys found for DID".into())
304 }
305 }
306
307 pub fn dids(&self) -> Result<Vec<String>, Box<dyn Error>> {
309 let dids = self
310 .dids
311 .lock()
312 .map_err(|e| format!("Mutex lock error: {e}"))?;
313 Ok(dids.keys().cloned().collect())
314 }
315
316 pub fn get_did(&self, did_id: &str) -> Web5Result<Option<DID>> {
318 let dids = self
319 .dids
320 .lock()
321 .map_err(|e| Web5Error::Storage(format!("Mutex lock error: {e}")))?;
322 Ok(dids.get(did_id).cloned())
323 }
324
325 pub fn list_dids(&self) -> Vec<DID> {
327 let dids = self
328 .dids
329 .lock()
330 .unwrap_or_else(|_| panic!("Failed to lock mutex"));
331 dids.values().cloned().collect()
332 }
333}
334
335#[derive(Debug, Clone)]
337pub struct IdentityManager {
338 did_manager: DIDManager,
339}
340
341impl IdentityManager {
342 pub fn new(namespace: &str) -> Self {
343 Self {
344 did_manager: DIDManager::new(namespace),
345 }
346 }
347
348 pub fn create_identity(&mut self) -> Web5Result<DID> {
349 self.did_manager.create_did()
350 }
351
352 pub fn get_identity(&self, did_id: &str) -> Web5Result<Option<DID>> {
353 self.did_manager.get_did(did_id)
354 }
355
356 pub fn list_identities(&self) -> Vec<DID> {
357 self.did_manager.list_dids()
358 }
359}
360
361fn generate_random_id() -> String {
364 let now = SystemTime::now()
365 .duration_since(UNIX_EPOCH)
366 .unwrap_or_default()
367 .as_secs();
368
369 format!("{now:x}")
370}
371
372fn generate_private_key() -> Vec<u8> {
374 use rand::RngCore;
376 let mut key = vec![0u8; 32];
377 rand::thread_rng().fill_bytes(&mut key);
378 key
379}
380
381fn generate_public_key_jwk(private_key: &[u8]) -> JWK {
383 use base64::Engine;
386
387 JWK {
389 kty: "EC".to_string(),
390 crv: Some("secp256k1".to_string()),
391 x: Some(base64::engine::general_purpose::URL_SAFE_NO_PAD.encode(&private_key[..16])),
392 y: Some(base64::engine::general_purpose::URL_SAFE_NO_PAD.encode(&private_key[16..])),
393 kid: Some("key-1".to_string()),
394 }
395}
396
397#[cfg(test)]
398mod tests {
399 use super::*;
400
401 #[test]
402 fn test_create_did() -> Result<(), Box<dyn Error>> {
403 let manager = DIDManager::new("example");
404 let did = manager.create_did()?;
405 assert!(!did.id.is_empty());
406 assert!(did.id.starts_with("did:example:"));
407 assert!(!did.private_keys.is_empty());
408 Ok(())
409 }
410
411 #[test]
412 fn test_default_did() -> Result<(), Box<dyn Error>> {
413 let mut manager = DIDManager::new("example");
414 let did = manager.create_did()?;
415
416 assert!(manager.get_default_did()?.is_none());
418
419 manager.set_default_did(&did.id)?;
421 assert_eq!(manager.get_default_did()?.unwrap(), did.id);
422 Ok(())
423 }
424}