PKCS Loaders
Five top-level functions extract X.509 certificates and/or PKCS#8 private keys from container formats (PKCS#7, PKCS#12). All functions accept DER, BER, or CER input; the encoding is detected automatically.
Functions
load_der_pkcs7_certificates
load_der_pkcs7_certificates(data: bytes) -> list[Certificate]
Parse a DER or BER PKCS#7 SignedData blob and return its embedded certificates. BER indefinite-length encodings (common in PKCS#7 files from older tools) are handled transparently. Non-certificate entries in the CertificateSet are silently skipped.
Raises ValueError if the outer ContentInfo contentType is not id-signedData, or on any
ASN.1 structural error.
load_pem_pkcs7_certificates
load_pem_pkcs7_certificates(data: bytes) -> list[Certificate]
Decode PEM block(s) in data (any label accepted: PKCS7, CMS, CERTIFICATE, etc.),
then extract certificates from each PKCS#7 payload. All certificates across all blocks are
returned as a single flat list.
Raises ValueError if no PEM block is found, or if any block fails to parse as PKCS#7
SignedData.
load_pkcs12_certificates
load_pkcs12_certificates(data: bytes, password: bytes = None) -> list[Certificate]
Extract certificates from a PKCS#12 / PFX archive. Non-certificate bag types
(keyBag, pkcs8ShroudedKeyBag, crlBag, secretBag) are silently skipped.
password is the archive password as raw bytes (UTF-8, no NUL terminator). Pass b""
or omit for no-password archives.
Encrypted bags are supported when built with the openssl Cargo feature
(PBES2/PBKDF2/AES-256-CBC) and optionally deprecated-pkcs12-algorithms (legacy 3DES).
Without the openssl feature a ValueError is raised when any encrypted bag is
encountered.
load_pkcs12_keys
load_pkcs12_keys(data: bytes, password: bytes = None) -> list[bytes]
Extract PKCS#8 private keys from a PKCS#12 archive. Returns a list of raw DER-encoded
OneAsymmetricKey blobs, one per keyBag (unencrypted) and pkcs8ShroudedKeyBag
(decrypted with the openssl feature) entry. certBag, crlBag, and secretBag
entries are silently skipped.
load_pkcs12
load_pkcs12(data: bytes, password: bytes = None) -> tuple[list[Certificate], list[bytes]]
Extract both certificates and private keys from a PKCS#12 archive in a single call.
Returns (certs, keys) where certs is a list[Certificate] and keys is a list[bytes]
of DER-encoded PKCS#8 structures.
create_pkcs12
create_pkcs12(
certificates: list[Certificate | bytes],
private_key: PrivateKey | bytes | None = None,
password: bytes | None = None,
) -> bytes
Build a DER-encoded PKCS#12 PFX archive. Each element of certificates may be a
Certificate object or raw DER bytes; both types may appear in the same list.
private_key may be a PrivateKey object or DER-encoded PKCS#8 bytes.
When password is None or omitted, the archive is written without encryption.
When password is provided and the library is built with the openssl Cargo feature,
bags are encrypted with PBES2/PBKDF2-SHA256/AES-256-CBC using 600,000 iterations.
Without the openssl feature, supplying a password raises ValueError.
Raises TypeError for unrecognised element types in certificates or for an
unrecognised private_key type.
Usage
import synta
# ── PKCS#7 SignedData (DER or BER) ───────────────────────────────────────────
# amazon-roots.p7b uses BER indefinite-length encoding (0x30 0x80…); both are
# handled transparently — no caller-visible difference.
data = open("bundle.p7b", "rb").read()
certs = synta.load_der_pkcs7_certificates(data)
for cert in certs:
print(cert.subject)
# ── PKCS#7 SignedData (PEM-wrapped) ──────────────────────────────────────────
pem = open("bundle.pem", "rb").read()
certs = synta.load_pem_pkcs7_certificates(pem)
# ── PKCS#12 — certificates only ──────────────────────────────────────────────
data = open("archive.p12", "rb").read()
certs = synta.load_pkcs12_certificates(data) # unencrypted
certs = synta.load_pkcs12_certificates(data, b"s3cr3t") # password-protected
print(f"found {len(certs)} certificate(s)")
for cert in certs:
print(cert.subject, cert.not_before, "–", cert.not_after)
# ── PKCS#12 — private keys only ──────────────────────────────────────────────
# Returns a list[bytes] of DER-encoded OneAsymmetricKey (PKCS#8) structures.
keys = synta.load_pkcs12_keys(data, b"s3cr3t")
for key_der in keys:
from cryptography.hazmat.primitives.serialization import load_der_private_key
key = load_der_private_key(key_der, None)
# ── PKCS#12 — both certificates and keys in one call ─────────────────────────
certs, keys = synta.load_pkcs12(data, b"s3cr3t")
Creating PKCS#12 Archives
import synta
# ── Certificate objects directly ─────────────────────────────────────────────
certs = synta.load_pkcs12_certificates(open("src.p12", "rb").read())
pfx = synta.create_pkcs12(certs) # no password
open("bundle.p12", "wb").write(pfx)
# ── With a password (openssl feature required) ────────────────────────────────
try:
pfx = synta.create_pkcs12(certs, password=b"s3cr3t")
except ValueError:
# Raised when password is provided without the openssl Cargo feature
pass
# ── With a cert and a PrivateKey object ──────────────────────────────────────
certs, keys = synta.load_pkcs12(open("src.p12", "rb").read())
key = synta.PrivateKey.from_der(keys[0])
pfx = synta.create_pkcs12(certs, private_key=key, password=b"s3cr3t")
# ── Raw DER bytes also accepted ───────────────────────────────────────────────
pfx = synta.create_pkcs12(
[cert.to_der() for cert in certs],
private_key=keys[0], # bytes from load_pkcs12_keys
)
# ── Roundtrip verification ────────────────────────────────────────────────────
parsed_back = synta.load_pkcs12_certificates(pfx, None)
assert len(parsed_back) == len(certs)
Encryption support: when password is provided and the library is built with
--features openssl, bags are encrypted with PBES2/PBKDF2-SHA256/AES-256-CBC using
600,000 iterations. Without the openssl feature, supplying a non-None password raises
ValueError.
See also PKI Blocks for format-agnostic reading, and PEM/DER for PEM encode/decode helpers.