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}