Skip to content

feat(wsse): pure-Python WS-Security signing (no xmlsec required)#1485

Open
martincollignon wants to merge 2 commits intomvantellingen:masterfrom
martincollignon:feat/pure-python-wsse-signature
Open

feat(wsse): pure-Python WS-Security signing (no xmlsec required)#1485
martincollignon wants to merge 2 commits intomvantellingen:masterfrom
martincollignon:feat/pure-python-wsse-signature

Conversation

@martincollignon
Copy link

Summary

Adds zeep.wsse.crypto — a pure-Python alternative to the existing xmlsec-based zeep.wsse.signature module. Uses the cryptography library instead of the C-based xmlsec, making installation straightforward on all platforms.

Motivation: We build Landbruget.dk, a Danish agricultural data transparency project. Integrating with Denmark's VetStat SOAP API for antibiotic usage data required WS-Security features that zeep's current xmlsec-based module doesn't support — and installing xmlsec across CI/CD and developer machines was a constant pain point. We ended up writing ~300 lines of manual XML signing. This PR extracts that into a clean, general-purpose module that benefits everyone.

What's new

Feature Current (xmlsec) New (crypto)
Sign Body + Timestamp
Sign UsernameToken
Sign BinarySecurityToken
Sign arbitrary elements ✅ (extra_references)
Inclusive namespace prefixes ✅ (per-reference)
PKCS#12 key loading
PEM key loading
Configurable digest algorithm Partial ✅ (SHA1/SHA256/SHA384/SHA512)
Configurable signature algorithm Partial ✅ (RSA-SHA1/SHA256/SHA384/SHA512)
No C library dependency
Signature verification
KeyIdentifier styles ✅ (ThumbprintSHA1, SKI)
Security header layout control ✅ (xmlsec_compatible, etc.)
Timestamp freshness validation
Certificate validity validation

Usage

from zeep.wsse.crypto import CryptoSignature, CryptoBinarySignature

# Drop-in replacement for wsse.Signature
sig = CryptoSignature("key.pem", "cert.pem")

# BinarySecurityToken variant
sig = CryptoBinarySignature("key.pem", "cert.pem")

# PKCS#12 support
sig = CryptoBinarySignature.from_pkcs12("cert.p12", b"password")

# Sign extra elements + custom C14N prefixes (e.g. for government SOAP APIs)
sig = CryptoBinarySignature(
    "key.pem", "cert.pem",
    sign_username_token=True,
    sign_binary_security_token=True,
    digest_method="http://www.w3.org/2001/04/xmlenc#sha256",
    inclusive_ns_prefixes={"Body": ["wsse", "ds"]},
)

# Works with Compose
from zeep.wsse import Compose
from zeep.wsse.username import UsernameToken
wsse = Compose([UsernameToken("user", "pass"), sig])

Install: pip install zeep[crypto]

Related issues

Test plan

  • 38 tests covering all features (signing, verification, algorithm combos, PKCS12, inclusive prefixes, key identifiers, header layout, timestamp validation, Compose integration, edge cases)
  • No changes to existing signature.py — fully additive
  • Graceful fallback if cryptography not installed (classes set to None in __init__.py)
  • crypto optional dependency added to setup.py extras

🤖 Generated with Claude Code

martincollignon and others added 2 commits March 20, 2026 10:09
Add `zeep.wsse.crypto` module as a drop-in alternative to the existing
xmlsec-based `zeep.wsse.signature` module. Uses the `cryptography`
library instead of the C-based `xmlsec`, making installation
straightforward on all platforms.

New capabilities beyond the xmlsec-based module:
- No C library dependency (pure Python via `cryptography` + `lxml`)
- PKCS#12 (.p12/.pfx) key loading support
- Configurable signed parts (Body, Timestamp, UsernameToken,
  BinarySecurityToken, or any element with wsu:Id)
- Per-reference inclusive namespace prefixes for exclusive C14N
- Mixed digest/signature algorithms (e.g. SHA-256 digests + RSA-SHA1)

Classes: CryptoSignature, CryptoBinarySignature, CryptoMemorySignature,
CryptoBinaryMemorySignature, PKCS12Signature

Install with: pip install zeep[crypto]

Closes mvantellingen#1357, relates to mvantellingen#1419, mvantellingen#1428, mvantellingen#1363, mvantellingen#1318

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add features surfaced by review:
- KeyIdentifier styles (ThumbprintSHA1, SubjectKeyIdentifier)
- Configurable security header element ordering
- Timestamp freshness validation (Created/Expires)
- Certificate validity period validation
- Internal _configure() method for cleaner initialization

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant