A .pfx or .p12 file is one ASN.1 structure, BER-encoded
(see DER), defined by PKCS #12 version 1.1, published as
RFC 7292. It wraps keys and certificates in layers: a MAC over everything, a list of
content blocks that may each be encrypted, and inside them typed “bags”. The OIDs from
PKCS #5, #7 and #9 that it uses are given here too. Sources: RFC 7292 (sections 4 and 5,
appendices B to D), RFC 5652 for the content type OIDs, RFC 2985 for the PKCS #9
attributes and the certTypes and crlTypes arcs, RFC 8018 for
PBES2 and PBKDF2, RFC 3565 for the AES OIDs, and RFC 9579 for PBMAC1.
PFX
PFX ::= SEQUENCE {
version INTEGER {v3(3)}(v3,...),
authSafe ContentInfo,
macData MacData OPTIONAL }
MacData ::= SEQUENCE {
mac DigestInfo, -- digest algorithm and the MAC value
macSalt OCTET STRING,
iterations INTEGER DEFAULT 1 }
versionis 3 (RFC 7292 section 4).authSafeis a ContentInfo of type data (1.2.840.113549.1.7.1) in password integrity mode, or signedData (1.2.840.113549.1.7.2) in public-key integrity mode. Its content is the BER encoding of an AuthenticatedSafe (RFC 7292 section 4.1; OIDs from RFC 5652).macData, present only in password integrity mode, is an HMAC over that content, keyed from the password, the salt and the iteration count. RFC 7292 section 5.1 allows SHA-1, SHA-224, SHA-256, SHA-384, SHA-512, SHA-512/224 or SHA-512/256 as the hash, named inmac. The default iteration count of 1 is “for historical reasons and its use is deprecated”; RFC 7292 points to NIST SP 800-132 for choosing a count.
Authenticated safe and safe contents
AuthenticatedSafe ::= SEQUENCE OF ContentInfo. Each ContentInfo is
one of (RFC 7292 sections 4.1 and 5.1; OIDs from RFC 5652 section 12.1):
| Content type | OID | Holds |
|---|---|---|
| data | 1.2.840.113549.1.7.1 | An OCTET STRING with the BER encoding of SafeContents, not encrypted. |
| encryptedData | 1.2.840.113549.1.7.6 | SafeContents encrypted with a key from the password. OpenSSL’s PKCS12_create stores certificates this way (see below). |
| envelopedData | 1.2.840.113549.1.7.3 | SafeContents encrypted to a recipient’s public key. |
SafeContents ::= SEQUENCE OF SafeBag
SafeBag ::= SEQUENCE {
bagId OBJECT IDENTIFIER,
bagValue [0] EXPLICIT ANY DEFINED BY bagId,
bagAttributes SET OF PKCS12Attribute OPTIONAL }
The SafeBag definition is simplified from RFC 7292 section 4.2, which writes
bagId and bagValue with information object classes.
Bag types
Bag OIDs are bagtypes = {pkcs-12 10 1}, where
pkcs-12 is 1.2.840.113549.1.12 (RFC 7292 section 4.2 and
appendix D).
| OID | Bag | Value |
|---|---|---|
1.2.840.113549.1.12.10.1.1 | keyBag | A PKCS #8 PrivateKeyInfo, not encrypted. |
1.2.840.113549.1.12.10.1.2 | pkcs8ShroudedKeyBag | A PKCS #8 EncryptedPrivateKeyInfo. OpenSSL’s PKCS12_create stores the private key this way. |
1.2.840.113549.1.12.10.1.3 | certBag | SEQUENCE { certId OID, certValue [0] EXPLICIT }; see below. |
1.2.840.113549.1.12.10.1.4 | crlBag | SEQUENCE { crlId OID, crlValue [0] EXPLICIT }: x509CRL, {crlTypes 1} = 1.2.840.113549.1.9.23.1, is a DER X.509 CRL in an OCTET STRING. |
1.2.840.113549.1.12.10.1.5 | secretBag | SEQUENCE { secretTypeId OID, secretValue [0] EXPLICIT }: any other secret. |
1.2.840.113549.1.12.10.1.6 | safeContentsBag | A nested SafeContents. |
Certificate types sit under certTypes = {pkcs-9 22} and
CRL types under crlTypes = {pkcs-9 23}, where
pkcs-9 is 1.2.840.113549.1.9 (RFC 2985 appendix A; the
types themselves are in RFC 7292 sections 4.2.3 and 4.2.4).
| certId | Certificate |
|---|---|
1.2.840.113549.1.9.22.1 | x509Certificate: a DER X.509 certificate in an OCTET STRING |
1.2.840.113549.1.9.22.2 | sdsiCertificate: a base64 SDSI certificate in an IA5String |
RFC 7292 section 4.2 names two bag attributes, both from PKCS #9 (RFC 2985 sections 5.5.1, 5.5.2 and appendix A):
| Attribute OID | Name | Value |
|---|---|---|
1.2.840.113549.1.9.20 | friendlyName | A single BMPString: “a user-friendly name of the object it belongs to”. OpenSSL’s PKCS12_create sets it from its name argument or the certificate’s alias. |
1.2.840.113549.1.9.21 | localKeyId | A single OCTET STRING identifying a key, “only to be used locally in applications”. OpenSSL’s PKCS12_create puts the same value, the SHA-1 digest of the certificate, on the key bag and its certificate bag. |
RFC 7292 allows other attributes (“Other attributes are allowed”) and says an
importing application “should ignore any object identifiers that it is not familiar
with” (section 5.2). One example is Microsoft’s CSP name,
1.3.6.1.4.1.311.17.1 (OpenSSL objects.txt), which OpenSSL’s
pkcs12 -CSP option writes.
Password-based encryption
RFC 7292 appendix C defines its own password-based algorithms, kept for backwards
compatibility with PKCS #12 v1.0 and not recommended. All use SHA-1, under
pkcs-12PbeIds = {pkcs-12 1}, with parameters
SEQUENCE { salt OCTET STRING, iterations INTEGER }:
| OID | Algorithm |
|---|---|
1.2.840.113549.1.12.1.1 | pbeWithSHAAnd128BitRC4 |
1.2.840.113549.1.12.1.2 | pbeWithSHAAnd40BitRC4 |
1.2.840.113549.1.12.1.3 | pbeWithSHAAnd3-KeyTripleDES-CBC |
1.2.840.113549.1.12.1.4 | pbeWithSHAAnd2-KeyTripleDES-CBC |
1.2.840.113549.1.12.1.5 | pbeWithSHAAnd128BitRC2-CBC |
1.2.840.113549.1.12.1.6 | pbewithSHAAnd40BitRC2-CBC (so spelt in RFC 7292) |
For these, keys and IVs come from the password by the PKCS #12 key derivation of
RFC 7292 appendix B, which also makes the MAC key for macData (appendix
B.4): the password is taken as a BMPString with a null terminator (each character as
2 bytes, most significant first, then two zero bytes; appendix B.1), and an ID byte
chooses what is made: 1 an encryption key, 2 an IV, 3 a MAC key (appendix B.3).
The alternative is PBES2 (id-PBES2 = {pkcs-5 13} =
1.2.840.113549.1.5.13) with PBKDF2 (id-PBKDF2 =
{pkcs-5 12} = 1.2.840.113549.1.5.12), both from RFC 8018,
and a cipher such as AES-256-CBC (id-aes256-CBC =
2.16.840.1.101.3.4.1.42, RFC 3565). OpenSSL’s PKCS12_create
defaults to PBES2 with PBKDF2 and AES-256-CBC for both keys and certificates, with
HMAC-SHA-256 for the MAC, while the MAC key is still derived by the appendix B method
(its documentation calls it PKCS12KDF). RFC 9579 adds PBMAC1 from RFC 8018 as a MAC
that uses PBKDF2 instead.
A file made by OpenSSL
With a key, its certificate and default settings, OpenSSL’s
PKCS12_create (crypto/pkcs12/p12_crt.c) builds:
- PFX, version 3, with MacData.
- authSafe: data, holding an AuthenticatedSafe of two ContentInfos.
- First: encryptedData, holding SafeContents with one certBag for the certificate and one for each extra CA certificate passed in.
- Second: data, holding SafeContents with one pkcs8ShroudedKeyBag for the private key.
- The key bag and its certificate bag share a localKeyId (the certificate’s SHA-1 digest) and, when a name is given or the certificate has an alias, a friendlyName.