alimentar/format/
signing.rs1use crate::error::{Error, Result};
7
8pub const PUBLIC_KEY_SIZE: usize = 32;
10
11pub const SIGNATURE_SIZE: usize = 64;
13
14#[cfg(feature = "format-signing")]
16#[derive(Clone)]
17pub struct SigningKeyPair {
18 signing_key: ed25519_dalek::SigningKey,
19}
20
21#[cfg(feature = "format-signing")]
22impl std::fmt::Debug for SigningKeyPair {
23 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
24 let pk = self.public_key_bytes();
26 write!(
27 f,
28 "SigningKeyPair {{ public_key: {:02x}{:02x}{:02x}{:02x}..., secret_key: [REDACTED] }}",
29 pk[0], pk[1], pk[2], pk[3]
30 )
31 }
32}
33
34#[cfg(feature = "format-signing")]
35impl SigningKeyPair {
36 pub fn generate() -> Result<Self> {
42 let mut key_bytes = [0u8; 32];
43 getrandom::getrandom(&mut key_bytes)
44 .map_err(|e| Error::Format(format!("RNG error: {e}")))?;
45 let signing_key = ed25519_dalek::SigningKey::from_bytes(&key_bytes);
46 Ok(Self { signing_key })
47 }
48
49 #[must_use]
51 pub fn from_bytes(secret_key: [u8; 32]) -> Self {
52 Self {
53 signing_key: ed25519_dalek::SigningKey::from_bytes(&secret_key),
54 }
55 }
56
57 #[must_use]
59 pub fn public_key_bytes(&self) -> [u8; 32] {
60 self.signing_key.verifying_key().to_bytes()
61 }
62
63 #[must_use]
65 pub fn secret_key_bytes(&self) -> [u8; 32] {
66 self.signing_key.to_bytes()
67 }
68
69 #[must_use]
73 pub fn sign(&self, message: &[u8]) -> [u8; 64] {
74 use ed25519_dalek::Signer;
75 self.signing_key.sign(message).to_bytes()
76 }
77}
78
79#[cfg(feature = "format-signing")]
91pub fn verify(message: &[u8], signature: &[u8; 64], public_key: &[u8; 32]) -> Result<()> {
92 use ed25519_dalek::{Signature, Verifier, VerifyingKey};
93
94 let verifying_key = VerifyingKey::from_bytes(public_key)
95 .map_err(|e| Error::Format(format!("Invalid public key: {e}")))?;
96
97 let sig = Signature::from_bytes(signature);
98
99 verifying_key
100 .verify(message, &sig)
101 .map_err(|_| Error::Format("Signature verification failed".to_string()))
102}
103
104#[derive(Debug, Clone)]
106pub struct SignatureBlock {
107 pub signature: [u8; 64],
109 pub public_key: [u8; 32],
111}
112
113impl SignatureBlock {
114 pub const SIZE: usize = SIGNATURE_SIZE + PUBLIC_KEY_SIZE;
116
117 #[cfg(feature = "format-signing")]
119 #[must_use]
120 pub fn sign(data: &[u8], key_pair: &SigningKeyPair) -> Self {
121 Self {
122 signature: key_pair.sign(data),
123 public_key: key_pair.public_key_bytes(),
124 }
125 }
126
127 #[cfg(feature = "format-signing")]
133 pub fn verify(&self, data: &[u8]) -> Result<()> {
134 verify(data, &self.signature, &self.public_key)
135 }
136
137 #[must_use]
139 pub fn to_bytes(&self) -> [u8; Self::SIZE] {
140 let mut buf = [0u8; Self::SIZE];
141 buf[..SIGNATURE_SIZE].copy_from_slice(&self.signature);
142 buf[SIGNATURE_SIZE..].copy_from_slice(&self.public_key);
143 buf
144 }
145
146 pub fn from_bytes(buf: &[u8]) -> Result<Self> {
152 if buf.len() < Self::SIZE {
153 return Err(Error::Format(format!(
154 "Signature block too small: {} bytes, expected {}",
155 buf.len(),
156 Self::SIZE
157 )));
158 }
159
160 let mut signature = [0u8; SIGNATURE_SIZE];
161 let mut public_key = [0u8; PUBLIC_KEY_SIZE];
162 signature.copy_from_slice(&buf[..SIGNATURE_SIZE]);
163 public_key.copy_from_slice(&buf[SIGNATURE_SIZE..Self::SIZE]);
164
165 Ok(Self {
166 signature,
167 public_key,
168 })
169 }
170}
171
172#[cfg(all(test, feature = "format-signing"))]
173mod tests {
174 use super::*;
175
176 #[test]
177 fn test_sign_verify_roundtrip() {
178 let key_pair = SigningKeyPair::generate().expect("keygen failed");
179 let message = b"Hello, World! This is a test message.";
180
181 let signature = key_pair.sign(message);
182 let public_key = key_pair.public_key_bytes();
183
184 verify(message, &signature, &public_key).expect("verification failed");
185 }
186
187 #[test]
188 fn test_wrong_message_fails() {
189 let key_pair = SigningKeyPair::generate().expect("keygen failed");
190 let message = b"Original message";
191 let wrong_message = b"Wrong message";
192
193 let signature = key_pair.sign(message);
194 let public_key = key_pair.public_key_bytes();
195
196 let result = verify(wrong_message, &signature, &public_key);
197 assert!(result.is_err());
198 }
199
200 #[test]
201 fn test_wrong_key_fails() {
202 let key_pair1 = SigningKeyPair::generate().expect("keygen 1 failed");
203 let key_pair2 = SigningKeyPair::generate().expect("keygen 2 failed");
204 let message = b"Test message";
205
206 let signature = key_pair1.sign(message);
207 let wrong_public_key = key_pair2.public_key_bytes();
208
209 let result = verify(message, &signature, &wrong_public_key);
210 assert!(result.is_err());
211 }
212
213 #[test]
214 fn test_signature_block_roundtrip() {
215 let key_pair = SigningKeyPair::generate().expect("keygen failed");
216 let data = b"Dataset content to sign";
217
218 let block = SignatureBlock::sign(data, &key_pair);
219 block.verify(data).expect("verify failed");
220
221 let bytes = block.to_bytes();
223 assert_eq!(bytes.len(), SignatureBlock::SIZE);
224
225 let restored = SignatureBlock::from_bytes(&bytes).expect("parse failed");
226 restored.verify(data).expect("restored verify failed");
227 }
228
229 #[test]
230 fn test_from_bytes_keypair() {
231 let key_pair1 = SigningKeyPair::generate().expect("keygen failed");
232 let secret_bytes = key_pair1.secret_key_bytes();
233
234 let key_pair2 = SigningKeyPair::from_bytes(secret_bytes);
235 assert_eq!(key_pair1.public_key_bytes(), key_pair2.public_key_bytes());
236
237 let message = b"Test determinism";
239 assert_eq!(key_pair1.sign(message), key_pair2.sign(message));
240 }
241
242 #[test]
243 fn test_different_keys_produce_different_signatures() {
244 let key_pair1 = SigningKeyPair::generate().expect("keygen 1 failed");
245 let key_pair2 = SigningKeyPair::generate().expect("keygen 2 failed");
246 let message = b"Same message";
247
248 let sig1 = key_pair1.sign(message);
249 let sig2 = key_pair2.sign(message);
250
251 assert_ne!(sig1, sig2);
252 }
253
254 #[test]
255 fn test_signature_block_from_bytes_too_small() {
256 let buf = [0u8; 10]; let result = SignatureBlock::from_bytes(&buf);
258 assert!(result.is_err());
259 let err_msg = format!("{}", result.unwrap_err());
260 assert!(err_msg.contains("too small"));
261 }
262
263 #[test]
264 fn test_constants() {
265 assert_eq!(PUBLIC_KEY_SIZE, 32);
266 assert_eq!(SIGNATURE_SIZE, 64);
267 assert_eq!(SignatureBlock::SIZE, 96);
268 }
269
270 #[test]
271 fn test_signing_key_pair_clone() {
272 let key_pair = SigningKeyPair::generate().expect("keygen failed");
273 let cloned = key_pair.clone();
274 assert_eq!(key_pair.public_key_bytes(), cloned.public_key_bytes());
275 assert_eq!(key_pair.secret_key_bytes(), cloned.secret_key_bytes());
276 }
277
278 #[test]
279 fn test_signing_key_pair_debug() {
280 let key_pair = SigningKeyPair::generate().expect("keygen failed");
281 let debug = format!("{:?}", key_pair);
282 assert!(debug.contains("SigningKeyPair"));
283 assert!(debug.contains("REDACTED"));
284 }
285
286 #[test]
287 fn test_signature_block_clone() {
288 let key_pair = SigningKeyPair::generate().expect("keygen failed");
289 let data = b"Test data";
290 let block = SignatureBlock::sign(data, &key_pair);
291 let cloned = block.clone();
292 assert_eq!(cloned.signature, block.signature);
293 assert_eq!(cloned.public_key, block.public_key);
294 }
295
296 #[test]
297 fn test_signature_block_debug() {
298 let key_pair = SigningKeyPair::generate().expect("keygen failed");
299 let block = SignatureBlock::sign(b"test", &key_pair);
300 let debug = format!("{:?}", block);
301 assert!(debug.contains("SignatureBlock"));
302 }
303
304 #[test]
305 fn test_verify_invalid_public_key() {
306 let message = b"Test message";
307 let signature = [0u8; 64];
308 let invalid_pk = [0u8; 32];
310 let result = verify(message, &signature, &invalid_pk);
311 assert!(result.is_err());
312 }
313
314 #[test]
315 fn test_empty_message_signing() {
316 let key_pair = SigningKeyPair::generate().expect("keygen failed");
317 let message = b"";
318 let signature = key_pair.sign(message);
319 let public_key = key_pair.public_key_bytes();
320 verify(message, &signature, &public_key).expect("empty message verify failed");
321 }
322
323 #[test]
324 fn test_large_message_signing() {
325 let key_pair = SigningKeyPair::generate().expect("keygen failed");
326 let message = vec![0xABu8; 1024 * 1024]; let signature = key_pair.sign(&message);
328 let public_key = key_pair.public_key_bytes();
329 verify(&message, &signature, &public_key).expect("large message verify failed");
330 }
331}