pqc_binary_format/
algorithm.rs

1//! Algorithm identifiers for supported post-quantum cryptographic algorithms.
2
3use serde::{Deserialize, Serialize};
4
5/// Algorithm identifier type
6pub type AlgorithmId = u16;
7
8/// Supported cryptographic algorithms with unique identifiers
9///
10/// Each algorithm has a unique 16-bit identifier used in the binary format.
11/// Identifiers are grouped by algorithm family for easy categorization.
12#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
13#[repr(u16)]
14pub enum Algorithm {
15    // Classical algorithms (0x0050-0x00FF)
16    /// Classical cryptography: X25519 + Ed25519 + AES-256-GCM
17    Classical = 0x0050,
18    /// Password-based classical encryption
19    PasswordClassical = 0x0051,
20
21    // Hybrid algorithms (0x0100-0x01FF)
22    /// Hybrid: ML-KEM-1024 + X25519 + ML-DSA-87 + Ed25519 + AES-256-GCM
23    Hybrid = 0x0100,
24
25    // Pure post-quantum algorithms (0x0200-0x02FF)
26    /// Post-quantum: ML-KEM-1024 + ML-DSA-87 + AES-256-GCM
27    PostQuantum = 0x0200,
28    /// Multi-algorithm runtime selection
29    MultiAlgorithm = 0x0201,
30    /// ML-KEM-1024 with AES-256-GCM
31    MlKem1024 = 0x0202,
32    /// Multi-KEM dual layer
33    MultiKem = 0x0203,
34    /// Multi-KEM triple layer
35    MultiKemTriple = 0x0204,
36    /// Quad-layer redundant security
37    QuadLayer = 0x0205,
38    /// Lattice-Code hybrid stack
39    LatticeCodeHybrid = 0x0206,
40    /// PQ3-Stack with forward secrecy
41    Pq3Stack = 0x0207,
42
43    // Max Secure series (0x0300-0x03FF)
44    /// Max Secure: PQ Lightweight
45    MaxSecureLightweight = 0x0300,
46    /// Max Secure: Pure PQ
47    MaxSecurePurePq = 0x0301,
48    /// Max Secure: Hybrid Transition
49    MaxSecureHybrid = 0x0302,
50    /// Max Secure: Stateless
51    MaxSecureStateless = 0x0303,
52    /// Max Secure: Crypto-Agile
53    MaxSecureCryptoAgile = 0x0304,
54    /// Max Secure: PQC + Zero-Knowledge
55    MaxSecurePqcZk = 0x0305,
56    /// Max Secure: Hybrid Transition
57    MaxSecureHybridTransition = 0x0306,
58
59    // FN-DSA series (Falcon-based signatures) (0x0400-0x04FF)
60    /// FN-DSA 512: Compact
61    FnDsa512Compact = 0x0400,
62    /// FN-DSA 1024: High-Security
63    FnDsa1024Security = 0x0401,
64    /// FN-DSA: Floating-Point Hardened
65    FnDsaFpHardened = 0x0402,
66    /// FN-DSA: Dual Signature
67    FnDsaDualSignature = 0x0403,
68    /// FN-DSA: Transition Stack
69    FnDsaTransition = 0x0404,
70    /// FN-DSA + Zero-Knowledge Stack
71    FnDsaZk = 0x0405,
72    /// FN-DSA + ZK Stack Enhanced
73    FnDsaZkStack = 0x0406,
74    /// FN-DSA: Transition Stack Enhanced
75    FnDsaTransitionStack = 0x0407,
76
77    // Experimental algorithms (0x0500-0x05FF)
78    /// Quantum-Inspired Lattice Fusion
79    QuantumLatticeFusion = 0x0500,
80    /// Post-ZK Homomorphic with LFHE 2023
81    PostZkHomomorphic = 0x0501,
82    /// Quantum-Resistant Consensus
83    QuantumResistantConsensus = 0x0502,
84    /// Entropy-Orchestrated PQ Stack
85    EntropyOrchestrated = 0x0503,
86    /// Lattice-Code Hybrid FN
87    LatticeCodeHybridFn = 0x0504,
88    /// AI-Synthesized Crypto-Agile
89    AiSynthesizedCryptoAgile = 0x0505,
90    /// Experimental Engine (generic)
91    Experimental = 0x0506,
92
93    // HQC Code-Based series (NIST 2025 Backup KEM) (0x0600-0x06FF)
94    /// HQC-128 (NIST Level 1, 128-bit security)
95    Hqc128 = 0x0600,
96    /// HQC-192 (NIST Level 3, 192-bit security)
97    Hqc192 = 0x0601,
98    /// HQC-256 (NIST Level 5, 256-bit security)
99    Hqc256 = 0x0602,
100
101    // NIST ML-KEM variants (FIPS 203) (0x0700-0x07FF)
102    /// ML-KEM-512 (NIST Level 1, 128-bit security)
103    MlKem512 = 0x0700,
104    /// ML-KEM-768 (NIST Level 3, 192-bit security)
105    MlKem768 = 0x0701,
106
107    // NIST ML-DSA variants (FIPS 204) (0x0800-0x08FF)
108    /// ML-DSA-44 (NIST Level 2, 128-bit security)
109    MlDsa44 = 0x0800,
110    /// ML-DSA-65 (NIST Level 3, 192-bit security)
111    MlDsa65 = 0x0801,
112    /// ML-DSA-87 (NIST Level 5, 256-bit security)
113    MlDsa87 = 0x0802,
114
115    // NIST SLH-DSA variants (FIPS 205) (0x0900-0x09FF)
116    /// SLH-DSA-SHA2-128s (NIST Level 1, small signatures)
117    SlhDsaSha2_128s = 0x0900,
118    /// SLH-DSA-SHA2-128f (NIST Level 1, fast signatures)
119    SlhDsaSha2_128f = 0x0901,
120    /// SLH-DSA-SHA2-192s (NIST Level 3, small signatures)
121    SlhDsaSha2_192s = 0x0902,
122    /// SLH-DSA-SHA2-192f (NIST Level 3, fast signatures)
123    SlhDsaSha2_192f = 0x0903,
124    /// SLH-DSA-SHA2-256s (NIST Level 5, small signatures)
125    SlhDsaSha2_256s = 0x0904,
126    /// SLH-DSA-SHA2-256f (NIST Level 5, fast signatures)
127    SlhDsaSha2_256f = 0x0905,
128}
129
130impl Algorithm {
131    /// Convert u16 identifier to Algorithm enum
132    ///
133    /// # Example
134    ///
135    /// ```
136    /// use pqc_binary_format::Algorithm;
137    ///
138    /// let algo = Algorithm::from_id(0x0100).unwrap();
139    /// assert_eq!(algo, Algorithm::Hybrid);
140    /// ```
141    #[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    /// Get u16 identifier for this algorithm
196    ///
197    /// # Example
198    ///
199    /// ```
200    /// use pqc_binary_format::Algorithm;
201    ///
202    /// assert_eq!(Algorithm::Hybrid.as_id(), 0x0100);
203    /// ```
204    #[must_use]
205    pub const fn as_id(self) -> u16 {
206        self as u16
207    }
208
209    /// Get human-readable name for this algorithm
210    ///
211    /// # Example
212    ///
213    /// ```
214    /// use pqc_binary_format::Algorithm;
215    ///
216    /// assert_eq!(Algorithm::Hybrid.name(), "Hybrid");
217    /// ```
218    #[must_use]
219    pub const fn name(self) -> &'static str {
220        match self {
221            Self::Classical => "Classical",
222            Self::PasswordClassical => "Password Classical",
223            Self::Hybrid => "Hybrid",
224            Self::PostQuantum => "Post-Quantum",
225            Self::MultiAlgorithm => "Multi-Algorithm",
226            Self::MlKem1024 => "ML-KEM-1024",
227            Self::MultiKem => "Multi-KEM Dual Layer",
228            Self::MultiKemTriple => "Multi-KEM Triple Layer",
229            Self::QuadLayer => "Quad-Layer",
230            Self::LatticeCodeHybrid => "Lattice-Code Hybrid",
231            Self::Pq3Stack => "PQ3-Stack",
232            Self::MaxSecureLightweight => "Max Secure: PQ Lightweight",
233            Self::MaxSecurePurePq => "Max Secure: Pure PQ",
234            Self::MaxSecureHybrid => "Max Secure: Hybrid",
235            Self::MaxSecureStateless => "Max Secure: Stateless",
236            Self::MaxSecureCryptoAgile => "Max Secure: Crypto-Agile",
237            Self::MaxSecurePqcZk => "Max Secure: PQC + ZK",
238            Self::FnDsa512Compact => "FN-DSA 512: Compact",
239            Self::FnDsa1024Security => "FN-DSA 1024: High-Security",
240            Self::FnDsaFpHardened => "FN-DSA: Floating-Point Hardened",
241            Self::FnDsaDualSignature => "FN-DSA: Dual Signature",
242            Self::FnDsaTransition => "FN-DSA: Transition Stack",
243            Self::FnDsaZk => "FN-DSA + ZK Stack",
244            Self::FnDsaZkStack => "FN-DSA + ZK Stack Enhanced",
245            Self::FnDsaTransitionStack => "FN-DSA: Transition Stack Enhanced",
246            Self::MaxSecureHybridTransition => "Max Secure: Hybrid Transition",
247            Self::QuantumLatticeFusion => "Quantum-Inspired Lattice Fusion",
248            Self::PostZkHomomorphic => "Post-ZK Homomorphic",
249            Self::QuantumResistantConsensus => "Quantum-Resistant Consensus",
250            Self::EntropyOrchestrated => "Entropy-Orchestrated",
251            Self::LatticeCodeHybridFn => "Lattice-Code Hybrid FN",
252            Self::AiSynthesizedCryptoAgile => "AI-Synthesized Crypto-Agile",
253            Self::Experimental => "Experimental Engine",
254            Self::Hqc128 => "HQC-128",
255            Self::Hqc192 => "HQC-192",
256            Self::Hqc256 => "HQC-256",
257            Self::MlKem512 => "ML-KEM-512",
258            Self::MlKem768 => "ML-KEM-768",
259            Self::MlDsa44 => "ML-DSA-44",
260            Self::MlDsa65 => "ML-DSA-65",
261            Self::MlDsa87 => "ML-DSA-87",
262            Self::SlhDsaSha2_128s => "SLH-DSA-SHA2-128s",
263            Self::SlhDsaSha2_128f => "SLH-DSA-SHA2-128f",
264            Self::SlhDsaSha2_192s => "SLH-DSA-SHA2-192s",
265            Self::SlhDsaSha2_192f => "SLH-DSA-SHA2-192f",
266            Self::SlhDsaSha2_256s => "SLH-DSA-SHA2-256s",
267            Self::SlhDsaSha2_256f => "SLH-DSA-SHA2-256f",
268        }
269    }
270
271    /// Check if this algorithm is marked as experimental
272    ///
273    /// Experimental algorithms may have reduced security guarantees
274    /// and are intended for research purposes.
275    #[must_use]
276    pub const fn is_experimental(self) -> bool {
277        matches!(
278            self,
279            Self::QuantumLatticeFusion
280                | Self::PostZkHomomorphic
281                | Self::QuantumResistantConsensus
282                | Self::EntropyOrchestrated
283                | Self::LatticeCodeHybridFn
284                | Self::AiSynthesizedCryptoAgile
285                | Self::Experimental
286        )
287    }
288
289    /// Get all defined algorithm identifiers
290    ///
291    /// Useful for iteration and testing.
292    #[must_use]
293    pub fn all() -> Vec<Self> {
294        vec![
295            Self::Classical,
296            Self::PasswordClassical,
297            Self::Hybrid,
298            Self::PostQuantum,
299            Self::MultiAlgorithm,
300            Self::MlKem1024,
301            Self::MultiKem,
302            Self::MultiKemTriple,
303            Self::QuadLayer,
304            Self::LatticeCodeHybrid,
305            Self::Pq3Stack,
306            Self::MaxSecureLightweight,
307            Self::MaxSecurePurePq,
308            Self::MaxSecureHybrid,
309            Self::MaxSecureStateless,
310            Self::MaxSecureCryptoAgile,
311            Self::MaxSecurePqcZk,
312            Self::MaxSecureHybridTransition,
313            Self::FnDsa512Compact,
314            Self::FnDsa1024Security,
315            Self::FnDsaFpHardened,
316            Self::FnDsaDualSignature,
317            Self::FnDsaTransition,
318            Self::FnDsaZk,
319            Self::FnDsaZkStack,
320            Self::FnDsaTransitionStack,
321            Self::QuantumLatticeFusion,
322            Self::PostZkHomomorphic,
323            Self::QuantumResistantConsensus,
324            Self::EntropyOrchestrated,
325            Self::LatticeCodeHybridFn,
326            Self::AiSynthesizedCryptoAgile,
327            Self::Experimental,
328            Self::Hqc128,
329            Self::Hqc192,
330            Self::Hqc256,
331            Self::MlKem512,
332            Self::MlKem768,
333            Self::MlDsa44,
334            Self::MlDsa65,
335            Self::MlDsa87,
336            Self::SlhDsaSha2_128s,
337            Self::SlhDsaSha2_128f,
338            Self::SlhDsaSha2_192s,
339            Self::SlhDsaSha2_192f,
340            Self::SlhDsaSha2_256s,
341            Self::SlhDsaSha2_256f,
342        ]
343    }
344}
345
346#[cfg(test)]
347mod tests {
348    use super::*;
349
350    #[test]
351    fn test_algorithm_roundtrip() {
352        for algo in Algorithm::all() {
353            let id = algo.as_id();
354            let recovered = Algorithm::from_id(id).unwrap();
355            assert_eq!(algo, recovered);
356        }
357    }
358
359    #[test]
360    fn test_invalid_algorithm_id() {
361        assert!(Algorithm::from_id(0xFFFF).is_none());
362    }
363
364    #[test]
365    fn test_experimental_detection() {
366        assert!(Algorithm::QuantumLatticeFusion.is_experimental());
367        assert!(!Algorithm::Hybrid.is_experimental());
368    }
369}