Skip to main content

forge/openssl/
parser.rs

1use crate::error::ConversionError;
2use crate::openssl::ParsedPfx;
3use openssl::pkcs12::Pkcs12;
4use std::fs;
5use std::path::Path;
6
7/// Parser for PFX/P12 files
8pub struct PfxParser;
9
10impl PfxParser {
11    /// Parse a PFX file from a file path
12    pub fn parse_file<P: AsRef<Path>>(
13        path: P,
14        password: &str,
15    ) -> Result<ParsedPfx, ConversionError> {
16        let path = path.as_ref();
17
18        // Check if file exists
19        if !path.exists() {
20            return Err(ConversionError::FileNotFound(path.display().to_string()));
21        }
22
23        // Read the file
24        let pfx_data =
25            fs::read(path).map_err(|e| ConversionError::FileRead(path.display().to_string(), e))?;
26
27        Self::parse_bytes(&pfx_data, password)
28    }
29
30    /// Parse PFX data from bytes
31    pub fn parse_bytes(data: &[u8], password: &str) -> Result<ParsedPfx, ConversionError> {
32        // Parse the PKCS12 structure
33        let pkcs12 = Pkcs12::from_der(data).map_err(|e| {
34            ConversionError::InvalidFormat(format!("Failed to parse PFX structure: {}", e))
35        })?;
36
37        // Extract the contents with the provided password
38        let parsed = pkcs12.parse2(password).map_err(|e| {
39            if password.is_empty() {
40                ConversionError::Authentication(format!(
41                    "Failed to parse PFX file: {}. This file may require a password. Use --password option.",
42                    e
43                ))
44            } else {
45                ConversionError::Authentication(format!(
46                    "Failed to parse PFX file with provided password: {}",
47                    e
48                ))
49            }
50        })?;
51
52        Ok(ParsedPfx::from(parsed))
53    }
54}