use native_ossl::pkcs12::Pkcs12;
use native_ossl::pkey::KeygenCtx;
use native_ossl::x509::{X509Builder, X509NameOwned};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut kgen = KeygenCtx::new(c"ED25519")?;
let priv_key = kgen.generate()?;
let pub_key = native_ossl::pkey::Pkey::<native_ossl::pkey::Public>::from(priv_key.clone());
let mut name = X509NameOwned::new()?;
name.add_entry_by_txt(c"CN", b"example.com")?;
let cert = X509Builder::new()?
.set_version(2)?
.set_serial_number(1)?
.set_not_before_offset(0)?
.set_not_after_offset(365 * 86400)?
.set_subject_name(&name)?
.set_issuer_name(&name)?
.set_public_key(&pub_key)?
.sign(&priv_key, None)?
.build();
let password = "correct horse battery staple";
let p12 = Pkcs12::create(password, "example.com", &priv_key, &cert, &[])?;
let der = p12.to_der()?;
println!("PKCS#12 bundle: {} bytes", der.len());
let loaded = Pkcs12::from_der(&der)?;
let (recovered_key, recovered_cert, ca_chain) = loaded.parse(password)?;
println!(
"Recovered key algorithm: Ed25519 = {}",
recovered_key.is_a(c"ED25519")
);
if let Some(subject) = recovered_cert.subject_name().to_string() {
println!("Recovered cert subject: {subject}");
}
println!("CA chain length: {}", ca_chain.len());
assert!(priv_key.public_eq(&recovered_key));
assert_eq!(cert.to_der()?, recovered_cert.to_der()?);
println!("Key and certificate match original: OK");
let der2 = loaded.to_der()?;
assert_eq!(der, der2);
println!("DER round-trip: OK");
Ok(())
}