Standalone library crate for building and parsing PKCS #12 objects.
PKCS #12 defines a portable format for storing and transporting a user's private keys and certificates.
This crate provides [Pkcs12Builder] for creating a Pfx containing one private key and one certificate, plus optional additional certificates (e.g. CA/intermediate chain certificates), all protected with password-based encryption (PBES2 / PBKDF2 by default) and a password-based MAC,
and [MacDataBuilder] for creating the MacData structure included in a Pfx.
Helper functions [add_key_id_attr] and [add_friendly_name_attr] are provided for setting the localKeyID and friendlyName PKCS #9 attributes on certificate and key bags.
- PBES2 encryption with configurable PBKDF2 PRF and AES-CBC cipher
- Configurable MAC algorithm and iteration count
- Optional additional certificates (CA/intermediate chain)
localKeyIDandfriendlyNameattribute helpers- Parsing and decryption of existing PKCS #12 files via [parse_pkcs12]
- Per-bag attribute preservation (key ID, friendly name, and arbitrary attributes are retained for each certificate and the key bag)
- Legacy PKCS #12 PBE support (SHA-1/3DES-CBC, SHA-1/RC2-CBC) with the
legacyfeature
use der::asn1::SetOfVec;
use pkcs12_builder::{
Pkcs12Builder, MacDataBuilder, parse_pkcs12,
add_key_id_attr, add_friendly_name_attr,
};
use pkcs12_builder::supported_algs::{EncryptionAlgorithm, MacAlgorithm};
// Assume `cert` is a parsed x509_cert::Certificate and `key` is DER-encoded PKCS #8
let key_id = hex_literal::hex!("EF 09 61 31 5F 51 9D 61 F2 69 7D 9E 75 E5 52 15 D0 7B 00 6D");
let mut cert_attrs = SetOfVec::new();
add_key_id_attr(&mut cert_attrs, &key_id).unwrap();
add_friendly_name_attr(&mut cert_attrs, "My Certificate").unwrap();
let mut key_attrs = SetOfVec::new();
add_key_id_attr(&mut key_attrs, &key_id).unwrap();
add_friendly_name_attr(&mut key_attrs, "My Certificate").unwrap();
let mut mac_builder = MacDataBuilder::new(MacAlgorithm::HmacSha256);
mac_builder.iterations(Some(600_000)).unwrap();
let mut builder = Pkcs12Builder::new();
builder
.iterations(Some(600_000)).unwrap()
.cert_attributes(Some(cert_attrs))
.key_attributes(Some(key_attrs))
.mac_data_builder(Some(mac_builder));
let der_pfx = builder
.build_with_rng(&cert, key, "password", &mut rand::rng())
.unwrap();
// Round-trip: parse back the PKCS #12 file
let contents = parse_pkcs12(&der_pfx, "password").unwrap();
assert_eq!(contents.key_der.as_ref(), key);
assert_eq!(contents.certificate.der, cert_der);Builder for PKCS #12 objects containing one key, one certificate, and optional additional certificates. Default algorithms: PBKDF2-HMAC-SHA-256 KDF, AES-256-CBC encryption, HMAC-SHA-256 MAC. Default iteration count: 600,000.
| Method | Description |
|---|---|
new() |
Create a builder with default settings |
iterations(Option<u32>) |
Set PBKDF2 iteration count for encryption and MAC KDFs (max i32::MAX) |
cert_kdf_algorithm(Option<Pbkdf2Prf>) |
PBKDF2 PRF for the certificate bag |
cert_enc_algorithm(Option<EncryptionAlgorithm>) |
Encryption algorithm for the certificate bag |
key_kdf_algorithm(Option<Pbkdf2Prf>) |
PBKDF2 PRF for the key bag |
key_enc_algorithm(Option<EncryptionAlgorithm>) |
Encryption algorithm for the key bag |
cert_kdf_algorithm_identifier(Option<AlgorithmIdentifierOwned>) |
Fully populated KDF AlgorithmIdentifier for the cert bag (overrides cert_kdf_algorithm) |
cert_enc_algorithm_identifier(Option<AlgorithmIdentifierOwned>) |
Fully populated encryption AlgorithmIdentifier for the cert bag (overrides cert_enc_algorithm) |
key_kdf_algorithm_identifier(Option<AlgorithmIdentifierOwned>) |
Fully populated KDF AlgorithmIdentifier for the key bag (overrides key_kdf_algorithm) |
key_enc_algorithm_identifier(Option<AlgorithmIdentifierOwned>) |
Fully populated encryption AlgorithmIdentifier for the key bag (overrides key_enc_algorithm) |
cert_attributes(Option<SetOfVec<Attribute>>) |
Attributes for the certificate SafeBag |
key_attributes(Option<SetOfVec<Attribute>>) |
Attributes for the key SafeBag |
additional_cert(Certificate) |
Add a CA/intermediate certificate (may be called multiple times) |
mac_data_builder(Option<MacDataBuilder>) |
Set a custom MacDataBuilder (sets omit_mac to false) |
omit_mac() |
Omit the MAC from the generated PKCS #12 (not recommended) |
cert_legacy_pbe_algorithm(Option<LegacyPbeAlgorithm>) |
Use legacy PBE for the cert bag (legacy feature; clears PBES2 settings) |
key_legacy_pbe_algorithm(Option<LegacyPbeAlgorithm>) |
Use legacy PBE for the key bag (legacy feature; clears PBES2 settings) |
cert_legacy_pbe_salt(Option<Vec<u8>>) |
Set the salt for legacy PBE cert encryption (legacy feature; optional, generated by build_with_rng if not set) |
key_legacy_pbe_salt(Option<Vec<u8>>) |
Set the salt for legacy PBE key encryption (legacy feature; optional, generated by build_with_rng if not set) |
build_with_rng(&mut self, &Certificate, &[u8], &str, &mut R) |
Build, generating random salts/IVs from the provided RNG. Do not reuse the builder after a failed call; create a new one instead. |
build(&self, &Certificate, &[u8], &str) |
Build using previously supplied algorithm identifiers (advanced) |
Builder for the MacData integrity structure.
| Method | Description |
|---|---|
new(MacAlgorithm) |
Create with the given digest algorithm (no salt; default 600,000 iterations) |
new_with_salt(MacAlgorithm, Vec<u8>) |
Create with a pre-set salt |
salt(Option<Vec<u8>>) |
Set or clear the salt |
has_salt() |
Returns true if a salt is set |
iterations(Option<u32>) |
Set the iteration count (max i32::MAX; default 600,000) |
build(&self, &str, &[u8]) |
Compute the MAC and return a MacData |
EncryptionAlgorithm — PBES2 content encryption ciphers:
Aes128CbcAes192CbcAes256Cbc
MacAlgorithm — HMAC digest algorithms for MAC:
HmacSha256HmacSha384HmacSha512HmacSha1(legacyfeature only)
LegacyPbeAlgorithm (legacy feature only) — legacy PKCS #12 PBE schemes:
ShaAnd3KeyTripleDesCbc— pbeWithSHAAnd3-KeyTripleDES-CBC (OID 1.2.840.113549.1.12.1.3)ShaAnd128BitRc2Cbc— pbeWithSHAAnd128BitRC2-CBC (OID 1.2.840.113549.1.12.1.5)
MAX_ITERATION_COUNT: u32— Maximum iteration count accepted when parsing (100,000,000). Protects against denial-of-service via crafted PKCS #12 files.
parse_pkcs12(der_p12: &[u8], password: &str) -> Result<Pkcs12Contents>
Decrypt a DER-encoded PKCS #12 file and return its contents.
Pkcs12Contents fields:
key_der: Zeroizing<Vec<u8>>— DER-encoded private keykey_id: Option<Vec<u8>>— optionallocalKeyIDfrom the key bagfriendly_name: Option<String>— optionalfriendlyNamefrom the key bagother_key_attributes: Option<Vec<Attribute>>— any additional key bag attributescertificate: CertAndAttributes— end-entity certificate and its bag attributesadditional_certificates: Vec<CertAndAttributes>— CA/intermediate chain certificates and their bag attributes
CertAndAttributes fields:
der: Vec<u8>— DER-encoded certificatelocal_key_id: Option<Vec<u8>>— optionallocalKeyIDattribute valuefriendly_name: Option<String>— optionalfriendlyNameattribute valueother_attributes: Option<Vec<Attribute>>— any additional bag attributes
add_key_id_attr(attrs: &mut SetOfVec<Attribute>, key_id: &[u8])— Add alocalKeyIDattributeadd_friendly_name_attr(attrs: &mut SetOfVec<Attribute>, name: &str)— Add afriendlyNameattribute (BMP string)
Enable the legacy feature to support legacy PKCS #12 PBE algorithms (SHA-1/3DES-CBC, SHA-1/RC2-CBC) and HMAC-SHA-1 MAC. These are required for interoperability with iOS SecPKCS12Import and other implementations that do not support PBES2.
[dependencies]
pkcs12_builder = { version = "0.1", features = ["legacy"] }This feature pulls in sha1, des, rc2, and cbc as additional dependencies.