1use serde::{Deserialize, Serialize};
4
5pub type AlgorithmId = u16;
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
13#[repr(u16)]
14pub enum Algorithm {
15 Classical = 0x0050,
18 PasswordClassical = 0x0051,
20
21 Hybrid = 0x0100,
24
25 PostQuantum = 0x0200,
28 MultiAlgorithm = 0x0201,
30 MlKem1024 = 0x0202,
32 MultiKem = 0x0203,
34 MultiKemTriple = 0x0204,
36 QuadLayer = 0x0205,
38 LatticeCodeHybrid = 0x0206,
40 Pq3Stack = 0x0207,
42
43 MaxSecureLightweight = 0x0300,
46 MaxSecurePurePq = 0x0301,
48 MaxSecureHybrid = 0x0302,
50 MaxSecureStateless = 0x0303,
52 MaxSecureCryptoAgile = 0x0304,
54 MaxSecurePqcZk = 0x0305,
56 MaxSecureHybridTransition = 0x0306,
58
59 FnDsa512Compact = 0x0400,
62 FnDsa1024Security = 0x0401,
64 FnDsaFpHardened = 0x0402,
66 FnDsaDualSignature = 0x0403,
68 FnDsaTransition = 0x0404,
70 FnDsaZk = 0x0405,
72 FnDsaZkStack = 0x0406,
74 FnDsaTransitionStack = 0x0407,
76
77 QuantumLatticeFusion = 0x0500,
80 PostZkHomomorphic = 0x0501,
82 QuantumResistantConsensus = 0x0502,
84 EntropyOrchestrated = 0x0503,
86 LatticeCodeHybridFn = 0x0504,
88 AiSynthesizedCryptoAgile = 0x0505,
90 Experimental = 0x0506,
92
93 Hqc128 = 0x0600,
96 Hqc192 = 0x0601,
98 Hqc256 = 0x0602,
100
101 MlKem512 = 0x0700,
104 MlKem768 = 0x0701,
106
107 MlDsa44 = 0x0800,
110 MlDsa65 = 0x0801,
112 MlDsa87 = 0x0802,
114
115 SlhDsaSha2_128s = 0x0900,
118 SlhDsaSha2_128f = 0x0901,
120 SlhDsaSha2_192s = 0x0902,
122 SlhDsaSha2_192f = 0x0903,
124 SlhDsaSha2_256s = 0x0904,
126 SlhDsaSha2_256f = 0x0905,
128}
129
130impl Algorithm {
131 #[must_use]
142 pub fn from_id(id: u16) -> Option<Self> {
143 match id {
144 0x0050 => Some(Self::Classical),
145 0x0051 => Some(Self::PasswordClassical),
146 0x0100 => Some(Self::Hybrid),
147 0x0200 => Some(Self::PostQuantum),
148 0x0201 => Some(Self::MultiAlgorithm),
149 0x0202 => Some(Self::MlKem1024),
150 0x0203 => Some(Self::MultiKem),
151 0x0204 => Some(Self::MultiKemTriple),
152 0x0205 => Some(Self::QuadLayer),
153 0x0206 => Some(Self::LatticeCodeHybrid),
154 0x0207 => Some(Self::Pq3Stack),
155 0x0300 => Some(Self::MaxSecureLightweight),
156 0x0301 => Some(Self::MaxSecurePurePq),
157 0x0302 => Some(Self::MaxSecureHybrid),
158 0x0303 => Some(Self::MaxSecureStateless),
159 0x0304 => Some(Self::MaxSecureCryptoAgile),
160 0x0305 => Some(Self::MaxSecurePqcZk),
161 0x0306 => Some(Self::MaxSecureHybridTransition),
162 0x0400 => Some(Self::FnDsa512Compact),
163 0x0401 => Some(Self::FnDsa1024Security),
164 0x0402 => Some(Self::FnDsaFpHardened),
165 0x0403 => Some(Self::FnDsaDualSignature),
166 0x0404 => Some(Self::FnDsaTransition),
167 0x0405 => Some(Self::FnDsaZk),
168 0x0406 => Some(Self::FnDsaZkStack),
169 0x0407 => Some(Self::FnDsaTransitionStack),
170 0x0500 => Some(Self::QuantumLatticeFusion),
171 0x0501 => Some(Self::PostZkHomomorphic),
172 0x0502 => Some(Self::QuantumResistantConsensus),
173 0x0503 => Some(Self::EntropyOrchestrated),
174 0x0504 => Some(Self::LatticeCodeHybridFn),
175 0x0505 => Some(Self::AiSynthesizedCryptoAgile),
176 0x0506 => Some(Self::Experimental),
177 0x0600 => Some(Self::Hqc128),
178 0x0601 => Some(Self::Hqc192),
179 0x0602 => Some(Self::Hqc256),
180 0x0700 => Some(Self::MlKem512),
181 0x0701 => Some(Self::MlKem768),
182 0x0800 => Some(Self::MlDsa44),
183 0x0801 => Some(Self::MlDsa65),
184 0x0802 => Some(Self::MlDsa87),
185 0x0900 => Some(Self::SlhDsaSha2_128s),
186 0x0901 => Some(Self::SlhDsaSha2_128f),
187 0x0902 => Some(Self::SlhDsaSha2_192s),
188 0x0903 => Some(Self::SlhDsaSha2_192f),
189 0x0904 => Some(Self::SlhDsaSha2_256s),
190 0x0905 => Some(Self::SlhDsaSha2_256f),
191 _ => None,
192 }
193 }
194
195 #[must_use]
212 pub fn from_name(name: &str) -> Option<Self> {
213 let lower = name.to_lowercase();
214 let compact: String = lower.chars().filter(|c| c.is_alphanumeric()).collect();
216 Self::all().into_iter().find(|algo| {
217 let canon = algo.canonical_name();
218 let canon_compact: String = canon.chars().filter(char::is_ascii_alphanumeric).collect();
219 lower == canon || compact == canon_compact
220 })
221 }
222
223 #[must_use]
228 pub const fn canonical_name(self) -> &'static str {
229 match self {
230 Self::Classical => "classical",
231 Self::PasswordClassical => "password-classical",
232 Self::Hybrid => "hybrid",
233 Self::PostQuantum => "post-quantum",
234 Self::MultiAlgorithm => "multi-algorithm",
235 Self::MlKem1024 => "ml-kem-1024",
236 Self::MultiKem => "multi-kem",
237 Self::MultiKemTriple => "multi-kem-triple",
238 Self::QuadLayer => "quad-layer",
239 Self::LatticeCodeHybrid => "lattice-code-hybrid",
240 Self::Pq3Stack => "pq3-stack",
241 Self::MaxSecureLightweight => "max-secure-lightweight",
242 Self::MaxSecurePurePq => "max-secure-pure-pq",
243 Self::MaxSecureHybrid => "max-secure-hybrid",
244 Self::MaxSecureStateless => "max-secure-stateless",
245 Self::MaxSecureCryptoAgile => "max-secure-crypto-agile",
246 Self::MaxSecurePqcZk => "max-secure-pqc-zk",
247 Self::MaxSecureHybridTransition => "max-secure-hybrid-transition",
248 Self::FnDsa512Compact => "fn-dsa-512-compact",
249 Self::FnDsa1024Security => "fn-dsa-1024-security",
250 Self::FnDsaFpHardened => "fn-dsa-fp-hardened",
251 Self::FnDsaDualSignature => "fn-dsa-dual-signature",
252 Self::FnDsaTransition => "fn-dsa-transition",
253 Self::FnDsaZk => "fn-dsa-zk",
254 Self::FnDsaZkStack => "fn-dsa-zk-stack",
255 Self::FnDsaTransitionStack => "fn-dsa-transition-stack",
256 Self::QuantumLatticeFusion => "quantum-lattice-fusion",
257 Self::PostZkHomomorphic => "post-zk-homomorphic",
258 Self::QuantumResistantConsensus => "quantum-resistant-consensus",
259 Self::EntropyOrchestrated => "entropy-orchestrated",
260 Self::LatticeCodeHybridFn => "lattice-code-hybrid-fn",
261 Self::AiSynthesizedCryptoAgile => "ai-synthesized-crypto-agile",
262 Self::Experimental => "experimental",
263 Self::Hqc128 => "hqc-128",
264 Self::Hqc192 => "hqc-192",
265 Self::Hqc256 => "hqc-256",
266 Self::MlKem512 => "ml-kem-512",
267 Self::MlKem768 => "ml-kem-768",
268 Self::MlDsa44 => "ml-dsa-44",
269 Self::MlDsa65 => "ml-dsa-65",
270 Self::MlDsa87 => "ml-dsa-87",
271 Self::SlhDsaSha2_128s => "slh-dsa-sha2-128s",
272 Self::SlhDsaSha2_128f => "slh-dsa-sha2-128f",
273 Self::SlhDsaSha2_192s => "slh-dsa-sha2-192s",
274 Self::SlhDsaSha2_192f => "slh-dsa-sha2-192f",
275 Self::SlhDsaSha2_256s => "slh-dsa-sha2-256s",
276 Self::SlhDsaSha2_256f => "slh-dsa-sha2-256f",
277 }
278 }
279
280 #[must_use]
290 pub const fn as_id(self) -> u16 {
291 self as u16
292 }
293
294 #[must_use]
304 pub const fn name(self) -> &'static str {
305 match self {
306 Self::Classical => "Classical",
307 Self::PasswordClassical => "Password Classical",
308 Self::Hybrid => "Hybrid",
309 Self::PostQuantum => "Post-Quantum",
310 Self::MultiAlgorithm => "Multi-Algorithm",
311 Self::MlKem1024 => "ML-KEM-1024",
312 Self::MultiKem => "Multi-KEM Dual Layer",
313 Self::MultiKemTriple => "Multi-KEM Triple Layer",
314 Self::QuadLayer => "Quad-Layer",
315 Self::LatticeCodeHybrid => "Lattice-Code Hybrid",
316 Self::Pq3Stack => "PQ3-Stack",
317 Self::MaxSecureLightweight => "Max Secure: PQ Lightweight",
318 Self::MaxSecurePurePq => "Max Secure: Pure PQ",
319 Self::MaxSecureHybrid => "Max Secure: Hybrid",
320 Self::MaxSecureStateless => "Max Secure: Stateless",
321 Self::MaxSecureCryptoAgile => "Max Secure: Crypto-Agile",
322 Self::MaxSecurePqcZk => "Max Secure: PQC + ZK",
323 Self::FnDsa512Compact => "FN-DSA 512: Compact",
324 Self::FnDsa1024Security => "FN-DSA 1024: High-Security",
325 Self::FnDsaFpHardened => "FN-DSA: Floating-Point Hardened",
326 Self::FnDsaDualSignature => "FN-DSA: Dual Signature",
327 Self::FnDsaTransition => "FN-DSA: Transition Stack",
328 Self::FnDsaZk => "FN-DSA + ZK Stack",
329 Self::FnDsaZkStack => "FN-DSA + ZK Stack Enhanced",
330 Self::FnDsaTransitionStack => "FN-DSA: Transition Stack Enhanced",
331 Self::MaxSecureHybridTransition => "Max Secure: Hybrid Transition",
332 Self::QuantumLatticeFusion => "Quantum-Inspired Lattice Fusion",
333 Self::PostZkHomomorphic => "Post-ZK Homomorphic",
334 Self::QuantumResistantConsensus => "Quantum-Resistant Consensus",
335 Self::EntropyOrchestrated => "Entropy-Orchestrated",
336 Self::LatticeCodeHybridFn => "Lattice-Code Hybrid FN",
337 Self::AiSynthesizedCryptoAgile => "AI-Synthesized Crypto-Agile",
338 Self::Experimental => "Experimental Engine",
339 Self::Hqc128 => "HQC-128",
340 Self::Hqc192 => "HQC-192",
341 Self::Hqc256 => "HQC-256",
342 Self::MlKem512 => "ML-KEM-512",
343 Self::MlKem768 => "ML-KEM-768",
344 Self::MlDsa44 => "ML-DSA-44",
345 Self::MlDsa65 => "ML-DSA-65",
346 Self::MlDsa87 => "ML-DSA-87",
347 Self::SlhDsaSha2_128s => "SLH-DSA-SHA2-128s",
348 Self::SlhDsaSha2_128f => "SLH-DSA-SHA2-128f",
349 Self::SlhDsaSha2_192s => "SLH-DSA-SHA2-192s",
350 Self::SlhDsaSha2_192f => "SLH-DSA-SHA2-192f",
351 Self::SlhDsaSha2_256s => "SLH-DSA-SHA2-256s",
352 Self::SlhDsaSha2_256f => "SLH-DSA-SHA2-256f",
353 }
354 }
355
356 #[must_use]
361 pub const fn is_experimental(self) -> bool {
362 matches!(
363 self,
364 Self::QuantumLatticeFusion
365 | Self::PostZkHomomorphic
366 | Self::QuantumResistantConsensus
367 | Self::EntropyOrchestrated
368 | Self::LatticeCodeHybridFn
369 | Self::AiSynthesizedCryptoAgile
370 | Self::Experimental
371 )
372 }
373
374 #[must_use]
378 pub fn all() -> Vec<Self> {
379 vec![
380 Self::Classical,
381 Self::PasswordClassical,
382 Self::Hybrid,
383 Self::PostQuantum,
384 Self::MultiAlgorithm,
385 Self::MlKem1024,
386 Self::MultiKem,
387 Self::MultiKemTriple,
388 Self::QuadLayer,
389 Self::LatticeCodeHybrid,
390 Self::Pq3Stack,
391 Self::MaxSecureLightweight,
392 Self::MaxSecurePurePq,
393 Self::MaxSecureHybrid,
394 Self::MaxSecureStateless,
395 Self::MaxSecureCryptoAgile,
396 Self::MaxSecurePqcZk,
397 Self::MaxSecureHybridTransition,
398 Self::FnDsa512Compact,
399 Self::FnDsa1024Security,
400 Self::FnDsaFpHardened,
401 Self::FnDsaDualSignature,
402 Self::FnDsaTransition,
403 Self::FnDsaZk,
404 Self::FnDsaZkStack,
405 Self::FnDsaTransitionStack,
406 Self::QuantumLatticeFusion,
407 Self::PostZkHomomorphic,
408 Self::QuantumResistantConsensus,
409 Self::EntropyOrchestrated,
410 Self::LatticeCodeHybridFn,
411 Self::AiSynthesizedCryptoAgile,
412 Self::Experimental,
413 Self::Hqc128,
414 Self::Hqc192,
415 Self::Hqc256,
416 Self::MlKem512,
417 Self::MlKem768,
418 Self::MlDsa44,
419 Self::MlDsa65,
420 Self::MlDsa87,
421 Self::SlhDsaSha2_128s,
422 Self::SlhDsaSha2_128f,
423 Self::SlhDsaSha2_192s,
424 Self::SlhDsaSha2_192f,
425 Self::SlhDsaSha2_256s,
426 Self::SlhDsaSha2_256f,
427 ]
428 }
429}
430
431#[cfg(test)]
432mod tests {
433 use super::*;
434
435 #[test]
436 fn test_algorithm_roundtrip() {
437 for algo in Algorithm::all() {
438 let id = algo.as_id();
439 let recovered = Algorithm::from_id(id).unwrap();
440 assert_eq!(algo, recovered);
441 }
442 }
443
444 #[test]
445 fn test_invalid_algorithm_id() {
446 assert!(Algorithm::from_id(0xFFFF).is_none());
447 }
448
449 #[test]
450 fn test_experimental_detection() {
451 assert!(Algorithm::QuantumLatticeFusion.is_experimental());
452 assert!(!Algorithm::Hybrid.is_experimental());
453 }
454}