1use base64::{engine::general_purpose::STANDARD, Engine as _};
6use zeroize::Zeroizing;
7
8use crate::{PemEncodeOptions, PemError, PemLabel};
9
10pub fn encode_pem(
12 label: PemLabel,
13 der: &[u8],
14 options: PemEncodeOptions,
15) -> Result<Zeroizing<String>, PemError> {
16 if der.is_empty() || der.len() > options.max_der_len {
17 return Err(PemError::DerTooLarge);
18 }
19 if options.line_width == 0 || options.line_width > 76 {
20 return Err(PemError::InvalidOptions);
21 }
22
23 let newline = options.line_ending.as_str();
24 let encoded = Zeroizing::new(STANDARD.encode(der));
25 let mut output = Zeroizing::new(String::new());
26 output.push_str("-----BEGIN ");
27 output.push_str(label.as_str());
28 output.push_str("-----");
29 output.push_str(newline);
30
31 for chunk in encoded.as_bytes().chunks(options.line_width) {
32 let line = core::str::from_utf8(chunk).map_err(|_| PemError::InvalidBase64)?;
33 output.push_str(line);
34 output.push_str(newline);
35 }
36
37 output.push_str("-----END ");
38 output.push_str(label.as_str());
39 output.push_str("-----");
40 output.push_str(newline);
41
42 Ok(output)
43}