API reference¶
Algorithm constants¶
- class Algorithm¶
Static class containing W3C XML Security algorithm URI strings. Use these instead of hardcoding URI strings in your code.
from pybergshamra import Algorithm print(Algorithm.RSA_SHA256) # "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"
Canonicalization
Digest
RSA Signature
RSA-PSS Signature
DSA Signature
ECDSA Signature
EdDSA Signature
HMAC Signature
ML-DSA Post-Quantum
SLH-DSA Post-Quantum
Block Cipher
Key Wrap
Key Transport
Mask Generation Function (MGF)
Key Agreement
Key Derivation
Transform
KeyValue Type
X509
Encrypted/Derived Key
Key management¶
KeyUsage¶
- class KeyUsage¶
Key usage mode enumeration. Pass these values to
Key.usage()orKeysManager.find_by_usage().- Sign¶
Key is used for signing.
- Verify¶
Key is used for signature verification.
- Encrypt¶
Key is used for encryption.
- Decrypt¶
Key is used for decryption.
- Any¶
Key can be used for any purpose (default).
import pybergshamra from pybergshamra import KeyUsage key = pybergshamra.load_rsa_private_pem(pem_data) key.usage = KeyUsage.Sign manager = pybergshamra.KeysManager() manager.add_key(key) found = manager.find_by_usage(KeyUsage.Sign)
Key¶
- class Key¶
A cryptographic key (RSA, EC, HMAC, AES, Ed25519, X25519, PQ, etc.). Keys are created through the key loader functions, not constructed directly.
- name: str | None¶
The key name, or
None. Readable and writable.key = pybergshamra.load_rsa_private_pem(pem_data) key.name = "my-signing-key" print(key.name) # "my-signing-key"
- algorithm_name: str¶
The algorithm name (read-only). Examples:
"RSA","EC-P256","HMAC","AES","3DES","Ed25519","X25519".key = pybergshamra.load_rsa_private_pem(pem_data) print(key.algorithm_name) # "RSA"
KeysManager¶
- class KeysManager¶
Key store for managing cryptographic keys and certificates.
import pybergshamra manager = pybergshamra.KeysManager() key = pybergshamra.load_rsa_private_pem(pem_data) manager.add_key(key) print(len(manager)) # 1 print(bool(manager)) # True
- find_by_name(name: str) Key | None¶
Find a key by name.
key = pybergshamra.load_hmac_key(b"secret") key.name = "my-hmac" manager.add_key(key) found = manager.find_by_name("my-hmac")
Key loaders¶
File-based loaders¶
- load_key_file(path: str) Key¶
Load a key from a file, auto-detecting the format by extension (
.pem,.der,.cer,.p12, etc.).- Raises:
KeyLoadError – If the file cannot be read or parsed.
key = pybergshamra.load_key_file("rsakey.pem")
- load_key_file_with_password(path: str, password: str) Key¶
Load a key from a password-protected file.
- Raises:
KeyLoadError – If the file cannot be read, the password is wrong, or the format is unsupported.
key = pybergshamra.load_key_file_with_password("cakey.pem", "secret123")
- load_pkcs12(data: bytes, password: str) Key¶
Load a key from PKCS#12 (PFX) data with a password.
- Parameters:
data – Raw PKCS#12 bytes.
password – The password protecting the PKCS#12 file.
- Raises:
KeyLoadError – If the data is invalid or the password is wrong.
p12_data = open("key.p12", "rb").read() key = pybergshamra.load_pkcs12(p12_data, "secret123")
- load_keys_file(path: str) list[Key]¶
Load keys from an xmlsec
keys.xmlfile.- Raises:
KeyLoadError – If the file cannot be read or parsed.
keys = pybergshamra.load_keys_file("keys.xml") for key in keys: print(key.name, key.algorithm_name)
RSA loaders¶
- load_rsa_private_pem(pem_data: bytes) Key¶
Load an RSA private key from PEM data.
- Raises:
KeyLoadError – If the PEM data is not a valid RSA private key.
- load_rsa_public_pem(pem_data: bytes) Key¶
Load an RSA public key from PEM data.
- Raises:
KeyLoadError – If the PEM data is not a valid RSA public key.
EC loaders¶
- load_ec_p256_private_pem(pem_data: bytes) Key¶
Load an EC P-256 (secp256r1) private key from PEM data.
- Raises:
KeyLoadError – If the PEM data is not a valid EC P-256 key.
- load_ec_p384_private_pem(pem_data: bytes) Key¶
Load an EC P-384 (secp384r1) private key from PEM data.
- Raises:
KeyLoadError – If the PEM data is not a valid EC P-384 key.
- load_ec_p521_private_pem(pem_data: bytes) Key¶
Load an EC P-521 (secp521r1) private key from PEM data.
- Raises:
KeyLoadError – If the PEM data is not a valid EC P-521 key.
X.509 loaders¶
- load_x509_cert_pem(pem_data: bytes) Key¶
Load an X.509 certificate from PEM data. The returned key contains the certificate’s public key and the certificate chain.
- Raises:
KeyLoadError – If the PEM data is not a valid certificate.
cert_pem = open("cert.pem", "rb").read() key = pybergshamra.load_x509_cert_pem(cert_pem) print(key.algorithm_name) # e.g. "RSA" print(len(key.x509_chain)) # 1
- load_x509_cert_der(data: bytes) Key¶
Load an X.509 certificate from DER data.
- Raises:
KeyLoadError – If the data is not a valid DER certificate.
Symmetric key loaders¶
- load_hmac_key(data: bytes) Key¶
Create an HMAC key from raw bytes. This function never fails.
key = pybergshamra.load_hmac_key(b"my-secret-key") print(key.algorithm_name) # "HMAC"
- load_aes_key(data: bytes) Key¶
Create an AES key from raw bytes. The data length must be 16 (AES-128), 24 (AES-192), or 32 (AES-256) bytes.
- Raises:
KeyLoadError – If the data length is invalid.
import os key = pybergshamra.load_aes_key(os.urandom(32)) # AES-256
- load_des3_key(data: bytes) Key¶
Create a 3DES key from raw bytes. The data must be 24 bytes.
- Raises:
KeyLoadError – If the data length is not 24.
Auto-detect loaders¶
- load_pem_auto(pem_data: bytes, password: str | None = None) Key¶
Auto-detect the PEM type and load the key. Handles RSA, EC, Ed25519, X.509 certificates, PKCS#8, and encrypted PEM.
- Parameters:
pem_data – PEM-encoded key or certificate bytes.
password – Optional password for encrypted PEM files.
- Raises:
KeyLoadError – If the PEM type cannot be determined or loaded.
# Works with any PEM type key = pybergshamra.load_pem_auto(open("some-key.pem", "rb").read()) # With password for encrypted PEM key = pybergshamra.load_pem_auto(open("cakey.pem", "rb").read(), password="secret123")
SPKI loaders¶
- load_spki_pem(pem_data: bytes) Key¶
Load a public key from SPKI (Subject Public Key Info) PEM data.
- Raises:
KeyLoadError – If the PEM data is not valid SPKI.
- load_spki_der(data: bytes) Key¶
Load a public key from SPKI DER data.
- Raises:
KeyLoadError – If the data is not valid SPKI DER.
Ed25519 loaders¶
- load_ed25519_private_pkcs8_der(data: bytes) Key¶
Load an Ed25519 private key from PKCS#8 DER data.
- Raises:
KeyLoadError – If the data is not a valid Ed25519 PKCS#8 key.
- load_ed25519_public_spki_der(data: bytes) Key¶
Load an Ed25519 public key from SPKI DER data.
- Raises:
KeyLoadError – If the data is not a valid Ed25519 SPKI key.
X25519 loaders¶
- load_x25519_private_raw(data: bytes) Key¶
Load an X25519 private key from raw 32-byte data.
- Raises:
KeyLoadError – If the data is not exactly 32 bytes.
- load_x25519_public_raw(data: bytes) Key¶
Load an X25519 public key from raw 32-byte data.
- Raises:
KeyLoadError – If the data is not exactly 32 bytes.
Keys XML¶
- parse_keys_xml(xml: str) list[Key]¶
Parse keys from an xmlsec
keys.xmlstring.- Raises:
KeyLoadError – If the XML is not a valid keys document.
xml = open("keys.xml").read() keys = pybergshamra.parse_keys_xml(xml) for k in keys: print(k.name, k.algorithm_name)
X509 KeyInfo builders¶
- build_x509_key_info(certs_b64: list[str]) str¶
Build a
<ds:KeyInfo><ds:X509Data>XML fragment from base64-encoded certificates.- Parameters:
certs_b64 – List of base64-encoded certificate strings.
- Returns:
XML string with
ds:namespace prefix.
import base64 cert_der = open("cert.der", "rb").read() cert_b64 = base64.b64encode(cert_der).decode() xml = pybergshamra.build_x509_key_info([cert_b64]) # '<ds:KeyInfo><ds:X509Data><ds:X509Certificate>...</ds:X509Certificate></ds:X509Data></ds:KeyInfo>'
- build_x509_key_info_from_der(certs_der: list[bytes]) str¶
Build a
<ds:KeyInfo><ds:X509Data>XML fragment from DER-encoded certificates.- Parameters:
certs_der – List of DER-encoded certificate bytes.
- Returns:
XML string with
ds:namespace prefix.
cert_der = open("cert.der", "rb").read() xml = pybergshamra.build_x509_key_info_from_der([cert_der])
Digital signatures¶
DsigContext¶
- class DsigContext(keys_manager: KeysManager)¶
Context for XML Digital Signature operations. Holds configuration and a
KeysManager. Build one, set properties, then callverify()orsign().- Parameters:
keys_manager – The key store to use for sign/verify operations.
manager = pybergshamra.KeysManager() manager.add_key(key) ctx = pybergshamra.DsigContext(manager)
- verification_time: str | None¶
Verification time override. Format:
"YYYY-MM-DD+HH:MM:SS". Default:None(use current time).
- trusted_keys_only: bool¶
Only use pre-configured keys, skip inline KeyInfo extraction. Default:
False.
- strict_verification: bool¶
Enforce strict reference target validation (anti-XSW protection). Default:
False.ctx = pybergshamra.DsigContext(manager) ctx.strict_verification = True result = pybergshamra.verify(ctx, xml)
VerifyResult¶
- class VerifyResult¶
Result of signature verification. Use
bool(result)to check validity.- references: list[VerifiedReference] | None¶
The verified references, or
Noneif invalid.
- key_info: VerifiedKeyInfo | None¶
Information about the verification key, or
Noneif invalid.
result = pybergshamra.verify(ctx, xml) if result: print("Valid!") for ref in result.references: print(f" Reference URI: {ref.uri}") print(f" Key algorithm: {result.key_info.algorithm}") else: print(f"Invalid: {result.reason}")
VerifiedReference¶
VerifiedKeyInfo¶
verify and sign¶
- verify(ctx: DsigContext, xml: str) VerifyResult¶
Verify a signed XML document. Returns a
VerifyResult– usebool(result)to check validity.- Parameters:
ctx – A configured
DsigContext.xml – The signed XML string.
- Raises:
XmlError – If the XML cannot be parsed.
result = pybergshamra.verify(ctx, xml) if result: print("Signature valid")
- sign(ctx: DsigContext, template_xml: str) str¶
Sign an XML template and return the signed XML string. The template must contain a
<Signature>skeleton with<SignedInfo>,<Reference>, etc.- Parameters:
ctx – A configured
DsigContext.template_xml – The XML template string.
- Raises:
XmlError – If the XML template cannot be parsed.
CryptoError – If signing fails.
signed_xml = pybergshamra.sign(ctx, template) print(signed_xml)
XML encryption¶
EncContext¶
- class EncContext(keys_manager: KeysManager)¶
Context for XML Encryption operations. Holds configuration and a
KeysManager.- Parameters:
keys_manager – The key store to use for encrypt/decrypt operations.
encrypt, decrypt, decrypt_to_bytes¶
- encrypt(ctx: EncContext, template_xml: str, data: bytes) str¶
Encrypt data using an XML template. The template must contain an
<EncryptedData>element with an empty<CipherValue>.- Parameters:
ctx – A configured
EncContext.template_xml – The XML encryption template.
data – The plaintext bytes to encrypt.
- Returns:
XML string with encrypted content.
- Raises:
EncryptionError – If encryption fails.
- decrypt(ctx: EncContext, xml: str) str¶
Decrypt an XML document containing
<EncryptedData>. Returns the decrypted XML as a string.- Parameters:
ctx – A configured
EncContext.xml – The XML string containing encrypted data.
- Raises:
EncryptionError – If decryption fails.
XmlError – If the XML cannot be parsed.
- decrypt_to_bytes(ctx: EncContext, xml: str) bytes¶
Decrypt an XML document containing
<EncryptedData>. Returns the raw decrypted bytes (supports non-UTF-8 content).- Parameters:
ctx – A configured
EncContext.xml – The XML string containing encrypted data.
- Raises:
EncryptionError – If decryption fails.
XmlError – If the XML cannot be parsed.
Canonicalization¶
C14nMode¶
- class C14nMode¶
XML Canonicalization mode enumeration.
- Inclusive¶
Inclusive C14N (
http://www.w3.org/TR/2001/REC-xml-c14n-20010315)
- InclusiveWithComments¶
Inclusive C14N with comments
- Inclusive11¶
Inclusive C14N 1.1
- Inclusive11WithComments¶
Inclusive C14N 1.1 with comments
- Exclusive¶
Exclusive C14N (
http://www.w3.org/2001/10/xml-exc-c14n#)
- ExclusiveWithComments¶
Exclusive C14N with comments
Properties
Methods
canonicalize and canonicalize_subtree¶
- canonicalize(xml: str, mode: C14nMode, inclusive_prefixes: list[str] | None = None) bytes¶
Canonicalize an XML document.
- Parameters:
xml – The XML string.
mode – The canonicalization mode.
inclusive_prefixes – Optional namespace prefixes to force visibly-utilized in exclusive C14N.
- Returns:
The canonicalized XML as bytes.
- Raises:
XmlError – If the XML cannot be parsed.
from pybergshamra import canonicalize, C14nMode result = canonicalize("<b/><a/>", C14nMode.Exclusive)
- canonicalize_subtree(xml: str, element_id: str, mode: C14nMode, inclusive_prefixes: list[str] | None = None) bytes¶
Canonicalize a subtree identified by an element ID.
- Parameters:
xml – The XML string.
element_id – The ID attribute value of the target element.
mode – The canonicalization mode.
inclusive_prefixes – Optional namespace prefixes.
- Returns:
The canonicalized subtree as bytes.
- Raises:
XmlError – If the XML cannot be parsed or the element is not found.
from pybergshamra import canonicalize_subtree, C14nMode xml = '<root><item Id="x1">hello</item></root>' result = canonicalize_subtree(xml, "x1", C14nMode.Exclusive)
Cryptographic primitives¶
- digest(algorithm_uri: str, data: bytes) bytes¶
Compute a one-shot message digest.
- Parameters:
algorithm_uri – A W3C algorithm URI (e.g.
Algorithm.SHA256).data – The data to digest.
- Returns:
The digest bytes.
- Raises:
AlgorithmError – If the algorithm is unsupported.
from pybergshamra import digest, Algorithm h = digest(Algorithm.SHA256, b"hello world") print(h.hex())
- pbkdf2_derive(password: bytes, salt: bytes, iteration_count: int, key_length: int, prf_uri: str) bytes¶
Derive a key using PBKDF2 (RFC 8018).
- Parameters:
password – The password/secret bytes.
salt – Salt bytes.
iteration_count – Number of iterations.
key_length – Desired output key length in bytes.
prf_uri – PRF algorithm URI (e.g.
Algorithm.HMAC_SHA256).
- Returns:
The derived key bytes.
from pybergshamra import pbkdf2_derive, Algorithm key = pbkdf2_derive( b"password", b"salt", 100_000, 32, Algorithm.HMAC_SHA256 )
- hkdf_derive(shared_secret: bytes, key_length: int, prf_uri: str | None = None, salt: bytes | None = None, info: bytes | None = None) bytes¶
Derive a key using HKDF (RFC 5869).
- Parameters:
shared_secret – Input keying material (IKM).
key_length – Desired output key length in bytes.
prf_uri – PRF algorithm URI (default: HMAC-SHA256).
salt – Optional salt bytes.
info – Optional context/info bytes.
- Returns:
The derived key bytes.
from pybergshamra import hkdf_derive key = hkdf_derive(b"shared-secret", 32, salt=b"salt", info=b"context")
- concat_kdf(shared_secret: bytes, key_length: int, digest_uri: str | None = None, algorithm_id: bytes | None = None, party_u_info: bytes | None = None, party_v_info: bytes | None = None) bytes¶
Derive a key using ConcatKDF (NIST SP 800-56A).
- Parameters:
shared_secret – The shared secret bytes (Z).
key_length – Desired output key length in bytes.
digest_uri – Digest algorithm URI (default: SHA-256).
algorithm_id – Optional AlgorithmID bytes.
party_u_info – Optional PartyUInfo bytes.
party_v_info – Optional PartyVInfo bytes.
- Returns:
The derived key bytes.
from pybergshamra import concat_kdf key = concat_kdf(b"shared-secret", 32)
Certificate validation¶
- validate_cert_chain(leaf_der: bytes, additional_certs: list[bytes] = [], trusted_certs: list[bytes] = [], untrusted_certs: list[bytes] = [], crls: list[bytes] = [], verification_time: str | None = None, skip_time_checks: bool = False) None¶
Validate an X.509 certificate chain. Verifies that the leaf certificate chains to a trusted root, optionally checking time validity and CRLs.
- Parameters:
leaf_der – DER-encoded leaf certificate.
additional_certs – Extra certificates from XML (DER-encoded).
trusted_certs – Trusted CA certificates (DER-encoded).
untrusted_certs – Untrusted intermediate certificates (DER-encoded).
crls – Certificate Revocation Lists (DER-encoded).
verification_time – Time override (format:
"YYYY-MM-DD+HH:MM:SS").skip_time_checks – Skip NotBefore/NotAfter validation.
- Raises:
CertificateError – If validation fails.
Returns
Noneon success.import pybergshamra leaf_der = open("leaf.der", "rb").read() ca_der = open("ca.der", "rb").read() # Raises CertificateError on failure pybergshamra.validate_cert_chain( leaf_der, trusted_certs=[ca_der], skip_time_checks=True, )