1use crate::error::{Error, Result};
8use serde::{Deserialize, Serialize};
9use std::collections::HashMap;
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
13pub enum SignatureAlgorithm {
14 RsaPkcs1v15,
16 RsaPss,
18 Ecdsa,
20 EdDsa,
22 Dsa,
24}
25
26impl SignatureAlgorithm {
27 pub fn as_str(&self) -> &'static str {
29 match self {
30 SignatureAlgorithm::RsaPkcs1v15 => "rsa-pkcs1v15",
31 SignatureAlgorithm::RsaPss => "rsa-pss",
32 SignatureAlgorithm::Ecdsa => "ecdsa",
33 SignatureAlgorithm::EdDsa => "eddsa",
34 SignatureAlgorithm::Dsa => "dsa",
35 }
36 }
37
38 pub fn min_key_size(&self) -> usize {
40 match self {
41 SignatureAlgorithm::RsaPkcs1v15 => 2048,
42 SignatureAlgorithm::RsaPss => 2048,
43 SignatureAlgorithm::Ecdsa => 256,
44 SignatureAlgorithm::EdDsa => 256,
45 SignatureAlgorithm::Dsa => 2048,
46 }
47 }
48
49 pub fn is_secure(&self) -> bool {
51 match self {
52 SignatureAlgorithm::RsaPkcs1v15 => true,
53 SignatureAlgorithm::RsaPss => true,
54 SignatureAlgorithm::Ecdsa => true,
55 SignatureAlgorithm::EdDsa => true,
56 SignatureAlgorithm::Dsa => false, }
58 }
59}
60
61#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
63pub enum SignatureFormat {
64 Raw,
66 Base64,
68 Hex,
70 Pem,
72 Der,
74}
75
76impl SignatureFormat {
77 pub fn as_str(&self) -> &'static str {
79 match self {
80 SignatureFormat::Raw => "raw",
81 SignatureFormat::Base64 => "base64",
82 SignatureFormat::Hex => "hex",
83 SignatureFormat::Pem => "pem",
84 SignatureFormat::Der => "der",
85 }
86 }
87}
88
89#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
91pub enum PublicKeyFormat {
92 Pem,
94 Der,
96 Raw,
98 Jwk,
100 Ssh,
102}
103
104impl PublicKeyFormat {
105 pub fn as_str(&self) -> &'static str {
107 match self {
108 PublicKeyFormat::Pem => "pem",
109 PublicKeyFormat::Der => "der",
110 PublicKeyFormat::Raw => "raw",
111 PublicKeyFormat::Jwk => "jwk",
112 PublicKeyFormat::Ssh => "ssh",
113 }
114 }
115}
116
117#[derive(Debug, Clone, Serialize, Deserialize)]
119pub struct PublicKey {
120 pub algorithm: SignatureAlgorithm,
122 pub format: PublicKeyFormat,
124 pub data: Vec<u8>,
126 pub key_id: Option<String>,
128 pub usage: Option<KeyUsage>,
130}
131
132impl PublicKey {
133 pub fn new(algorithm: SignatureAlgorithm, format: PublicKeyFormat, data: Vec<u8>) -> Self {
135 Self {
136 algorithm,
137 format,
138 data,
139 key_id: None,
140 usage: None,
141 }
142 }
143
144 pub fn with_key_id(mut self, key_id: String) -> Self {
146 self.key_id = Some(key_id);
147 self
148 }
149
150 pub fn with_usage(mut self, usage: KeyUsage) -> Self {
152 self.usage = Some(usage);
153 self
154 }
155
156 pub fn key_size(&self) -> usize {
158 self.data.len() * 8
159 }
160
161 pub fn validate(&self) -> Result<()> {
163 if !self.algorithm.is_secure() {
164 return Err(Error::InvalidState(format!(
165 "Algorithm {:?} is not considered secure",
166 self.algorithm
167 )));
168 }
169
170 if self.key_size() < self.algorithm.min_key_size() {
171 return Err(Error::InvalidState(format!(
172 "Key size {} is below minimum {} for algorithm {:?}",
173 self.key_size(),
174 self.algorithm.min_key_size(),
175 self.algorithm
176 )));
177 }
178
179 Ok(())
180 }
181}
182
183#[derive(Debug, Clone, Serialize, Deserialize)]
185pub struct KeyUsage {
186 pub purposes: Vec<KeyPurpose>,
188 pub expires_at: Option<u64>,
190 pub not_before: Option<u64>,
192}
193
194#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
196pub enum KeyPurpose {
197 CodeSigning,
199 DocumentSigning,
201 TimestampSigning,
203 CertificateSigning,
205 Custom(String),
207}
208
209#[derive(Debug, Clone, Serialize, Deserialize)]
211pub struct Signature {
212 pub algorithm: SignatureAlgorithm,
214 pub format: SignatureFormat,
216 pub data: Vec<u8>,
218 pub key_id: Option<String>,
220 pub created_at: Option<u64>,
222 pub expires_at: Option<u64>,
224}
225
226impl Signature {
227 pub fn new(algorithm: SignatureAlgorithm, format: SignatureFormat, data: Vec<u8>) -> Self {
229 Self {
230 algorithm,
231 format,
232 data,
233 key_id: None,
234 created_at: None,
235 expires_at: None,
236 }
237 }
238
239 pub fn with_key_id(mut self, key_id: String) -> Self {
241 self.key_id = Some(key_id);
242 self
243 }
244
245 pub fn with_created_at(mut self, created_at: u64) -> Self {
247 self.created_at = Some(created_at);
248 self
249 }
250
251 pub fn with_expires_at(mut self, expires_at: u64) -> Self {
253 self.expires_at = Some(expires_at);
254 self
255 }
256
257 pub fn is_expired(&self) -> bool {
259 if let Some(expires_at) = self.expires_at {
260 let now = 0; now > expires_at
263 } else {
264 false
265 }
266 }
267
268 pub fn decode_data(&self) -> Result<Vec<u8>> {
270 match self.format {
271 SignatureFormat::Raw => Ok(self.data.clone()),
272 SignatureFormat::Base64 => {
273 use base64::{Engine as _, engine::general_purpose};
274 general_purpose::STANDARD
275 .decode(&self.data)
276 .map_err(|e| Error::InvalidState(format!("Invalid base64 signature: {}", e)))
277 }
278 SignatureFormat::Hex => hex::decode(&self.data)
279 .map_err(|e| Error::InvalidState(format!("Invalid hex signature: {}", e))),
280 SignatureFormat::Pem | SignatureFormat::Der => {
281 Err(Error::InvalidState(
283 "PEM/DER signature parsing not implemented".to_string(),
284 ))
285 }
286 }
287 }
288}
289
290#[derive(Debug, Clone)]
292pub struct SignatureConfig {
293 pub public_key: PublicKey,
295 pub signature: Signature,
297 pub signed_data: Option<Vec<u8>>,
299 pub ignore_expired: bool,
301}
302
303impl SignatureConfig {
304 pub fn new(public_key: PublicKey, signature: Signature) -> Self {
306 Self {
307 public_key,
308 signature,
309 signed_data: None,
310 ignore_expired: false,
311 }
312 }
313
314 pub fn with_signed_data(mut self, data: Vec<u8>) -> Self {
316 self.signed_data = Some(data);
317 self
318 }
319
320 pub fn with_ignore_expired(mut self, ignore: bool) -> Self {
322 self.ignore_expired = ignore;
323 self
324 }
325
326 pub fn validate(&self) -> Result<()> {
328 self.public_key.validate()?;
330
331 if self.public_key.algorithm != self.signature.algorithm {
333 return Err(Error::InvalidState(format!(
334 "Algorithm mismatch: key is {:?}, signature is {:?}",
335 self.public_key.algorithm, self.signature.algorithm
336 )));
337 }
338
339 if !self.ignore_expired && self.signature.is_expired() {
341 return Err(Error::InvalidState("Signature has expired".to_string()));
342 }
343
344 if let (Some(key_key_id), Some(sig_key_id)) =
346 (&self.public_key.key_id, &self.signature.key_id)
347 && key_key_id != sig_key_id
348 {
349 return Err(Error::InvalidState("Key ID mismatch".to_string()));
350 }
351
352 Ok(())
353 }
354}
355
356pub trait SignatureVerifier: Send + Sync {
358 fn verify(&self, data: &[u8], config: &SignatureConfig) -> Result<bool>;
360
361 fn algorithm(&self) -> SignatureAlgorithm;
363}
364
365pub struct MockVerifier {
367 algorithm: SignatureAlgorithm,
368 should_verify: bool,
369}
370
371impl MockVerifier {
372 pub fn new(algorithm: SignatureAlgorithm, should_verify: bool) -> Self {
374 Self {
375 algorithm,
376 should_verify,
377 }
378 }
379
380 pub fn set_should_verify(&mut self, should_verify: bool) {
382 self.should_verify = should_verify;
383 }
384}
385
386impl SignatureVerifier for MockVerifier {
387 fn verify(&self, _data: &[u8], config: &SignatureConfig) -> Result<bool> {
388 config.validate()?;
389 Ok(self.should_verify)
390 }
391
392 fn algorithm(&self) -> SignatureAlgorithm {
393 self.algorithm
394 }
395}
396
397pub struct SignatureManager {
399 verifiers: HashMap<SignatureAlgorithm, Box<dyn SignatureVerifier>>,
400}
401
402impl SignatureManager {
403 pub fn new() -> Self {
405 let mut manager = Self {
406 verifiers: HashMap::new(),
407 };
408
409 manager.add_mock_verifiers();
411 manager
412 }
413
414 fn add_mock_verifiers(&mut self) {
416 use SignatureAlgorithm::*;
417
418 self.verifiers
420 .insert(RsaPkcs1v15, Box::new(MockVerifier::new(RsaPkcs1v15, true)));
421 self.verifiers
422 .insert(RsaPss, Box::new(MockVerifier::new(RsaPss, true)));
423 self.verifiers
424 .insert(Ecdsa, Box::new(MockVerifier::new(Ecdsa, true)));
425 self.verifiers
426 .insert(EdDsa, Box::new(MockVerifier::new(EdDsa, true)));
427 self.verifiers
428 .insert(Dsa, Box::new(MockVerifier::new(Dsa, true)));
429 }
430
431 pub fn add_verifier(&mut self, verifier: Box<dyn SignatureVerifier>) {
433 self.verifiers.insert(verifier.algorithm(), verifier);
434 }
435
436 pub fn verify(&self, data: &[u8], config: &SignatureConfig) -> Result<bool> {
438 if let Some(verifier) = self.verifiers.get(&config.signature.algorithm) {
439 verifier.verify(data, config)
440 } else {
441 Err(Error::InvalidState(format!(
442 "No verifier available for algorithm {:?}",
443 config.signature.algorithm
444 )))
445 }
446 }
447
448 pub fn supports_algorithm(&self, algorithm: SignatureAlgorithm) -> bool {
450 self.verifiers.contains_key(&algorithm)
451 }
452
453 pub fn supported_algorithms(&self) -> Vec<SignatureAlgorithm> {
455 self.verifiers.keys().copied().collect()
456 }
457}
458
459impl Default for SignatureManager {
460 fn default() -> Self {
461 Self::new()
462 }
463}
464
465pub fn verify_signature(data: &[u8], config: &SignatureConfig) -> Result<bool> {
467 let manager = SignatureManager::new();
468 manager.verify(data, config)
469}
470
471#[cfg(test)]
472mod tests {
473 use super::*;
474
475 #[test]
476 fn test_signature_algorithm() {
477 assert_eq!(SignatureAlgorithm::RsaPkcs1v15.as_str(), "rsa-pkcs1v15");
478 assert_eq!(SignatureAlgorithm::RsaPkcs1v15.min_key_size(), 2048);
479 assert!(SignatureAlgorithm::RsaPkcs1v15.is_secure());
480 assert!(!SignatureAlgorithm::Dsa.is_secure());
481 }
482
483 #[test]
484 fn test_signature_format() {
485 assert_eq!(SignatureFormat::Base64.as_str(), "base64");
486 }
487
488 #[test]
489 fn test_public_key_format() {
490 assert_eq!(PublicKeyFormat::Pem.as_str(), "pem");
491 }
492
493 #[test]
494 fn test_public_key_creation() {
495 let key = PublicKey::new(
496 SignatureAlgorithm::RsaPkcs1v15,
497 PublicKeyFormat::Pem,
498 b"mock_key_data".to_vec(),
499 )
500 .with_key_id("test-key".to_string());
501
502 assert_eq!(key.algorithm, SignatureAlgorithm::RsaPkcs1v15);
503 assert_eq!(key.format, PublicKeyFormat::Pem);
504 assert_eq!(key.data, b"mock_key_data");
505 assert_eq!(key.key_id, Some("test-key".to_string()));
506 }
507
508 #[test]
509 fn test_public_key_validation() {
510 let key = PublicKey::new(
511 SignatureAlgorithm::RsaPkcs1v15,
512 PublicKeyFormat::Pem,
513 vec![0u8; 256], );
515 assert!(key.validate().is_ok());
516
517 let key = PublicKey::new(
519 SignatureAlgorithm::Dsa,
520 PublicKeyFormat::Pem,
521 vec![0u8; 256],
522 );
523 assert!(key.validate().is_err());
524
525 let key = PublicKey::new(
527 SignatureAlgorithm::RsaPkcs1v15,
528 PublicKeyFormat::Pem,
529 vec![0u8; 128], );
531 assert!(key.validate().is_err());
532 }
533
534 #[test]
535 fn test_signature_creation() {
536 let sig = Signature::new(
537 SignatureAlgorithm::RsaPkcs1v15,
538 SignatureFormat::Base64,
539 b"mock_signature".to_vec(),
540 )
541 .with_key_id("test-key".to_string())
542 .with_created_at(1234567890)
543 .with_expires_at(1234567990);
544
545 assert_eq!(sig.algorithm, SignatureAlgorithm::RsaPkcs1v15);
546 assert_eq!(sig.format, SignatureFormat::Base64);
547 assert_eq!(sig.data, b"mock_signature");
548 assert_eq!(sig.key_id, Some("test-key".to_string()));
549 assert_eq!(sig.created_at, Some(1234567890));
550 assert_eq!(sig.expires_at, Some(1234567990));
551 }
552
553 #[test]
554 fn test_signature_decode_data() {
555 let sig = Signature::new(
556 SignatureAlgorithm::RsaPkcs1v15,
557 SignatureFormat::Raw,
558 b"raw_data".to_vec(),
559 );
560 assert_eq!(sig.decode_data().unwrap(), b"raw_data");
561
562 let sig = Signature::new(
563 SignatureAlgorithm::RsaPkcs1v15,
564 SignatureFormat::Hex,
565 b"48656c6c6f".to_vec(), );
567 assert_eq!(sig.decode_data().unwrap(), b"Hello");
568 }
569
570 #[test]
571 fn test_signature_config() {
572 let key = PublicKey::new(
573 SignatureAlgorithm::RsaPkcs1v15,
574 PublicKeyFormat::Pem,
575 vec![0u8; 256],
576 );
577 let sig = Signature::new(
578 SignatureAlgorithm::RsaPkcs1v15,
579 SignatureFormat::Raw,
580 b"signature".to_vec(),
581 );
582
583 let config = SignatureConfig::new(key, sig)
584 .with_signed_data(b"data".to_vec())
585 .with_ignore_expired(true);
586
587 assert!(config.validate().is_ok());
588 }
589
590 #[test]
591 fn test_signature_config_algorithm_mismatch() {
592 let key = PublicKey::new(
593 SignatureAlgorithm::RsaPkcs1v15,
594 PublicKeyFormat::Pem,
595 vec![0u8; 256],
596 );
597 let sig = Signature::new(
598 SignatureAlgorithm::Ecdsa,
599 SignatureFormat::Raw,
600 b"signature".to_vec(),
601 );
602
603 let config = SignatureConfig::new(key, sig);
604 assert!(config.validate().is_err());
605 }
606
607 #[test]
608 fn test_mock_verifier() {
609 let verifier = MockVerifier::new(SignatureAlgorithm::RsaPkcs1v15, true);
610 assert_eq!(verifier.algorithm(), SignatureAlgorithm::RsaPkcs1v15);
611
612 let key = PublicKey::new(
613 SignatureAlgorithm::RsaPkcs1v15,
614 PublicKeyFormat::Pem,
615 vec![0u8; 256],
616 );
617 let sig = Signature::new(
618 SignatureAlgorithm::RsaPkcs1v15,
619 SignatureFormat::Raw,
620 b"signature".to_vec(),
621 );
622 let config = SignatureConfig::new(key, sig);
623
624 assert!(verifier.verify(b"data", &config).unwrap());
625
626 let verifier = MockVerifier::new(SignatureAlgorithm::RsaPkcs1v15, false);
627 assert!(!verifier.verify(b"data", &config).unwrap());
628 }
629
630 #[test]
631 fn test_signature_manager() {
632 let manager = SignatureManager::new();
633
634 assert!(manager.supports_algorithm(SignatureAlgorithm::RsaPkcs1v15));
635 assert!(manager.supports_algorithm(SignatureAlgorithm::Ecdsa));
636
637 let algorithms = manager.supported_algorithms();
638 assert!(algorithms.contains(&SignatureAlgorithm::RsaPkcs1v15));
639 assert!(algorithms.contains(&SignatureAlgorithm::Ecdsa));
640
641 let key = PublicKey::new(
642 SignatureAlgorithm::RsaPkcs1v15,
643 PublicKeyFormat::Pem,
644 vec![0u8; 256],
645 );
646 let sig = Signature::new(
647 SignatureAlgorithm::RsaPkcs1v15,
648 SignatureFormat::Raw,
649 b"signature".to_vec(),
650 );
651 let config = SignatureConfig::new(key, sig);
652
653 assert!(manager.verify(b"data", &config).unwrap());
655 }
656
657 #[test]
658 fn test_convenience_function() {
659 let key = PublicKey::new(
660 SignatureAlgorithm::RsaPkcs1v15,
661 PublicKeyFormat::Pem,
662 vec![0u8; 256],
663 );
664 let sig = Signature::new(
665 SignatureAlgorithm::RsaPkcs1v15,
666 SignatureFormat::Raw,
667 b"signature".to_vec(),
668 );
669 let config = SignatureConfig::new(key, sig);
670
671 assert!(verify_signature(b"data", &config).unwrap());
673 }
674}