Skip to main content

cargocrypt/crypto/
algorithm.rs

1//! Algorithm types and traits for cryptographic operations
2//!
3//! This module defines cryptographic algorithms with security best practices:
4//! - Only authenticated encryption algorithms are supported
5//! - Algorithms are evaluated for side-channel resistance
6//! - Security properties are clearly documented
7
8use std::fmt;
9
10/// Supported cryptographic algorithms with security properties
11#[derive(Debug, Clone, Copy, PartialEq, Eq)]
12pub enum Algorithm {
13    /// ChaCha20-Poly1305 authenticated encryption
14    /// 
15    /// Security properties:
16    /// - Authenticated encryption with associated data (AEAD)
17    /// - Resistant to timing attacks
18    /// - No known cache-timing vulnerabilities
19    /// - Post-quantum secure (against known algorithms)
20    /// - Stream cipher with polynomial authenticator
21    ChaCha20Poly1305,
22    
23    /// AES-256-GCM authenticated encryption (future implementation)
24    /// 
25    /// Security properties:
26    /// - Authenticated encryption with associated data (AEAD)
27    /// - Hardware acceleration on many platforms
28    /// - Potential cache-timing vulnerabilities in software implementations
29    /// - Post-quantum secure (against known algorithms)
30    /// - Block cipher with galois counter mode
31    Aes256Gcm,
32}
33
34/// Extension trait for algorithm properties and security characteristics
35pub trait AlgorithmExt {
36    /// Get the key length in bytes
37    fn key_length(&self) -> usize;
38    
39    /// Get the nonce/IV length in bytes
40    fn nonce_length(&self) -> usize;
41    
42    /// Get the authentication tag length in bytes
43    fn tag_length(&self) -> usize;
44    
45    /// Check if this is an authenticated encryption algorithm
46    fn is_authenticated(&self) -> bool;
47    
48    /// Get the security level in bits (minimum of key size and tag size)
49    fn security_level_bits(&self) -> usize;
50    
51    /// Check if the algorithm is resistant to timing attacks
52    fn is_timing_attack_resistant(&self) -> bool;
53    
54    /// Check if the algorithm is resistant to cache-timing attacks
55    fn is_cache_timing_resistant(&self) -> bool;
56    
57    /// Check if the algorithm is believed to be post-quantum secure
58    fn is_post_quantum_secure(&self) -> bool;
59    
60    /// Get algorithm family (stream cipher, block cipher, etc.)
61    fn algorithm_family(&self) -> AlgorithmFamily;
62    
63}
64
65/// Algorithm family classification
66#[derive(Debug, Clone, Copy, PartialEq, Eq)]
67pub enum AlgorithmFamily {
68    /// Stream cipher with polynomial authenticator
69    StreamCipher,
70    /// Block cipher with authenticated mode
71    BlockCipher,
72}
73
74impl AlgorithmExt for Algorithm {
75    fn key_length(&self) -> usize {
76        match self {
77            Algorithm::ChaCha20Poly1305 => 32, // 256 bits
78            Algorithm::Aes256Gcm => 32,        // 256 bits
79        }
80    }
81    
82    fn nonce_length(&self) -> usize {
83        match self {
84            Algorithm::ChaCha20Poly1305 => 12, // 96 bits
85            Algorithm::Aes256Gcm => 12,        // 96 bits
86        }
87    }
88    
89    fn tag_length(&self) -> usize {
90        match self {
91            Algorithm::ChaCha20Poly1305 => 16, // 128 bits
92            Algorithm::Aes256Gcm => 16,        // 128 bits
93        }
94    }
95    
96    fn is_authenticated(&self) -> bool {
97        // All our algorithms are authenticated encryption
98        true
99    }
100    
101    fn security_level_bits(&self) -> usize {
102        match self {
103            Algorithm::ChaCha20Poly1305 => 128, // Limited by Poly1305 tag
104            Algorithm::Aes256Gcm => 128,        // Limited by GCM tag
105        }
106    }
107    
108    fn is_timing_attack_resistant(&self) -> bool {
109        match self {
110            Algorithm::ChaCha20Poly1305 => true,  // Software implementation is constant-time
111            Algorithm::Aes256Gcm => false,        // Software AES can have timing issues
112        }
113    }
114    
115    fn is_cache_timing_resistant(&self) -> bool {
116        match self {
117            Algorithm::ChaCha20Poly1305 => true,  // No lookup tables in ChaCha20
118            Algorithm::Aes256Gcm => false,        // AES S-boxes can cause cache timing
119        }
120    }
121    
122    fn is_post_quantum_secure(&self) -> bool {
123        match self {
124            Algorithm::ChaCha20Poly1305 => true,  // Symmetric crypto is PQ-secure
125            Algorithm::Aes256Gcm => true,         // Symmetric crypto is PQ-secure
126        }
127    }
128    
129    fn algorithm_family(&self) -> AlgorithmFamily {
130        match self {
131            Algorithm::ChaCha20Poly1305 => AlgorithmFamily::StreamCipher,
132            Algorithm::Aes256Gcm => AlgorithmFamily::BlockCipher,
133        }
134    }
135    
136}
137
138impl fmt::Display for Algorithm {
139    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
140        match self {
141            Algorithm::ChaCha20Poly1305 => write!(f, "ChaCha20-Poly1305"),
142            Algorithm::Aes256Gcm => write!(f, "AES-256-GCM"),
143        }
144    }
145}
146
147impl Default for Algorithm {
148    fn default() -> Self {
149        // ChaCha20-Poly1305 is preferred due to better side-channel resistance
150        Algorithm::ChaCha20Poly1305
151    }
152}
153
154impl Algorithm {
155    /// Get all supported algorithms
156    pub fn all() -> &'static [Algorithm] {
157        &[Algorithm::ChaCha20Poly1305, Algorithm::Aes256Gcm]
158    }
159    
160    /// Get algorithms suitable for timing-attack resistance
161    pub fn timing_resistant() -> Vec<Algorithm> {
162        Self::all()
163            .iter()
164            .filter(|alg| alg.is_timing_attack_resistant())
165            .copied()
166            .collect()
167    }
168    
169    /// Get the most secure algorithm for side-channel resistance
170    pub fn most_secure() -> Algorithm {
171        // Prefer ChaCha20-Poly1305 for its side-channel resistance
172        Algorithm::ChaCha20Poly1305
173    }
174}
175
176#[cfg(test)]
177mod tests {
178    use super::*;
179    
180    #[test]
181    fn test_algorithm_properties() {
182        let alg = Algorithm::ChaCha20Poly1305;
183        assert_eq!(alg.key_length(), 32);
184        assert_eq!(alg.nonce_length(), 12);
185        assert_eq!(alg.tag_length(), 16);
186        assert!(alg.is_authenticated());
187        assert_eq!(alg.security_level_bits(), 128);
188        assert!(alg.is_timing_attack_resistant());
189        assert!(alg.is_cache_timing_resistant());
190        assert!(alg.is_post_quantum_secure());
191        assert_eq!(alg.algorithm_family(), AlgorithmFamily::StreamCipher);
192        assert_eq!(alg.to_string(), "ChaCha20-Poly1305");
193    }
194    
195    #[test]
196    fn test_algorithm_security_comparison() {
197        let chacha = Algorithm::ChaCha20Poly1305;
198        let aes = Algorithm::Aes256Gcm;
199        
200        // ChaCha20-Poly1305 should be more resistant to side-channel attacks
201        assert!(chacha.is_timing_attack_resistant());
202        assert!(chacha.is_cache_timing_resistant());
203        
204        // AES-GCM has potential vulnerabilities in software implementations
205        assert!(!aes.is_timing_attack_resistant());
206        assert!(!aes.is_cache_timing_resistant());
207        
208        // Both should be post-quantum secure (symmetric crypto)
209        assert!(chacha.is_post_quantum_secure());
210        assert!(aes.is_post_quantum_secure());
211    }
212    
213    #[test]
214    fn test_timing_resistance_selection() {
215        // Test timing-resistant algorithms
216        let resistant_algs = Algorithm::timing_resistant();
217        assert!(resistant_algs.contains(&Algorithm::ChaCha20Poly1305));
218        assert!(!resistant_algs.contains(&Algorithm::Aes256Gcm));
219        
220        // Most secure algorithm should be ChaCha20-Poly1305
221        assert_eq!(Algorithm::most_secure(), Algorithm::ChaCha20Poly1305);
222    }
223    
224    #[test]
225    fn test_algorithm_security_properties() {
226        let chacha = Algorithm::ChaCha20Poly1305;
227        let aes = Algorithm::Aes256Gcm;
228        
229        // ChaCha20-Poly1305 should be timing attack resistant
230        assert!(chacha.is_timing_attack_resistant());
231        assert!(chacha.is_cache_timing_resistant());
232        
233        // AES-GCM has potential timing vulnerabilities
234        assert!(!aes.is_timing_attack_resistant());
235        assert!(!aes.is_cache_timing_resistant());
236        
237        // Both should be authenticated
238        assert!(chacha.is_authenticated());
239        assert!(aes.is_authenticated());
240    }
241}