forge/openssl/
formatter.rs1use crate::error::ConversionError;
2use crate::openssl::ParsedPfx;
3use openssl::x509::X509;
4
5pub struct PemFormatter;
7
8impl PemFormatter {
9 pub fn private_key_to_pem(parsed: &ParsedPfx) -> Result<Vec<u8>, ConversionError> {
11 let pem_data = parsed
12 .private_key
13 .private_key_to_pem_pkcs8()
14 .map_err(ConversionError::from)?;
15
16 if !Self::validate_pem(&pem_data) {
18 return Err(ConversionError::InvalidFormat(
19 "Generated private key PEM is invalid".to_string(),
20 ));
21 }
22
23 Ok(pem_data)
24 }
25
26 pub fn certificate_to_pem(parsed: &ParsedPfx) -> Result<Vec<u8>, ConversionError> {
28 let pem_data = parsed.certificate.to_pem().map_err(ConversionError::from)?;
29
30 if !Self::validate_pem(&pem_data) {
32 return Err(ConversionError::InvalidFormat(
33 "Generated certificate PEM is invalid".to_string(),
34 ));
35 }
36
37 Ok(pem_data)
38 }
39
40 pub fn cert_to_pem(cert: &X509) -> Result<Vec<u8>, ConversionError> {
42 let pem_data = cert.to_pem().map_err(ConversionError::from)?;
43
44 if !Self::validate_pem(&pem_data) {
46 return Err(ConversionError::InvalidFormat(
47 "Generated certificate PEM is invalid".to_string(),
48 ));
49 }
50
51 Ok(pem_data)
52 }
53
54 pub fn chain_to_pem(parsed: &ParsedPfx) -> Result<Vec<u8>, ConversionError> {
56 let mut chain_pem = Self::certificate_to_pem(parsed)?;
57
58 for cert in &parsed.chain {
59 let cert_pem = Self::cert_to_pem(cert)?;
60 chain_pem.extend_from_slice(&cert_pem);
61 }
62
63 if !Self::validate_pem(&chain_pem) {
65 return Err(ConversionError::InvalidFormat(
66 "Generated certificate chain PEM is invalid".to_string(),
67 ));
68 }
69
70 Ok(chain_pem)
71 }
72
73 pub fn chain_certs_to_pem(parsed: &ParsedPfx) -> Result<Vec<Vec<u8>>, ConversionError> {
75 parsed.chain.iter().map(Self::cert_to_pem).collect()
76 }
77
78 pub fn combined_to_pem(
80 parsed: &ParsedPfx,
81 include_chain: bool,
82 ) -> Result<Vec<u8>, ConversionError> {
83 let mut combined = Self::private_key_to_pem(parsed)?;
84
85 if include_chain && parsed.has_chain() {
86 let chain_pem = Self::chain_to_pem(parsed)?;
87 combined.extend_from_slice(&chain_pem);
88 } else {
89 let cert_pem = Self::certificate_to_pem(parsed)?;
90 combined.extend_from_slice(&cert_pem);
91 }
92
93 if !Self::validate_pem(&combined) {
95 return Err(ConversionError::InvalidFormat(
96 "Generated combined PEM is invalid".to_string(),
97 ));
98 }
99
100 Ok(combined)
101 }
102
103 pub fn validate_pem(pem_data: &[u8]) -> bool {
105 let pem_str = match std::str::from_utf8(pem_data) {
106 Ok(s) => s,
107 Err(_) => return false,
108 };
109
110 let has_begin = pem_str.contains("-----BEGIN");
112 let has_end = pem_str.contains("-----END");
113
114 if !has_begin || !has_end {
115 return false;
116 }
117
118 let begin_count = pem_str.matches("-----BEGIN").count();
120 let end_count = pem_str.matches("-----END").count();
121
122 begin_count == end_count && begin_count > 0
123 }
124}