pqc_binary_format/
metadata.rs

1//! Metadata structures for algorithm-specific parameters.
2
3use crate::{error::CryptoError, Result};
4use serde::{Deserialize, Serialize};
5use std::collections::HashMap;
6
7/// Algorithm-specific metadata container
8///
9/// Contains all parameters needed to decrypt and verify the encrypted data.
10#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
11pub struct PqcMetadata {
12    /// Key encapsulation parameters (optional)
13    pub kem_params: Option<KemParameters>,
14    /// Signature parameters (optional)
15    pub sig_params: Option<SigParameters>,
16    /// Encryption parameters (required)
17    pub enc_params: EncParameters,
18    /// Compression parameters (optional)
19    pub compression_params: Option<CompressionParameters>,
20    /// Additional custom parameters
21    pub custom: HashMap<String, Vec<u8>>,
22}
23
24/// Key Encapsulation Mechanism (KEM) parameters
25///
26/// Used by algorithms that employ key encapsulation (ML-KEM, etc.)
27#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
28pub struct KemParameters {
29    /// Public key for KEM
30    pub public_key: Vec<u8>,
31    /// Encapsulated ciphertext
32    pub ciphertext: Vec<u8>,
33    /// Algorithm-specific parameters
34    pub params: HashMap<String, Vec<u8>>,
35}
36
37/// Digital signature parameters
38///
39/// Used by algorithms that include signatures (ML-DSA, Ed25519, etc.)
40#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
41pub struct SigParameters {
42    /// Public key for signature verification
43    pub public_key: Vec<u8>,
44    /// Digital signature
45    pub signature: Vec<u8>,
46    /// Algorithm-specific parameters
47    pub params: HashMap<String, Vec<u8>>,
48}
49
50/// Symmetric encryption parameters
51///
52/// Required for all algorithms as they all use symmetric encryption
53/// for the actual data encryption.
54#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
55pub struct EncParameters {
56    /// Initialization vector / nonce
57    pub iv: Vec<u8>,
58    /// Authentication tag (for AEAD ciphers like AES-GCM)
59    pub tag: Vec<u8>,
60    /// Algorithm-specific parameters
61    pub params: HashMap<String, Vec<u8>>,
62}
63
64/// Compression algorithm parameters
65///
66/// Indicates if compression was applied before encryption.
67#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
68pub struct CompressionParameters {
69    /// Compression algorithm name (e.g., "zstd", "brotli", "lz4")
70    pub algorithm: String,
71    /// Compression level (0-9)
72    pub level: u8,
73    /// Original size before compression
74    pub original_size: u64,
75    /// Algorithm-specific parameters
76    pub params: HashMap<String, Vec<u8>>,
77}
78
79impl PqcMetadata {
80    /// Create new empty metadata with default encryption parameters
81    ///
82    /// # Example
83    ///
84    /// ```
85    /// use pqc_binary_format::PqcMetadata;
86    ///
87    /// let mut metadata = PqcMetadata::new();
88    /// metadata.enc_params.iv = vec![0; 12];
89    /// metadata.enc_params.tag = vec![0; 16];
90    /// ```
91    #[must_use]
92    pub fn new() -> Self {
93        Self {
94            kem_params: None,
95            sig_params: None,
96            enc_params: EncParameters {
97                iv: Vec::new(),
98                tag: Vec::new(),
99                params: HashMap::new(),
100            },
101            compression_params: None,
102            custom: HashMap::new(),
103        }
104    }
105
106    /// Validate metadata structure
107    ///
108    /// Ensures all required fields are present and valid.
109    pub fn validate(&self) -> Result<()> {
110        // Validate encryption parameters (required)
111        if self.enc_params.iv.is_empty() {
112            return Err(CryptoError::MetadataError(
113                "Encryption IV cannot be empty".to_string(),
114            ));
115        }
116
117        // Additional validation can be added here for specific parameters
118        Ok(())
119    }
120
121    /// Add custom parameter
122    ///
123    /// # Example
124    ///
125    /// ```
126    /// use pqc_binary_format::PqcMetadata;
127    ///
128    /// let mut metadata = PqcMetadata::new();
129    /// metadata.add_custom("my_param".to_string(), vec![1, 2, 3]);
130    /// ```
131    pub fn add_custom(&mut self, key: String, value: Vec<u8>) {
132        self.custom.insert(key, value);
133    }
134
135    /// Get custom parameter
136    ///
137    /// # Example
138    ///
139    /// ```
140    /// use pqc_binary_format::PqcMetadata;
141    ///
142    /// let mut metadata = PqcMetadata::new();
143    /// metadata.add_custom("my_param".to_string(), vec![1, 2, 3]);
144    /// assert_eq!(metadata.get_custom("my_param"), Some(&[1, 2, 3][..]));
145    /// ```
146    #[must_use]
147    pub fn get_custom(&self, key: &str) -> Option<&[u8]> {
148        self.custom.get(key).map(Vec::as_slice)
149    }
150}
151
152impl Default for PqcMetadata {
153    fn default() -> Self {
154        Self::new()
155    }
156}
157
158#[cfg(test)]
159mod tests {
160    use super::*;
161
162    #[test]
163    fn test_metadata_validation() {
164        let mut metadata = PqcMetadata::new();
165
166        // Should fail with empty IV
167        assert!(metadata.validate().is_err());
168
169        // Should succeed with valid IV
170        metadata.enc_params.iv = vec![1; 12];
171        assert!(metadata.validate().is_ok());
172    }
173
174    #[test]
175    fn test_custom_parameters() {
176        let mut metadata = PqcMetadata::new();
177        metadata.add_custom("test".to_string(), vec![1, 2, 3]);
178
179        assert_eq!(metadata.get_custom("test"), Some(&[1, 2, 3][..]));
180        assert_eq!(metadata.get_custom("missing"), None);
181    }
182}