1use crate::crypto::provider_bridge;
2use crate::error::AgentError;
3use auths_crypto::SecureSeed;
4use log::error;
5use std::collections::HashMap;
6use std::fmt;
7use zeroize::Zeroizing;
8
9#[derive(Default)]
13pub struct AgentCore {
14 pub keys: HashMap<Vec<u8>, SecureSeed>,
16}
17
18impl fmt::Debug for AgentCore {
19 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
20 f.debug_struct("AgentCore")
21 .field("key_count", &self.keys.len())
22 .finish_non_exhaustive()
23 }
24}
25
26impl AgentCore {
27 pub fn new() -> Self {
29 Self::default()
30 }
31
32 pub fn register_key(&mut self, pkcs8_bytes: Zeroizing<Vec<u8>>) -> Result<(), AgentError> {
38 let (seed, pubkey) = crate::crypto::signer::load_seed_and_pubkey(&pkcs8_bytes)?;
39 self.keys.insert(pubkey.to_vec(), seed);
40 Ok(())
41 }
42
43 pub fn unregister_key(&mut self, pubkey: &[u8]) -> Result<(), AgentError> {
45 self.keys
46 .remove(pubkey)
47 .map(|_| ())
48 .ok_or(AgentError::KeyNotFound)
49 }
50
51 pub fn sign(&self, pubkey_to_find: &[u8], data: &[u8]) -> Result<Vec<u8>, AgentError> {
54 let seed = self
55 .keys
56 .get(pubkey_to_find)
57 .ok_or(AgentError::KeyNotFound)?;
58
59 provider_bridge::sign_ed25519_sync(seed, data).map_err(|e| {
60 error!("CryptoProvider signing failed: {}", e);
61 AgentError::CryptoError(format!("Ed25519 signing failed: {}", e))
62 })
63 }
64
65 pub fn public_keys(&self) -> Vec<Vec<u8>> {
67 self.keys.keys().cloned().collect()
68 }
69
70 pub fn key_count(&self) -> usize {
72 self.keys.len()
73 }
74
75 pub fn clear_keys(&mut self) {
77 self.keys.clear();
78 }
79}
80
81#[cfg(test)]
82mod tests {
83 use super::*;
84 use ring::rand::SystemRandom;
85 use ring::signature::{ED25519, Ed25519KeyPair, KeyPair, UnparsedPublicKey};
86 use zeroize::Zeroizing;
87
88 fn generate_test_key_bytes() -> (Vec<u8>, Vec<u8>) {
89 let rng = SystemRandom::new();
90 let pkcs8_doc = Ed25519KeyPair::generate_pkcs8(&rng).expect("Failed to generate PKCS#8");
91 let pkcs8_bytes = pkcs8_doc.as_ref().to_vec();
92 let keypair =
93 Ed25519KeyPair::from_pkcs8(&pkcs8_bytes).expect("Failed to parse generated PKCS#8");
94 let pubkey_bytes = keypair.public_key().as_ref().to_vec();
95 (pubkey_bytes, pkcs8_bytes)
96 }
97
98 fn core_with_two_keys() -> (AgentCore, Vec<u8>, Vec<u8>) {
99 let (pubkey1, pkcs8_1) = generate_test_key_bytes();
100 let (pubkey2, pkcs8_2) = generate_test_key_bytes();
101 let mut core = AgentCore::default();
102 core.register_key(Zeroizing::new(pkcs8_1)).unwrap();
103 core.register_key(Zeroizing::new(pkcs8_2)).unwrap();
104 (core, pubkey1, pubkey2)
105 }
106
107 #[test]
108 fn register_keys_updates_count_and_listing() {
109 let (core, pubkey1, pubkey2) = core_with_two_keys();
110 assert_eq!(core.key_count(), 2);
111 let mut keys = core.public_keys();
112 keys.sort();
113 let mut expected = vec![pubkey1, pubkey2];
114 expected.sort();
115 assert_eq!(keys, expected);
116 }
117
118 #[test]
119 fn sign_produces_verifiable_signature() {
120 let (core, pubkey1, _) = core_with_two_keys();
121 let message = b"test message for agent core";
122 let signature = core.sign(&pubkey1, message).unwrap();
123 assert!(!signature.is_empty());
124 let ring_key = UnparsedPublicKey::new(&ED25519, &pubkey1);
125 assert!(ring_key.verify(message, &signature).is_ok());
126 }
127
128 #[test]
129 fn sign_with_different_keys_produces_different_signatures() {
130 let (core, pubkey1, pubkey2) = core_with_two_keys();
131 let message = b"test message";
132 let sig1 = core.sign(&pubkey1, message).unwrap();
133 let sig2 = core.sign(&pubkey2, message).unwrap();
134 assert_ne!(sig1, sig2);
135 }
136
137 #[test]
138 fn sign_with_nonexistent_key_returns_key_not_found() {
139 let (core, _, _) = core_with_two_keys();
140 let err = core.sign(&[99u8; 32], b"msg").unwrap_err();
141 assert!(matches!(err, AgentError::KeyNotFound));
142 }
143
144 #[test]
145 fn unregister_removes_key_and_prevents_signing() {
146 let (mut core, pubkey1, pubkey2) = core_with_two_keys();
147 core.unregister_key(&pubkey1).unwrap();
148 assert_eq!(core.key_count(), 1);
149 assert_eq!(core.public_keys(), vec![pubkey2.clone()]);
150 assert!(matches!(
151 core.sign(&pubkey1, b"msg").unwrap_err(),
152 AgentError::KeyNotFound
153 ));
154 assert!(core.sign(&pubkey2, b"msg").is_ok());
156 }
157
158 #[test]
159 fn clear_keys_removes_all() {
160 let (mut core, pubkey1, _) = core_with_two_keys();
161 core.clear_keys();
162 assert_eq!(core.key_count(), 0);
163 assert!(core.public_keys().is_empty());
164 assert!(matches!(
165 core.unregister_key(&pubkey1).unwrap_err(),
166 AgentError::KeyNotFound
167 ));
168 }
169
170 #[test]
171 fn test_register_invalid_key() {
172 let mut core = AgentCore::default();
173 let invalid_bytes = vec![1, 2, 3, 4];
174 let result = core.register_key(Zeroizing::new(invalid_bytes));
175 assert!(result.is_err());
176 assert_eq!(core.key_count(), 0);
177 }
178}