agent_uri_attestation/
keys.rs1use ed25519_dalek::{SigningKey as DalekSigningKey, VerifyingKey as DalekVerifyingKey};
4
5use crate::error::AttestationError;
6
7#[derive(Clone)]
23pub struct SigningKey {
24 inner: DalekSigningKey,
25}
26
27impl SigningKey {
28 #[must_use]
30 pub fn generate() -> Self {
31 let mut rng = rand::thread_rng();
32 Self {
33 inner: DalekSigningKey::generate(&mut rng),
34 }
35 }
36
37 pub fn from_bytes(bytes: &[u8; 32]) -> Result<Self, AttestationError> {
44 Ok(Self {
45 inner: DalekSigningKey::from_bytes(bytes),
46 })
47 }
48
49 #[must_use]
51 pub fn to_bytes(&self) -> [u8; 32] {
52 self.inner.to_bytes()
53 }
54
55 #[must_use]
57 pub fn verifying_key(&self) -> VerifyingKey {
58 VerifyingKey {
59 inner: self.inner.verifying_key(),
60 }
61 }
62
63 pub(crate) fn as_dalek(&self) -> &DalekSigningKey {
65 &self.inner
66 }
67}
68
69impl std::fmt::Debug for SigningKey {
70 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
71 f.debug_struct("SigningKey")
72 .field("public_key", &self.verifying_key())
73 .finish_non_exhaustive()
74 }
75}
76
77#[derive(Clone, PartialEq, Eq)]
97pub struct VerifyingKey {
98 inner: DalekVerifyingKey,
99}
100
101impl VerifyingKey {
102 pub fn from_bytes(bytes: &[u8; 32]) -> Result<Self, AttestationError> {
109 DalekVerifyingKey::from_bytes(bytes)
110 .map(|inner| Self { inner })
111 .map_err(|e| AttestationError::InvalidKeyFormat {
112 reason: e.to_string(),
113 })
114 }
115
116 #[must_use]
118 pub fn to_bytes(&self) -> [u8; 32] {
119 self.inner.to_bytes()
120 }
121
122}
123
124impl std::fmt::Debug for VerifyingKey {
125 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
126 let bytes = self.to_bytes();
128 write!(
129 f,
130 "VerifyingKey({:02x}{:02x}{:02x}{:02x}...)",
131 bytes[0], bytes[1], bytes[2], bytes[3]
132 )
133 }
134}
135
136#[cfg(test)]
137mod tests {
138 use super::*;
139
140 #[test]
141 fn signing_key_generates_unique_keys() {
142 let key1 = SigningKey::generate();
143 let key2 = SigningKey::generate();
144
145 assert_ne!(key1.to_bytes(), key2.to_bytes());
146 }
147
148 #[test]
149 fn signing_key_roundtrip_bytes() {
150 let original = SigningKey::generate();
151 let bytes = original.to_bytes();
152 let recovered = SigningKey::from_bytes(&bytes).unwrap();
153
154 assert_eq!(original.to_bytes(), recovered.to_bytes());
155 }
156
157 #[test]
158 fn verifying_key_roundtrip_bytes() {
159 let signing_key = SigningKey::generate();
160 let verifying_key = signing_key.verifying_key();
161 let bytes = verifying_key.to_bytes();
162 let recovered = VerifyingKey::from_bytes(&bytes).unwrap();
163
164 assert_eq!(verifying_key, recovered);
165 }
166
167 #[test]
168 fn verifying_key_from_invalid_bytes_fails() {
169 let test_cases = [
172 [0xFFu8; 32],
173 [0xEEu8; 32],
174 {
175 let mut b = [0u8; 32];
176 b[31] = 0x80; b
178 },
179 ];
180
181 let mut found_invalid = false;
182 for invalid_bytes in &test_cases {
183 let result = VerifyingKey::from_bytes(invalid_bytes);
184 if result.is_err() {
185 found_invalid = true;
186 assert!(matches!(
187 result,
188 Err(AttestationError::InvalidKeyFormat { .. })
189 ));
190 break;
191 }
192 }
193
194 if !found_invalid {
197 let signing_key = SigningKey::generate();
199 let valid_key = signing_key.verifying_key();
200 assert!(VerifyingKey::from_bytes(&valid_key.to_bytes()).is_ok());
201 }
202 }
203
204 #[test]
205 fn signing_key_debug_shows_public_key() {
206 let key = SigningKey::generate();
207 let debug_output = format!("{key:?}");
208
209 assert!(debug_output.contains("SigningKey"));
210 assert!(debug_output.contains("VerifyingKey"));
211 }
212
213 #[test]
214 fn verifying_key_debug_shows_partial_bytes() {
215 let signing_key = SigningKey::generate();
216 let verifying_key = signing_key.verifying_key();
217 let debug_output = format!("{verifying_key:?}");
218
219 assert!(debug_output.contains("VerifyingKey("));
220 assert!(debug_output.contains("..."));
221 }
222}