Examples ======== Verify a SAML Response ---------------------- Load an IdP certificate, register the ``ID`` attribute, and verify: .. code-block:: python import pybergshamra saml_xml = open("saml-response.xml").read() manager = pybergshamra.KeysManager() idp_cert = pybergshamra.load_x509_cert_pem(open("idp-cert.pem", "rb").read()) manager.add_key(idp_cert) ctx = pybergshamra.DsigContext(manager) ctx.add_id_attr("ID") # SAML uses "ID" not "Id" result = pybergshamra.verify(ctx, saml_xml) if result: print("SAML signature valid") print(f" Algorithm: {result.key_info.algorithm}") for ref in result.references: print(f" Reference: {ref.uri}") else: print(f"SAML signature invalid: {result.reason}") Sign an XML document (enveloped) -------------------------------- Build a signature template with pyuppsala's ``XmlWriter`` and sign it: .. code-block:: python import pybergshamra from pybergshamra import Algorithm from pyuppsala import XmlWriter DSIG_NS = "http://www.w3.org/2000/09/xmldsig#" # Build the document with an embedded signature template w = XmlWriter() w.start_element("Document", [("Id", "doc-1")]) w.start_element("Data") w.text("Important content") w.end_element("Data") # Signature template w.start_element_ns(DSIG_NS, "ds", "Signature") w.start_element_ns(DSIG_NS, "ds", "SignedInfo") w.start_element_ns(DSIG_NS, "ds", "CanonicalizationMethod", [("Algorithm", Algorithm.EXC_C14N)]) w.end_element_ns(DSIG_NS, "ds", "CanonicalizationMethod") w.start_element_ns(DSIG_NS, "ds", "SignatureMethod", [("Algorithm", Algorithm.RSA_SHA256)]) w.end_element_ns(DSIG_NS, "ds", "SignatureMethod") w.start_element_ns(DSIG_NS, "ds", "Reference", [("URI", "#doc-1")]) w.start_element_ns(DSIG_NS, "ds", "Transforms") w.start_element_ns(DSIG_NS, "ds", "Transform", [("Algorithm", Algorithm.ENVELOPED_SIGNATURE)]) w.end_element_ns(DSIG_NS, "ds", "Transform") w.end_element_ns(DSIG_NS, "ds", "Transforms") w.start_element_ns(DSIG_NS, "ds", "DigestMethod", [("Algorithm", Algorithm.SHA256)]) w.end_element_ns(DSIG_NS, "ds", "DigestMethod") w.start_element_ns(DSIG_NS, "ds", "DigestValue") w.end_element_ns(DSIG_NS, "ds", "DigestValue") w.end_element_ns(DSIG_NS, "ds", "Reference") w.end_element_ns(DSIG_NS, "ds", "SignedInfo") w.start_element_ns(DSIG_NS, "ds", "SignatureValue") w.end_element_ns(DSIG_NS, "ds", "SignatureValue") w.end_element_ns(DSIG_NS, "ds", "Signature") w.end_element("Document") template = w.to_string() # Sign manager = pybergshamra.KeysManager() key = pybergshamra.load_rsa_private_pem(open("rsakey.pem", "rb").read()) manager.add_key(key) ctx = pybergshamra.DsigContext(manager) ctx.add_id_attr("Id") signed_xml = pybergshamra.sign(ctx, template) print(signed_xml) Sign with HMAC -------------- .. code-block:: python import pybergshamra template = open("hmac-sign-template.xml").read() manager = pybergshamra.KeysManager() key = pybergshamra.load_hmac_key(b"my-shared-secret-key") key.name = "hmac-key" manager.add_key(key) ctx = pybergshamra.DsigContext(manager) signed_xml = pybergshamra.sign(ctx, template) Sign with ECDSA --------------- .. code-block:: python import pybergshamra template = open("ec-sign-template.xml").read() manager = pybergshamra.KeysManager() key = pybergshamra.load_ec_p256_private_pem(open("ec-p256-key.pem", "rb").read()) manager.add_key(key) ctx = pybergshamra.DsigContext(manager) signed_xml = pybergshamra.sign(ctx, template) Encrypt XML with AES-256-GCM + RSA-OAEP ---------------------------------------- Build an encryption template and encrypt data: .. code-block:: python import pybergshamra # Load the recipient's public key (from their certificate) manager = pybergshamra.KeysManager() key = pybergshamra.load_x509_cert_pem(open("recipient-cert.pem", "rb").read()) manager.add_key(key) # Template defines: AES-256-GCM for content, RSA-OAEP for key transport template = open("enc-template-aes256gcm-rsa-oaep.xml").read() plaintext = b"Classified information" ctx = pybergshamra.EncContext(manager) encrypted_xml = pybergshamra.encrypt(ctx, template, plaintext) print(encrypted_xml) Decrypt an EncryptedAssertion ----------------------------- .. code-block:: python import pybergshamra encrypted_xml = open("encrypted-assertion.xml").read() manager = pybergshamra.KeysManager() key = pybergshamra.load_rsa_private_pem(open("sp-private-key.pem", "rb").read()) manager.add_key(key) ctx = pybergshamra.EncContext(manager) # Decrypt to XML string decrypted_xml = pybergshamra.decrypt(ctx, encrypted_xml) print(decrypted_xml) # Or decrypt to raw bytes (useful for non-XML content) decrypted_bytes = pybergshamra.decrypt_to_bytes(ctx, encrypted_xml) Canonicalize a subtree ---------------------- Exclusive C14N with inclusive namespace prefixes, commonly needed for SAML signature verification: .. code-block:: python import pybergshamra from pybergshamra import C14nMode xml = """\ https://idp.example.com ... ... """ # Canonicalize the full document result = pybergshamra.canonicalize(xml, C14nMode.Exclusive) print(result.decode()) # Canonicalize just the Assertion subtree, keeping "saml" prefix visible result = pybergshamra.canonicalize_subtree( xml, "assertion-1", C14nMode.Exclusive, inclusive_prefixes=["saml"] ) print(result.decode()) Certificate chain validation ---------------------------- Validate a leaf certificate against trusted CA certificates: .. code-block:: python import pybergshamra leaf_der = open("server-cert.der", "rb").read() ca_der = open("ca-cert.der", "rb").read() intermediate_der = open("intermediate.der", "rb").read() try: pybergshamra.validate_cert_chain( leaf_der, trusted_certs=[ca_der], untrusted_certs=[intermediate_der], ) print("Certificate chain is valid") except pybergshamra.CertificateError as e: print(f"Validation failed: {e}") # Skip time checks for testing with expired certs pybergshamra.validate_cert_chain( leaf_der, trusted_certs=[ca_der], skip_time_checks=True, ) Key derivation -------------- PBKDF2, HKDF, and ConcatKDF examples: .. code-block:: python import pybergshamra from pybergshamra import Algorithm # PBKDF2: derive a 256-bit key from a password derived = pybergshamra.pbkdf2_derive( password=b"my-password", salt=b"random-salt-value", iteration_count=100_000, key_length=32, prf_uri=Algorithm.HMAC_SHA256, ) print(f"PBKDF2 key: {derived.hex()}") # HKDF: derive a key from shared secret derived = pybergshamra.hkdf_derive( shared_secret=b"shared-secret-from-key-agreement", key_length=32, salt=b"application-salt", info=b"encryption-context", ) print(f"HKDF key: {derived.hex()}") # ConcatKDF: derive a key (NIST SP 800-56A style) derived = pybergshamra.concat_kdf( shared_secret=b"ecdh-shared-secret", key_length=32, ) print(f"ConcatKDF key: {derived.hex()}") # Standalone digest h = pybergshamra.digest(Algorithm.SHA256, b"data to hash") print(f"SHA-256: {h.hex()}") Ed25519 signatures ------------------ .. code-block:: python import pybergshamra # Load Ed25519 keys from DER private_key = pybergshamra.load_ed25519_private_pkcs8_der(private_der_bytes) public_key = pybergshamra.load_ed25519_public_spki_der(public_der_bytes) print(private_key.algorithm_name) # "Ed25519" print(private_key.has_private_key) # True # Use in signing manager = pybergshamra.KeysManager() manager.add_key(private_key) ctx = pybergshamra.DsigContext(manager) signed_xml = pybergshamra.sign(ctx, template) # Verify with public key verify_manager = pybergshamra.KeysManager() verify_manager.add_key(public_key) verify_ctx = pybergshamra.DsigContext(verify_manager) result = pybergshamra.verify(verify_ctx, signed_xml) assert result.is_valid