1use crate::crypto::{generate_keypair, sign_message, verify_signature, Signature};
4use crate::error::{CryptoError, Error, Result};
5use ed25519_dalek::{SigningKey, VerifyingKey, PUBLIC_KEY_LENGTH, SECRET_KEY_LENGTH};
6use serde::{Deserialize, Serialize};
7use uuid::Uuid;
8use zeroize::{Zeroize, ZeroizeOnDrop};
9use base64::{Engine as _, engine::general_purpose::URL_SAFE_NO_PAD};
10
11#[derive(Clone, Serialize, Deserialize)]
13pub struct AgentIdentity {
14 id: Uuid,
16 #[serde(serialize_with = "serialize_signing_key", deserialize_with = "deserialize_signing_key")]
18 signing_key: SigningKey,
19 #[serde(serialize_with = "serialize_verifying_key", deserialize_with = "deserialize_verifying_key")]
21 verifying_key: VerifyingKey,
22 did: String,
24}
25
26fn serialize_signing_key<S>(key: &SigningKey, serializer: S) -> std::result::Result<S::Ok, S::Error>
28where
29 S: serde::Serializer,
30{
31 let bytes = key.to_bytes();
32 serializer.serialize_bytes(&bytes)
33}
34
35fn deserialize_signing_key<'de, D>(deserializer: D) -> std::result::Result<SigningKey, D::Error>
36where
37 D: serde::Deserializer<'de>,
38{
39 let bytes: Vec<u8> = serde::Deserialize::deserialize(deserializer)?;
40 let key_bytes: [u8; 32] = bytes.as_slice().try_into()
41 .map_err(|_| serde::de::Error::custom("Invalid signing key length"))?;
42 Ok(SigningKey::from_bytes(&key_bytes))
43}
44
45fn serialize_verifying_key<S>(key: &VerifyingKey, serializer: S) -> std::result::Result<S::Ok, S::Error>
47where
48 S: serde::Serializer,
49{
50 let bytes = key.to_bytes();
51 serializer.serialize_bytes(&bytes)
52}
53
54fn deserialize_verifying_key<'de, D>(deserializer: D) -> std::result::Result<VerifyingKey, D::Error>
55where
56 D: serde::Deserializer<'de>,
57{
58 let bytes: Vec<u8> = serde::Deserialize::deserialize(deserializer)?;
59 let key_bytes: [u8; 32] = bytes.as_slice().try_into()
60 .map_err(|_| serde::de::Error::custom("Invalid verifying key length"))?;
61 VerifyingKey::from_bytes(&key_bytes)
62 .map_err(|e| serde::de::Error::custom(format!("Invalid verifying key: {}", e)))
63}
64
65impl AgentIdentity {
66 pub fn generate() -> Result<Self> {
68 let id = Uuid::new_v4();
69 let (signing_key, verifying_key) = generate_keypair()?;
70 let did = Self::compute_did(&verifying_key);
71
72 Ok(Self {
73 id,
74 signing_key,
75 verifying_key,
76 did,
77 })
78 }
79
80 pub fn from_signing_key(signing_key: SigningKey) -> Result<Self> {
82 let id = Uuid::new_v4();
83 let verifying_key = signing_key.verifying_key();
84 let did = Self::compute_did(&verifying_key);
85
86 Ok(Self {
87 id,
88 signing_key,
89 verifying_key,
90 did,
91 })
92 }
93
94 pub fn from_bytes(signing_key_bytes: &[u8]) -> Result<Self> {
96 if signing_key_bytes.len() != SECRET_KEY_LENGTH {
97 return Err(Error::Crypto(CryptoError::InvalidPrivateKey {
98 details: format!("Expected {} bytes, got {}", SECRET_KEY_LENGTH, signing_key_bytes.len()),
99 }));
100 }
101
102 let signing_key = SigningKey::from_bytes(
103 signing_key_bytes.try_into().map_err(|_| {
104 Error::Crypto(CryptoError::InvalidPrivateKey {
105 details: "Invalid key length".to_string(),
106 })
107 })?
108 );
109
110 Self::from_signing_key(signing_key)
111 }
112
113 pub fn id(&self) -> &Uuid {
115 &self.id
116 }
117
118 pub fn did(&self) -> &str {
120 &self.did
121 }
122
123 pub fn signing_key(&self) -> &SigningKey {
125 &self.signing_key
126 }
127
128 pub fn verifying_key(&self) -> &VerifyingKey {
130 &self.verifying_key
131 }
132
133 pub fn verifying_key_bytes(&self) -> [u8; PUBLIC_KEY_LENGTH] {
135 self.verifying_key.to_bytes()
136 }
137
138 pub fn sign(&self, message: &[u8]) -> Result<Signature> {
140 sign_message(&self.signing_key, message)
141 }
142
143 pub fn verify(&self, message: &[u8], signature: &Signature) -> Result<bool> {
145 verify_signature(&self.verifying_key, message, signature)
146 }
147
148 pub fn to_bytes(&self) -> [u8; SECRET_KEY_LENGTH] {
150 self.signing_key.to_bytes()
151 }
152
153 pub fn to_did_document(&self) -> DidDocument {
155 DidDocument::new(self.did.clone(), self.verifying_key)
156 }
157
158 fn compute_did(verifying_key: &VerifyingKey) -> String {
160 let key_bytes = verifying_key.to_bytes();
161 let encoded = URL_SAFE_NO_PAD.encode(&key_bytes);
162 format!("did:key:z{}", encoded)
163 }
164}
165
166impl Drop for AgentIdentity {
167 fn drop(&mut self) {
168 }
171}
172
173impl std::fmt::Debug for AgentIdentity {
174 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
175 f.debug_struct("AgentIdentity")
176 .field("id", &self.id)
177 .field("did", &self.did)
178 .field("verifying_key", &hex::encode(self.verifying_key.to_bytes()))
179 .finish_non_exhaustive()
180 }
181}
182
183#[derive(Debug, Clone, Serialize, Deserialize)]
185pub struct DidDocument {
186 pub id: String,
188
189 #[serde(rename = "verificationMethod")]
191 pub verification_method: Vec<VerificationMethod>,
192
193 pub authentication: Vec<String>,
195
196 #[serde(rename = "assertionMethod")]
198 pub assertion_method: Vec<String>,
199}
200
201impl DidDocument {
202 pub fn new(did: String, verifying_key: VerifyingKey) -> Self {
204 let key_id = format!("{}#key-1", did);
205 let verification_method = vec![
206 VerificationMethod {
207 id: key_id.clone(),
208 type_: "Ed25519VerificationKey2020".to_string(),
209 controller: did.clone(),
210 public_key_multibase: format!("z{}",
211 URL_SAFE_NO_PAD.encode(&verifying_key.to_bytes())
212 ),
213 }
214 ];
215
216 Self {
217 id: did,
218 verification_method,
219 authentication: vec![key_id.clone()],
220 assertion_method: vec![key_id],
221 }
222 }
223
224 pub fn validate(&self) -> Result<()> {
226 if self.id.is_empty() {
227 return Err(Error::Did("DID cannot be empty".to_string()));
228 }
229
230 if !self.id.starts_with("did:") {
231 return Err(Error::Did("DID must start with 'did:'".to_string()));
232 }
233
234 if self.verification_method.is_empty() {
235 return Err(Error::Did("DID document must have at least one verification method".to_string()));
236 }
237
238 Ok(())
239 }
240}
241
242#[derive(Debug, Clone, Serialize, Deserialize)]
244pub struct VerificationMethod {
245 pub id: String,
247
248 #[serde(rename = "type")]
250 pub type_: String,
251
252 pub controller: String,
254
255 #[serde(rename = "publicKeyMultibase")]
257 pub public_key_multibase: String,
258}
259
260#[cfg(test)]
261mod tests {
262 use super::*;
263
264 #[test]
265 fn test_generate_identity() {
266 let identity = AgentIdentity::generate().unwrap();
267 assert!(identity.did().starts_with("did:key:z"));
268 assert!(!identity.id().is_nil());
269 }
270
271 #[test]
272 fn test_sign_and_verify() {
273 let identity = AgentIdentity::generate().unwrap();
274 let message = b"test message";
275
276 let signature = identity.sign(message).unwrap();
277 let is_valid = identity.verify(message, &signature).unwrap();
278
279 assert!(is_valid);
280 }
281
282 #[test]
283 fn test_verify_wrong_message() {
284 let identity = AgentIdentity::generate().unwrap();
285 let message = b"test message";
286 let wrong_message = b"wrong message";
287
288 let signature = identity.sign(message).unwrap();
289 let is_valid = identity.verify(wrong_message, &signature).unwrap();
290
291 assert!(!is_valid);
292 }
293
294 #[test]
295 fn test_identity_from_bytes() {
296 let identity1 = AgentIdentity::generate().unwrap();
297 let key_bytes = identity1.to_bytes();
298
299 let identity2 = AgentIdentity::from_bytes(&key_bytes).unwrap();
300
301 assert_eq!(
302 identity1.verifying_key_bytes(),
303 identity2.verifying_key_bytes()
304 );
305 }
306
307 #[test]
308 fn test_invalid_key_bytes() {
309 let invalid_bytes = vec![0u8; 16];
310 let result = AgentIdentity::from_bytes(&invalid_bytes);
311 assert!(result.is_err());
312 }
313
314 #[test]
315 fn test_did_document() {
316 let identity = AgentIdentity::generate().unwrap();
317 let doc = identity.to_did_document();
318
319 assert_eq!(doc.id, identity.did());
320 assert!(!doc.verification_method.is_empty());
321 assert!(!doc.authentication.is_empty());
322 assert!(!doc.assertion_method.is_empty());
323
324 doc.validate().unwrap();
325 }
326
327 #[test]
328 fn test_did_document_validation() {
329 let identity = AgentIdentity::generate().unwrap();
330 let mut doc = identity.to_did_document();
331
332 assert!(doc.validate().is_ok());
334
335 doc.id = String::new();
337 assert!(doc.validate().is_err());
338
339 doc.id = "not-a-did".to_string();
341 assert!(doc.validate().is_err());
342 }
343
344 #[test]
345 fn test_multiple_identities() {
346 let identity1 = AgentIdentity::generate().unwrap();
347 let identity2 = AgentIdentity::generate().unwrap();
348
349 assert_ne!(identity1.id(), identity2.id());
350 assert_ne!(identity1.did(), identity2.did());
351 assert_ne!(
352 identity1.verifying_key_bytes(),
353 identity2.verifying_key_bytes()
354 );
355 }
356
357 #[test]
358 fn test_cross_identity_verification() {
359 let identity1 = AgentIdentity::generate().unwrap();
360 let identity2 = AgentIdentity::generate().unwrap();
361
362 let message = b"test message";
363 let signature = identity1.sign(message).unwrap();
364
365 let is_valid = identity2.verify(message, &signature).unwrap();
367 assert!(!is_valid);
368 }
369}