1
0
mirror of https://github.com/pcvolkmer/cert-tools.git synced 2025-07-01 14:02:54 +00:00

feat: support for PKCS#12 export

This commit is contained in:
2025-05-01 12:43:01 +02:00
parent 5029376529
commit be4af05507
3 changed files with 175 additions and 16 deletions

View File

@ -21,8 +21,11 @@ use itertools::Itertools;
use openssl::asn1::Asn1Time;
use openssl::hash::MessageDigest;
use openssl::nid::Nid;
use openssl::pkcs12::Pkcs12;
use openssl::pkcs7::Pkcs7;
use openssl::pkey::{PKey, PKeyRef, Public};
use openssl::pkey::{PKey, PKeyRef, Private, Public};
use openssl::rsa::Rsa;
use openssl::stack::Stack;
use openssl::x509::X509;
use std::cmp::Ordering;
use std::fmt::Display;
@ -50,7 +53,35 @@ fn asn1time(time: &SystemTime) -> Asn1Time {
.unwrap()
}
#[derive(PartialEq)]
pub fn save_p12_file(path: &Path, certs: &Vec<Certificate>, password: &str, private_key: Option<PrivateKey>) -> Result<(), String> {
if certs.is_empty() {
return Err("Invalid chain".to_owned());
}
let mut pkcs12_builder = Pkcs12::builder();
pkcs12_builder.cert(&certs[0].cert);
if certs.len() > 1 {
let mut ca_stack = Stack::<X509>::new().map_err(|_| "Invalid chain".to_owned())?;
certs[1..].iter().for_each(|cert| {
let _ = ca_stack.push(cert.clone().cert);
});
pkcs12_builder.ca(ca_stack);
}
if let Some(private_key) = private_key {
let key = &PKey::from_rsa(private_key.key).map_err(|_| "Invalid key".to_owned())?;
pkcs12_builder.pkey(key);
}
let result = pkcs12_builder.build2(password).map_err(|e| e.to_string())?;
let result = result.to_der().map_err(|e| e.to_string())?;
fs::write(path, result).map_err(|e| e.to_string())?;
Ok(())
}
#[derive(Clone, PartialEq)]
pub enum StringValue {
Valid(String),
Invalid,
@ -76,7 +107,9 @@ impl From<String> for StringValue {
}
}
#[derive(Clone)]
pub struct PrivateKey {
key: Rsa<Private>,
modulus: StringValue,
}
@ -87,6 +120,7 @@ impl PrivateKey {
match key.rsa() {
Ok(key) => Ok(PrivateKey {
key: key.clone(),
modulus: hex_encode(key.n().to_vec()).into(),
}),
Err(err) => Err(err.to_string()),