PKCS#12¶
PKCS#12 (also known as PFX) is a file format defined in RFC 7292 for storing cryptographic objects - typically a private key and its associated X.509 certificate chain - protected by a password. It is widely used for importing and exporting credentials in TLS servers, browsers, and certificate management tools.
This API is defined in botan/pkcs12.h.
Added in version 3.13.
PKCS12_Export_Options¶
-
class PKCS12_Export_Options¶
Options controlling how a PKCS#12 file is generated. Construct with the password (mandatory) and an optional friendly name; tweak individual fields with the chainable
with_*mutators, or pick a preset via the static pseudo-constructors below.-
explicit PKCS12_Export_Options(std::string_view password, std::optional<std::string> friendly_name = {})¶
Constructs an options object with modern defaults: PBES2-SHA256-AES256 key encryption, SHA-256 MAC, 100 000 KDF iterations, certificates stored unencrypted.
-
static PKCS12_Export_Options modern(std::string_view password, std::optional<std::string> friendly_name = {})¶
Pseudo-constructor for modern defaults (identical to the regular constructor). Spelled out for clarity at call sites.
-
static PKCS12_Export_Options legacy_compat(std::string_view password, std::optional<std::string> friendly_name = {})¶
Pseudo-constructor for legacy-compatible defaults: PBE-SHA1-3DES key encryption, SHA-1 MAC, 2 048 KDF iterations. Use when interoperability with old software (Java keytool pre-2019, legacy OpenSSL releases, pre-Windows-10) is required.
-
PKCS12_Export_Options &with_friendly_name(std::string name)¶
Overrides the friendly name. If unset, the bundle-level friendly name (see
PKCS12::set_friendly_name) is used.
-
PKCS12_Export_Options &with_iterations(size_t n)¶
Sets the KDF iteration count. Values of 0 or above 1 000 000 (
PKCS12_MAX_ITERATIONS) cause anInvalid_Argumentexception at export time.
-
PKCS12_Export_Options &with_key_encryption_algo(std::string algo)¶
Algorithm used to encrypt the private key (PKCS8ShroudedKeyBag). Supported values:
"PBES2-SHA256-AES256"- modern (default)"PBES2-SHA256-AES128"- modern"PBE-SHA1-3DES"- legacy"PBE-SHA1-2DES"- legacy
-
PKCS12_Export_Options &with_cert_encryption_algo(std::string algo)¶
Algorithm used to encrypt certificates. If the algo is empty (default), certificates are stored unencrypted.
-
PKCS12_Export_Options &with_mac_digest(std::string algo)¶
Hash algorithm for the integrity MAC. Supported:
"SHA-1","SHA-224","SHA-256","SHA-384","SHA-512","SHA-512-256". Default is"SHA-256".
-
PKCS12_Export_Options &without_mac()¶
Disables the integrity MAC. Generally not recommended.
-
explicit PKCS12_Export_Options(std::string_view password, std::optional<std::string> friendly_name = {})¶
PKCS12¶
-
class PKCS12¶
PKCS#12/PFX bundle: parse, inspect, mutate, and export. The default constructor produces an empty bundle that the caller fills via the
add_*/set_*mutators before invokingexport_to.-
PKCS12()¶
Constructs an empty bundle.
-
PKCS12(std::span<const uint8_t> data, std::string_view password)¶
Parses a DER-encoded PFX file. Throws
Decoding_Errorif the file is malformed, orInvalid_Authentication_Tagif MAC verification fails.
Accessors¶
-
const std::vector<std::shared_ptr<Private_Key>> &private_keys() const¶
Private keys stored in the bundle, in storage order (parse-order for parsed PFX, insertion-order for built ones). PKCS#12 supports multiple keys per file.
-
const std::vector<X509_Certificate> &certificates() const¶
All certificates stored in the bundle. The end-entity, if any, comes first when produced by parsing; insertion order is preserved for bundles built in memory.
-
std::optional<X509_Certificate> end_entity_certificate() const¶
The first certificate whose
subjectPublicKeyInfomatches one of the stored private keys, ornulloptif none match (e.g. a certificate-only or key-only bundle).
-
std::vector<X509_Certificate> ca_certificates() const¶
Convenience helper: every certificate except the one returned by
end_entity_certificate. Returned in storage order. For a key-less bundle, returns all certificates after the first.
-
const std::optional<std::string> &friendly_name() const¶
The
friendlyNameattribute, if present.
-
const std::optional<std::vector<uint8_t>> &local_key_id() const¶
The
localKeyIdattribute, if present.
-
const std::vector<OID> &unknown_bag_types() const¶
OIDs of bag types encountered during parsing but not handled by this implementation (e.g.
SecretBag). Empty for normal PKCS#12 files and for bundles constructed in-memory.
Mutators¶
Adds a private key to the bundle.
-
void add_certificate(X509_Certificate cert)¶
Adds a certificate. End-entity vs CA is determined at export time by matching against stored keys.
-
void set_friendly_name(std::string name)¶
-
void clear_friendly_name()¶
-
void set_local_key_id(std::vector<uint8_t> id)¶
-
void clear_local_key_id()¶
Set or clear the bundle-level friendly name / localKeyId attributes.
Export¶
-
std::vector<uint8_t> export_to(const PKCS12_Export_Options &options, RandomNumberGenerator &rng) const¶
Serializes the bundle as a PKCS#12/PFX file.
Throws
Invalid_Argumentif the options are inconsistent (e.g. an unsupported algorithm is requested) or if a stored private key does not match any stored certificate.Iteration counts above
PKCS12_MAX_ITERATIONS(1 000 000) and a SafeContentsBag nesting depth abovePKCS12_MAX_NESTING(10) are rejected.
-
PKCS12()¶
Examples¶
Generating a PFX file from a freshly created key and self-signed certificate:
#include <botan/auto_rng.h>
#include <botan/ec_group.h>
#include <botan/ecdsa.h>
#include <botan/hex.h>
#include <botan/pkcs12.h>
#include <botan/x509self.h>
#include <iostream>
#include <memory>
int main() {
Botan::AutoSeeded_RNG rng;
// Generate an ECDSA private key + self-signed certificate to bundle.
auto key = std::make_shared<Botan::ECDSA_PrivateKey>(rng, Botan::EC_Group::from_name("secp256r1"));
const Botan::X509_Cert_Options cert_opts("example.com");
const auto cert = Botan::X509::create_self_signed_cert(cert_opts, *key, "SHA-256", rng);
// Populate the PKCS#12 bundle.
Botan::PKCS12 bundle;
bundle.add_key(key);
bundle.add_certificate(cert);
bundle.set_friendly_name("My Key");
// Export with modern defaults (PBES2-SHA256-AES256, SHA-256 MAC,
// 100 000 iterations). For maximum interoperability with legacy software
// use Botan::PKCS12_Export_Options::legacy_compat("secret") instead.
const auto pfx = bundle.export_to(Botan::PKCS12_Export_Options::modern("secret"), rng);
std::cout << Botan::hex_encode(pfx) << '\n';
return 0;
}
Parsing a PFX file with error handling:
#include <botan/exceptn.h>
#include <botan/hex.h>
#include <botan/pk_keys.h>
#include <botan/pkcs12.h>
#include <botan/pkix_types.h>
#include <botan/x509cert.h>
#include <iostream>
#include <iterator>
#include <vector>
int main() {
// Read a hex-encoded PFX from stdin.
const std::string hex_input((std::istreambuf_iterator<char>(std::cin)), std::istreambuf_iterator<char>());
const auto pfx_bytes = Botan::hex_decode(hex_input);
try {
const Botan::PKCS12 bundle(pfx_bytes, "secret");
if(!bundle.private_keys().empty()) {
const auto& key = bundle.private_keys().front();
std::cout << "Key: " << key->algo_name() << " (" << key->key_length() << " bits)\n";
}
if(const auto ee = bundle.end_entity_certificate()) {
std::cout << "End-entity: " << ee->subject_dn().to_string() << '\n'
<< "Fingerprint (SHA-256): " << ee->fingerprint("SHA-256") << '\n';
}
for(const auto& ca : bundle.ca_certificates()) {
std::cout << "CA: " << ca.subject_dn().to_string() << '\n';
}
if(bundle.friendly_name()) {
std::cout << "Friendly name: " << *bundle.friendly_name() << '\n';
}
} catch(const Botan::Invalid_Authentication_Tag&) {
std::cerr << "Wrong password or corrupted MAC\n";
return 1;
} catch(const Botan::Decoding_Error& e) {
std::cerr << "Malformed or unsupported PFX file: " << e.what() << '\n';
return 2;
}
return 0;
}
Building a PFX bundle that contains a CA certificate chain alongside the end-entity key and certificate:
#include <botan/asn1_time.h>
#include <botan/auto_rng.h>
#include <botan/ec_group.h>
#include <botan/ecdsa.h>
#include <botan/hex.h>
#include <botan/pkcs10.h>
#include <botan/pkcs12.h>
#include <botan/x509_ca.h>
#include <botan/x509self.h>
#include <iostream>
#include <memory>
#include <vector>
int main() {
Botan::AutoSeeded_RNG rng;
const auto group = Botan::EC_Group::from_name("secp256r1");
// Issuing CA.
const Botan::ECDSA_PrivateKey ca_key(rng, group);
Botan::X509_Cert_Options ca_opts("Example CA");
ca_opts.CA_key();
const auto ca_cert = Botan::X509::create_self_signed_cert(ca_opts, ca_key, "SHA-256", rng);
// End-entity, signed by the CA.
auto ee_key = std::make_shared<Botan::ECDSA_PrivateKey>(rng, group);
Botan::X509_Cert_Options ee_opts("example.com");
ee_opts.dns = "example.com";
const auto csr = Botan::X509::create_cert_req(ee_opts, *ee_key, "SHA-256", rng);
const Botan::X509_CA ca(ca_cert, ca_key, "SHA-256", rng);
const auto ee_cert = ca.sign_request(csr, rng, Botan::X509_Time("200101000000Z"), Botan::X509_Time("300101000000Z"));
// Bundle: end-entity key + cert + issuing CA in the chain.
Botan::PKCS12 bundle;
bundle.add_key(ee_key);
bundle.add_certificate(ee_cert);
bundle.add_certificate(ca_cert);
const auto pfx = bundle.export_to(Botan::PKCS12_Export_Options::modern("secret", "Server Key"), rng);
std::cout << Botan::hex_encode(pfx) << '\n';
return 0;
}
Note
The default encryption algorithm is PBES2-SHA256-AES256 with
SHA-256 MAC and 100 000 KDF iterations. For maximum compatibility
with legacy software (older Java keytool, legacy OpenSSL builds), use
PKCS12_Export_Options::legacy_compat or explicitly configure
with_key_encryption_algo("PBE-SHA1-3DES"),
with_mac_digest("SHA-1"), and with_iterations(2048).
Supported Algorithms¶
The following algorithms are available depending on which Botan modules are built:
Field |
Value |
Required module |
Notes |
|---|---|---|---|
|
|
|
Default; recommended for modern use |
|
|
|
Modern |
|
|
|
Legacy; widest compatibility |
|
|
|
Legacy |
|
Same as above, or |
Empty = certificates stored unencrypted |
|
|
|
|
Default; required by OpenSSL 3.x default policy |
|
|
|
Legacy; widest compatibility |
|
|
|
Uncommon; supported for parsing and generation |
See Command Line Interface for the pkcs12_export / pkcs12_info CLI commands.