cargocrypt/crypto/
algorithm.rs1use std::fmt;
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq)]
12pub enum Algorithm {
13 ChaCha20Poly1305,
22
23 Aes256Gcm,
32}
33
34pub trait AlgorithmExt {
36 fn key_length(&self) -> usize;
38
39 fn nonce_length(&self) -> usize;
41
42 fn tag_length(&self) -> usize;
44
45 fn is_authenticated(&self) -> bool;
47
48 fn security_level_bits(&self) -> usize;
50
51 fn is_timing_attack_resistant(&self) -> bool;
53
54 fn is_cache_timing_resistant(&self) -> bool;
56
57 fn is_post_quantum_secure(&self) -> bool;
59
60 fn algorithm_family(&self) -> AlgorithmFamily;
62
63}
64
65#[derive(Debug, Clone, Copy, PartialEq, Eq)]
67pub enum AlgorithmFamily {
68 StreamCipher,
70 BlockCipher,
72}
73
74impl AlgorithmExt for Algorithm {
75 fn key_length(&self) -> usize {
76 match self {
77 Algorithm::ChaCha20Poly1305 => 32, Algorithm::Aes256Gcm => 32, }
80 }
81
82 fn nonce_length(&self) -> usize {
83 match self {
84 Algorithm::ChaCha20Poly1305 => 12, Algorithm::Aes256Gcm => 12, }
87 }
88
89 fn tag_length(&self) -> usize {
90 match self {
91 Algorithm::ChaCha20Poly1305 => 16, Algorithm::Aes256Gcm => 16, }
94 }
95
96 fn is_authenticated(&self) -> bool {
97 true
99 }
100
101 fn security_level_bits(&self) -> usize {
102 match self {
103 Algorithm::ChaCha20Poly1305 => 128, Algorithm::Aes256Gcm => 128, }
106 }
107
108 fn is_timing_attack_resistant(&self) -> bool {
109 match self {
110 Algorithm::ChaCha20Poly1305 => true, Algorithm::Aes256Gcm => false, }
113 }
114
115 fn is_cache_timing_resistant(&self) -> bool {
116 match self {
117 Algorithm::ChaCha20Poly1305 => true, Algorithm::Aes256Gcm => false, }
120 }
121
122 fn is_post_quantum_secure(&self) -> bool {
123 match self {
124 Algorithm::ChaCha20Poly1305 => true, Algorithm::Aes256Gcm => true, }
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 Algorithm::ChaCha20Poly1305
151 }
152}
153
154impl Algorithm {
155 pub fn all() -> &'static [Algorithm] {
157 &[Algorithm::ChaCha20Poly1305, Algorithm::Aes256Gcm]
158 }
159
160 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 pub fn most_secure() -> Algorithm {
171 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 assert!(chacha.is_timing_attack_resistant());
202 assert!(chacha.is_cache_timing_resistant());
203
204 assert!(!aes.is_timing_attack_resistant());
206 assert!(!aes.is_cache_timing_resistant());
207
208 assert!(chacha.is_post_quantum_secure());
210 assert!(aes.is_post_quantum_secure());
211 }
212
213 #[test]
214 fn test_timing_resistance_selection() {
215 let resistant_algs = Algorithm::timing_resistant();
217 assert!(resistant_algs.contains(&Algorithm::ChaCha20Poly1305));
218 assert!(!resistant_algs.contains(&Algorithm::Aes256Gcm));
219
220 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 assert!(chacha.is_timing_attack_resistant());
231 assert!(chacha.is_cache_timing_resistant());
232
233 assert!(!aes.is_timing_attack_resistant());
235 assert!(!aes.is_cache_timing_resistant());
236
237 assert!(chacha.is_authenticated());
239 assert!(aes.is_authenticated());
240 }
241}