1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
use std::fmt; use openssl::{ pkcs12::Pkcs12, pkey::{PKey, Private}, x509::X509, }; /// A cryptographic identity. /// /// An identity is an X509 certificate along with its corresponding private key and chain of certificates to a trusted /// root. #[derive(Clone)] pub struct Identity { pub(crate) pkey: PKey<Private>, pub(crate) cert: X509, pub(crate) chain: Vec<X509>, } impl fmt::Debug for Identity { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("Identity").finish() } } impl Identity { /// Parses a DER-formatted PKCS #12 archive, using the specified password to decrypt the key. /// /// The archive should contain a leaf certificate and its private key, as well any intermediate /// certificates that should be sent to clients to allow them to build a chain to a trusted /// root. The chain certificates should be in order from the leaf certificate towards the root. /// /// PKCS #12 archives typically have the file extension `.p12` or `.pfx`, and can be created /// with the OpenSSL `pkcs12` tool: /// /// ```bash /// openssl pkcs12 -export -out identity.pfx -inkey key.pem -in cert.pem -certfile chain_certs.pem /// ``` pub fn from_pkcs12(buf: &[u8], pass: &str) -> crate::Result<Self> { let pkcs12 = Pkcs12::from_der(buf)?; let parsed = pkcs12.parse(pass)?; Ok(Identity { pkey: parsed.pkey, cert: parsed.cert, chain: parsed.chain.into_iter().flatten().collect(), }) } }