rust_crypto_utils/
signatures.rs1use ed25519_dalek::{Signature, Signer, SigningKey, Verifier, VerifyingKey};
4use hmac::{Hmac, Mac};
5use rand::rngs::OsRng;
6use sha2::Sha256;
7use zeroize::{Zeroize, ZeroizeOnDrop};
8
9type HmacSha256 = Hmac<Sha256>;
10
11#[derive(ZeroizeOnDrop)]
13pub struct Ed25519KeyPair {
14 signing_key: SigningKey,
15}
16
17impl Ed25519KeyPair {
18 pub fn generate() -> Self {
20 use rand::RngCore;
21 let mut seed = [0u8; 32];
22 OsRng.fill_bytes(&mut seed);
23 let signing_key = SigningKey::from_bytes(&seed);
24 Self { signing_key }
25 }
26
27 pub fn from_seed(seed: &[u8; 32]) -> Self {
29 let signing_key = SigningKey::from_bytes(seed);
30 Self { signing_key }
31 }
32
33 pub fn sign(&self, message: &[u8]) -> Vec<u8> {
35 let signature = self.signing_key.sign(message);
36 signature.to_bytes().to_vec()
37 }
38
39 pub fn public_key(&self) -> Ed25519PublicKey {
41 Ed25519PublicKey {
42 verifying_key: self.signing_key.verifying_key(),
43 }
44 }
45
46 pub fn to_bytes(&self) -> [u8; 32] {
48 self.signing_key.to_bytes()
49 }
50}
51
52#[derive(Clone)]
54pub struct Ed25519PublicKey {
55 verifying_key: VerifyingKey,
56}
57
58impl Ed25519PublicKey {
59 pub fn from_bytes(bytes: &[u8; 32]) -> Result<Self, String> {
61 VerifyingKey::from_bytes(bytes)
62 .map(|verifying_key| Self { verifying_key })
63 .map_err(|e| format!("Invalid public key: {}", e))
64 }
65
66 pub fn verify(&self, message: &[u8], signature: &[u8]) -> Result<(), String> {
68 if signature.len() != 64 {
69 return Err("Invalid signature length".to_string());
70 }
71
72 let sig_array: [u8; 64] = signature.try_into()
73 .map_err(|_| "Failed to convert signature")?;
74 let signature = Signature::from_bytes(&sig_array);
75
76 self.verifying_key
77 .verify(message, &signature)
78 .map_err(|e| format!("Verification failed: {}", e))
79 }
80
81 pub fn to_bytes(&self) -> [u8; 32] {
83 self.verifying_key.to_bytes()
84 }
85}
86
87#[derive(Zeroize, ZeroizeOnDrop)]
89pub struct HmacKey {
90 key: Vec<u8>,
91}
92
93impl HmacKey {
94 pub fn new(key: Vec<u8>) -> Self {
96 Self { key }
97 }
98
99 pub fn generate() -> Self {
101 let mut key = vec![0u8; 32];
102 rand::RngCore::fill_bytes(&mut OsRng, &mut key);
103 Self { key }
104 }
105
106 pub fn sign(&self, message: &[u8]) -> Vec<u8> {
108 let mut mac = HmacSha256::new_from_slice(&self.key)
109 .expect("HMAC key length error");
110 mac.update(message);
111 mac.finalize().into_bytes().to_vec()
112 }
113
114 pub fn verify(&self, message: &[u8], tag: &[u8]) -> Result<(), String> {
116 let mut mac = HmacSha256::new_from_slice(&self.key)
117 .map_err(|e| format!("HMAC error: {}", e))?;
118 mac.update(message);
119 mac.verify_slice(tag)
120 .map_err(|_| "HMAC verification failed".to_string())
121 }
122
123 pub fn as_bytes(&self) -> &[u8] {
125 &self.key
126 }
127}
128
129pub struct SignatureSuite {
131 ed25519_keypair: Option<Ed25519KeyPair>,
132 hmac_key: Option<HmacKey>,
133}
134
135impl SignatureSuite {
136 pub fn new_ed25519() -> Self {
138 Self {
139 ed25519_keypair: Some(Ed25519KeyPair::generate()),
140 hmac_key: None,
141 }
142 }
143
144 pub fn new_hmac() -> Self {
146 Self {
147 ed25519_keypair: None,
148 hmac_key: Some(HmacKey::generate()),
149 }
150 }
151
152 pub fn new_combined() -> Self {
154 Self {
155 ed25519_keypair: Some(Ed25519KeyPair::generate()),
156 hmac_key: Some(HmacKey::generate()),
157 }
158 }
159
160 pub fn sign_ed25519(&self, message: &[u8]) -> Option<Vec<u8>> {
162 self.ed25519_keypair.as_ref().map(|kp| kp.sign(message))
163 }
164
165 pub fn sign_hmac(&self, message: &[u8]) -> Option<Vec<u8>> {
167 self.hmac_key.as_ref().map(|key| key.sign(message))
168 }
169
170 pub fn ed25519_public_key(&self) -> Option<Ed25519PublicKey> {
172 self.ed25519_keypair.as_ref().map(|kp| kp.public_key())
173 }
174}
175
176#[cfg(test)]
177mod tests {
178 use super::*;
179
180 #[test]
181 fn test_ed25519_sign_verify() {
182 let keypair = Ed25519KeyPair::generate();
183 let message = b"Test message for signing";
184
185 let signature = keypair.sign(message);
186 assert_eq!(signature.len(), 64);
187
188 let public_key = keypair.public_key();
189 assert!(public_key.verify(message, &signature).is_ok());
190 }
191
192 #[test]
193 fn test_ed25519_verify_failure() {
194 let keypair = Ed25519KeyPair::generate();
195 let message = b"Original message";
196 let tampered = b"Tampered message";
197
198 let signature = keypair.sign(message);
199 let public_key = keypair.public_key();
200
201 assert!(public_key.verify(tampered, &signature).is_err());
202 }
203
204 #[test]
205 fn test_ed25519_from_seed() {
206 let seed = [42u8; 32];
207 let keypair1 = Ed25519KeyPair::from_seed(&seed);
208 let keypair2 = Ed25519KeyPair::from_seed(&seed);
209
210 let message = b"Test";
211 let sig1 = keypair1.sign(message);
212 let sig2 = keypair2.sign(message);
213
214 assert_eq!(sig1, sig2);
215 }
216
217 #[test]
218 fn test_hmac_sign_verify() {
219 let key = HmacKey::generate();
220 let message = b"Test message";
221
222 let tag = key.sign(message);
223 assert!(key.verify(message, &tag).is_ok());
224 }
225
226 #[test]
227 fn test_hmac_verify_failure() {
228 let key = HmacKey::generate();
229 let message = b"Original message";
230 let tampered = b"Tampered message";
231
232 let tag = key.sign(message);
233 assert!(key.verify(tampered, &tag).is_err());
234 }
235
236 #[test]
237 fn test_hmac_different_keys() {
238 let key1 = HmacKey::generate();
239 let key2 = HmacKey::generate();
240 let message = b"Test";
241
242 let tag1 = key1.sign(message);
243 assert!(key2.verify(message, &tag1).is_err());
244 }
245
246 #[test]
247 fn test_signature_suite_ed25519() {
248 let suite = SignatureSuite::new_ed25519();
249 let message = b"Test message";
250
251 let signature = suite.sign_ed25519(message).expect("Signing failed");
252 let public_key = suite.ed25519_public_key().expect("No public key");
253
254 assert!(public_key.verify(message, &signature).is_ok());
255 }
256
257 #[test]
258 fn test_signature_suite_hmac() {
259 let suite = SignatureSuite::new_hmac();
260 let message = b"Test message";
261
262 let tag = suite.sign_hmac(message).expect("HMAC signing failed");
263 assert!(!tag.is_empty());
264 }
265
266 #[test]
267 fn test_signature_suite_combined() {
268 let suite = SignatureSuite::new_combined();
269 let message = b"Test message";
270
271 assert!(suite.sign_ed25519(message).is_some());
272 assert!(suite.sign_hmac(message).is_some());
273 }
274
275 #[test]
276 fn test_ed25519_public_key_serialization() {
277 let keypair = Ed25519KeyPair::generate();
278 let public_key = keypair.public_key();
279
280 let bytes = public_key.to_bytes();
281 let restored = Ed25519PublicKey::from_bytes(&bytes).unwrap();
282
283 let message = b"Test";
284 let signature = keypair.sign(message);
285
286 assert!(restored.verify(message, &signature).is_ok());
287 }
288}