Skip to main content

forge/openssl/
mod.rs

1mod formatter;
2mod parser;
3
4pub use formatter::PemFormatter;
5pub use parser::PfxParser;
6
7use openssl::pkcs12::ParsedPkcs12_2 as ParsedPkcs12;
8use openssl::pkey::PKey;
9use openssl::pkey::Private;
10use openssl::x509::X509;
11
12/// Represents the contents of a parsed PFX file
13#[derive(Debug)]
14pub struct ParsedPfx {
15    /// The private key
16    pub private_key: PKey<Private>,
17    /// The main certificate
18    pub certificate: X509,
19    /// Additional certificates in the chain (if any)
20    pub chain: Vec<X509>,
21}
22
23impl From<ParsedPkcs12> for ParsedPfx {
24    fn from(parsed: ParsedPkcs12) -> Self {
25        Self {
26            private_key: parsed.pkey.expect("Private key is required"),
27            certificate: parsed.cert.expect("Certificate is required"),
28            chain: parsed
29                .ca
30                .map(|stack| stack.into_iter().collect())
31                .unwrap_or_default(),
32        }
33    }
34}
35
36/// Certificate information structure
37#[derive(Debug, Clone)]
38pub struct CertificateInfo {
39    pub subject: String,
40    pub issuer: String,
41    pub serial_number: String,
42    pub not_before: String,
43    pub not_after: String,
44    pub signature_algorithm: String,
45}
46
47impl ParsedPfx {
48    /// Get certificate information as a formatted string (legacy method)
49    pub fn cert_info(&self) -> String {
50        let info = self.certificate_info();
51        format!("Subject: {}\nIssuer: {}", info.subject, info.issuer)
52    }
53
54    /// Get detailed certificate information
55    pub fn certificate_info(&self) -> CertificateInfo {
56        let cert = &self.certificate;
57        CertificateInfo {
58            subject: format!("{:?}", cert.subject_name()),
59            issuer: format!("{:?}", cert.issuer_name()),
60            serial_number: cert
61                .serial_number()
62                .to_bn()
63                .unwrap()
64                .to_hex_str()
65                .unwrap()
66                .to_string(),
67            not_before: cert.not_before().to_string(),
68            not_after: cert.not_after().to_string(),
69            signature_algorithm: cert.signature_algorithm().object().to_string(),
70        }
71    }
72
73    /// Check if this PFX contains a certificate chain
74    pub fn has_chain(&self) -> bool {
75        !self.chain.is_empty()
76    }
77
78    /// Get the number of certificates in the chain
79    pub fn chain_length(&self) -> usize {
80        self.chain.len()
81    }
82}