Skip to main content

pdf_ast/crypto/
mod.rs

1pub mod certificates;
2pub mod decryption;
3pub mod encryption;
4pub mod pkcs7;
5pub mod signature_verification;
6pub mod signatures;
7pub mod timestamp;
8
9use thiserror::Error;
10
11#[derive(Error, Debug)]
12pub enum CryptoError {
13    #[error("Invalid signature format: {0}")]
14    InvalidSignatureFormat(String),
15
16    #[error("Invalid format: {0}")]
17    InvalidFormat(String),
18
19    #[error("Certificate parsing error: {0}")]
20    CertificateError(String),
21
22    #[error("Encryption error: {0}")]
23    EncryptionError(String),
24
25    #[error("Unsupported algorithm: {0}")]
26    UnsupportedAlgorithm(String),
27
28    #[error("Invalid key: {0}")]
29    InvalidKey(String),
30
31    #[error("Verification failed: {0}")]
32    VerificationFailed(String),
33
34    #[error("Authentication required")]
35    AuthenticationRequired,
36
37    #[error("IO error: {0}")]
38    Io(#[from] std::io::Error),
39
40    #[cfg(feature = "crypto")]
41    #[error("OpenSSL error: {0}")]
42    OpenSsl(String),
43}
44
45pub type CryptoResult<T> = Result<T, CryptoError>;
46
47/// Cryptographic configuration
48#[derive(Debug, Clone)]
49pub struct CryptoConfig {
50    /// Enable signature verification
51    pub enable_signature_verification: bool,
52
53    /// Enable certificate chain validation
54    pub enable_cert_chain_validation: bool,
55
56    /// Trust store path for certificate validation
57    pub trust_store_path: Option<String>,
58
59    /// Maximum certificate chain depth
60    pub max_cert_chain_depth: u32,
61
62    /// Enable CRL checking
63    pub enable_crl_checking: bool,
64
65    /// Enable OCSP checking
66    pub enable_ocsp_checking: bool,
67
68    /// Timeout for network operations (CRL, OCSP)
69    pub network_timeout_seconds: u32,
70
71    /// Enable TSA chain validation for RFC3161 timestamps
72    pub enable_tsa_chain_validation: bool,
73
74    /// Enable TSA revocation checks (OCSP/CRL) during timestamp validation
75    pub enable_tsa_revocation_checks: bool,
76
77    /// Allowed TSA certificate fingerprints (SHA-256). Empty means allow all.
78    pub tsa_allow_fingerprints: Vec<String>,
79
80    /// Blocked TSA certificate fingerprints (SHA-256).
81    pub tsa_block_fingerprints: Vec<String>,
82}
83
84impl Default for CryptoConfig {
85    fn default() -> Self {
86        Self {
87            enable_signature_verification: true,
88            enable_cert_chain_validation: true,
89            trust_store_path: None,
90            max_cert_chain_depth: 5,
91            enable_crl_checking: false, // Disabled by default for performance
92            enable_ocsp_checking: false, // Disabled by default for performance
93            network_timeout_seconds: 30,
94            enable_tsa_chain_validation: true,
95            enable_tsa_revocation_checks: true,
96            tsa_allow_fingerprints: Vec::new(),
97            tsa_block_fingerprints: Vec::new(),
98        }
99    }
100}
101
102/// Main cryptographic provider interface
103pub trait CryptoProvider {
104    /// Verify a digital signature
105    fn verify_signature(
106        &self,
107        _signature_data: &[u8],
108        _signed_data: &[u8],
109        _config: &CryptoConfig,
110    ) -> CryptoResult<SignatureVerificationResult>;
111
112    /// Parse and validate a certificate
113    fn parse_certificate(&self, cert_data: &[u8]) -> CryptoResult<CertificateInfo>;
114
115    /// Verify a certificate chain
116    fn verify_certificate_chain(
117        &self,
118        cert_chain: &[&[u8]],
119        _config: &CryptoConfig,
120    ) -> CryptoResult<CertificateChainResult>;
121
122    /// Decrypt encrypted data
123    fn decrypt(&self, encrypted_data: &[u8], key: &[u8], algorithm: &str) -> CryptoResult<Vec<u8>>;
124
125    /// Encrypt data
126    fn encrypt(&self, data: &[u8], key: &[u8], algorithm: &str) -> CryptoResult<Vec<u8>>;
127}
128
129#[derive(Debug, Clone)]
130pub struct SignatureVerificationResult {
131    pub is_valid: bool,
132    pub signer_certificate: Option<CertificateInfo>,
133    pub signing_time: Option<chrono::DateTime<chrono::Utc>>,
134    pub algorithm: String,
135    pub error_message: Option<String>,
136    pub certificate_chain: Vec<CertificateInfo>,
137    pub timestamp_info: Option<TimestampInfo>,
138}
139
140#[derive(Debug, Clone)]
141pub struct CertificateInfo {
142    pub subject: String,
143    pub issuer: String,
144    pub serial_number: String,
145    pub der: Vec<u8>,
146    pub not_before: chrono::DateTime<chrono::Utc>,
147    pub not_after: chrono::DateTime<chrono::Utc>,
148    pub public_key_algorithm: String,
149    pub signature_algorithm: String,
150    pub key_usage: Vec<String>,
151    pub extended_key_usage: Vec<String>,
152    pub is_ca: bool,
153    pub fingerprint_sha256: String,
154}
155
156#[derive(Debug, Clone)]
157pub struct CertificateChainResult {
158    pub is_valid: bool,
159    pub chain: Vec<CertificateInfo>,
160    pub trust_anchor: Option<CertificateInfo>,
161    pub validation_errors: Vec<String>,
162    pub validation_warnings: Vec<String>,
163}
164
165#[derive(Debug, Clone)]
166pub struct TimestampInfo {
167    pub timestamp: chrono::DateTime<chrono::Utc>,
168    pub timestamp_authority: String,
169    pub hash_algorithm: String,
170    pub is_valid: bool,
171    pub error_message: Option<String>,
172}
173
174/// Get the default crypto provider based on available features
175pub fn get_default_crypto_provider() -> Box<dyn CryptoProvider + Send + Sync> {
176    #[cfg(feature = "crypto")]
177    {
178        Box::new(openssl_provider::OpenSslCryptoProvider::new())
179    }
180    #[cfg(not(feature = "crypto"))]
181    {
182        Box::new(mock_provider::MockCryptoProvider::new())
183    }
184}
185
186// Mock provider for when crypto features are disabled
187#[cfg(not(feature = "crypto"))]
188mod mock_provider {
189    use super::*;
190
191    pub struct MockCryptoProvider;
192
193    impl MockCryptoProvider {
194        pub fn new() -> Self {
195            Self
196        }
197    }
198
199    impl CryptoProvider for MockCryptoProvider {
200        fn verify_signature(
201            &self,
202            __signature_data: &[u8],
203            __signed_data: &[u8],
204            __config: &CryptoConfig,
205        ) -> CryptoResult<SignatureVerificationResult> {
206            Ok(SignatureVerificationResult {
207                is_valid: false,
208                signer_certificate: None,
209                signing_time: None,
210                algorithm: "Mock".to_string(),
211                error_message: Some("Cryptographic features not enabled".to_string()),
212                certificate_chain: Vec::new(),
213                timestamp_info: None,
214            })
215        }
216
217        fn parse_certificate(&self, _cert_data: &[u8]) -> CryptoResult<CertificateInfo> {
218            Err(CryptoError::UnsupportedAlgorithm(
219                "Cryptographic features not enabled".to_string(),
220            ))
221        }
222
223        fn verify_certificate_chain(
224            &self,
225            _cert_chain: &[&[u8]],
226            __config: &CryptoConfig,
227        ) -> CryptoResult<CertificateChainResult> {
228            Ok(CertificateChainResult {
229                is_valid: false,
230                chain: Vec::new(),
231                trust_anchor: None,
232                validation_errors: vec!["Cryptographic features not enabled".to_string()],
233                validation_warnings: Vec::new(),
234            })
235        }
236
237        fn decrypt(
238            &self,
239            _encrypted_data: &[u8],
240            _key: &[u8],
241            _algorithm: &str,
242        ) -> CryptoResult<Vec<u8>> {
243            Err(CryptoError::UnsupportedAlgorithm(
244                "Cryptographic features not enabled".to_string(),
245            ))
246        }
247
248        fn encrypt(&self, _data: &[u8], _key: &[u8], _algorithm: &str) -> CryptoResult<Vec<u8>> {
249            Err(CryptoError::UnsupportedAlgorithm(
250                "Cryptographic features not enabled".to_string(),
251            ))
252        }
253    }
254}
255
256// OpenSSL provider implementation
257#[cfg(feature = "crypto")]
258mod openssl_provider {
259    use super::*;
260
261    pub struct OpenSslCryptoProvider;
262
263    impl OpenSslCryptoProvider {
264        pub fn new() -> Self {
265            Self
266        }
267    }
268
269    impl CryptoProvider for OpenSslCryptoProvider {
270        fn verify_signature(
271            &self,
272            signature_data: &[u8],
273            signed_data: &[u8],
274            _config: &CryptoConfig,
275        ) -> CryptoResult<SignatureVerificationResult> {
276            let handler = crate::crypto::pkcs7::Pkcs7Handler::new();
277            handler.verify_pkcs7(signature_data, signed_data)
278        }
279
280        fn parse_certificate(&self, cert_data: &[u8]) -> CryptoResult<CertificateInfo> {
281            crate::crypto::certificates::parse_der_certificate(cert_data)
282        }
283
284        fn verify_certificate_chain(
285            &self,
286            cert_chain: &[&[u8]],
287            config: &CryptoConfig,
288        ) -> CryptoResult<CertificateChainResult> {
289            let validator =
290                crate::crypto::certificates::CertificateChainValidator::new(config.clone())?;
291            validator.validate_chain(cert_chain)
292        }
293
294        fn decrypt(
295            &self,
296            encrypted_data: &[u8],
297            key: &[u8],
298            algorithm: &str,
299        ) -> CryptoResult<Vec<u8>> {
300            match algorithm {
301                "RC4" => Ok(crate::crypto::encryption::rc4_decrypt(encrypted_data, key)),
302                "AES-128-CBC" | "AES-256-CBC" => {
303                    if encrypted_data.len() < 16 {
304                        return Err(CryptoError::InvalidKey(
305                            "AES data too short for IV".to_string(),
306                        ));
307                    }
308                    let iv = &encrypted_data[..16];
309                    let ciphertext = &encrypted_data[16..];
310                    crate::crypto::encryption::aes_decrypt_cbc(ciphertext, key, Some(iv)).map_err(
311                        |e| CryptoError::EncryptionError(format!("AES decrypt error: {}", e)),
312                    )
313                }
314                _ => Err(CryptoError::UnsupportedAlgorithm(format!(
315                    "Unsupported algorithm: {}",
316                    algorithm
317                ))),
318            }
319        }
320
321        fn encrypt(&self, data: &[u8], key: &[u8], algorithm: &str) -> CryptoResult<Vec<u8>> {
322            match algorithm {
323                "RC4" => Ok(crate::crypto::encryption::rc4_encrypt(data, key)),
324                "AES-128-CBC" | "AES-256-CBC" => {
325                    use rand::RngCore;
326                    let mut iv = [0u8; 16];
327                    let mut rng = rand::rngs::OsRng;
328                    rng.fill_bytes(&mut iv);
329                    let encrypted =
330                        crate::crypto::encryption::aes_encrypt_cbc(data, key, Some(&iv)).map_err(
331                            |e| CryptoError::EncryptionError(format!("AES encrypt error: {}", e)),
332                        )?;
333                    let mut out = Vec::with_capacity(16 + encrypted.len());
334                    out.extend_from_slice(&iv);
335                    out.extend_from_slice(&encrypted);
336                    Ok(out)
337                }
338                _ => Err(CryptoError::UnsupportedAlgorithm(format!(
339                    "Unsupported algorithm: {}",
340                    algorithm
341                ))),
342            }
343        }
344    }
345}
346
347// Add chrono for date/time handling (would need to be added to Cargo.toml)
348mod chrono {
349    use std::fmt;
350
351    #[derive(Debug, Clone, Copy)]
352    pub struct DateTime<Tz> {
353        timestamp: i64,
354        _tz: std::marker::PhantomData<Tz>,
355    }
356
357    impl<Tz> DateTime<Tz> {
358        pub fn from_timestamp(ts: i64) -> Self {
359            Self {
360                timestamp: ts,
361                _tz: std::marker::PhantomData,
362            }
363        }
364
365        pub fn timestamp(&self) -> i64 {
366            self.timestamp
367        }
368    }
369
370    impl<Tz> fmt::Display for DateTime<Tz> {
371        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
372            write!(f, "DateTime({})", self.timestamp)
373        }
374    }
375
376    #[derive(Debug, Clone, Copy)]
377    pub struct Utc;
378
379    impl Utc {
380        pub fn now() -> DateTime<Utc> {
381            DateTime::from_timestamp(
382                std::time::SystemTime::now()
383                    .duration_since(std::time::UNIX_EPOCH)
384                    .unwrap()
385                    .as_secs() as i64,
386            )
387        }
388    }
389}