v0.2.3 - JWS Header Enhancements and Security Hardening
🚀 Release Highlights
This release introduces significant JWS/JWT enhancements for plugin ecosystem readiness while maintaining security and performance. One breaking change with a straightforward migration path.
⚠️ BREAKING CHANGE
verify_jws() now returns (header, payload) tuple instead of just payload
Migration
# Before (v0.2.2)
payload = verify_jws(token)
# After (v0.2.3)
header, payload = verify_jws(token)
# Or if you don't need the header:
_, payload = verify_jws(token)Why? Access to header information (kid, alg, typ, iat) without re-parsing enables:
- Plugin header validation
- Fast DID routing before verification
- Audit trail with header timestamps
📖 Migration Guide: docs/dev-design/VERIFY_JWS_CHANGE.md
✨ New Features
1. Custom JWS Headers (#43)
# Enable custom 'typ' headers for plugin ecosystems
token = create_jws(agent, payload, headers={"typ": "dpop+jwt"})- Use Cases: DPoP tokens, OAuth tokens, SIOP tokens
- Protected Fields:
alg,kid,iatcannot be overridden (security-critical) - Unblocks: didlite-ap2, didlite-oauth, didlite-siop plugins
2. Fast DID Extraction (#44)
# Extract DID without signature verification (~24x faster)
did = extract_signer_did(token)- Performance: 0.01ms per extraction (~190,000/sec)
- Use Cases: Routing, logging, rate limiting before expensive verification
⚠️ Security: Does NOT verify signature - always useverify_jws()for auth
3. Header Timestamp (iat) (#43)
- Both header and payload contain
iatclaim - Enables header-based timestamp validation
- Zero performance overhead
🔒 Security & Quality
Test Coverage: 96% → 97.2%
- 236 tests (+135 new tests)
- 7 categories: Compliance, Core, Fuzzing, Integration, JWS, Keystore, Security
- 233 passed, 3 skipped
New Security Tests:
- ✅ Missing
kidheader validation (prevents algorithm confusion) - ✅ Improved signature tampering detection
- ✅ Future-dated token rejection (prevents replay attacks)
- ✅ Algorithm enforcement (VULN-4, VULN-5, VULN-6)
Coverage by Module:
| Module | Coverage | Status |
|---|---|---|
didlite/core.py |
98% | ✅ All security-critical paths |
didlite/jws.py |
99% | ✅ Attack prevention verified |
didlite/keystore.py |
95% | ✅ All backends validated |
| Overall | 97.2% | ✅ Production-ready |
⚡ Performance (Raspberry Pi 5)
| Operation | v0.2.2 | v0.2.3 | Change |
|---|---|---|---|
| Identity Generation | 0.11ms | 0.11ms | Stable |
| Token Creation | 0.13ms | 0.08ms | +58% faster ⚡ |
| Token Verification | 0.24ms | 0.24ms | Zero overhead |
| DID Extraction | N/A | 0.01ms | NEW - 24x faster 🚀 |
| Custom Headers | N/A | 0.08ms | NEW - zero overhead |
Throughput:
- Token creation: ~13,100/sec (was ~8,300/sec)
- DID extraction: ~190,000/sec (NEW)
🎯 Plugin Ecosystem Readiness
This release unblocks three planned plugins:
didlite-ap2 (Agent Payment Protocol)
- Requires custom
typheaders for mandate signing - Needs header access for payment verification
didlite-oauth (OAuth 2.0)
- DPoP token support via custom headers
- Fast DID extraction for token introspection
didlite-siop (Self-Issued OpenID)
- Custom
typ: "openid4vci+jwt"headers - Header-based timestamp validation
📦 Installation
pip install didlite==0.2.3Upgrade from v0.2.2
pip install --upgrade didliteMigration Steps:
- Update
verify_jws()calls to destructure tuple:header, payload = verify_jws(token) - Run tests to verify compatibility
- (Optional) Use new
extract_signer_did()for routing/logging
📋 What's Changed
Features
- feat: v0.2.3 - JWS header enhancements and breaking changes (#48)
- Custom headers parameter for
create_jws() verify_jws()tuple return:(header, payload)- New
extract_signer_did()helper function - Header timestamp (
iat) inclusion
- Custom headers parameter for
Documentation
- docs: Update documentation for v0.2.3 breaking changes
- docs: Update test coverage and performance metrics
- docs: Revise package description in setup.py
Testing
- test: Improve test coverage and reliability for security paths
- Fixed flaky signature validation test
- Added missing
kidheader security test - Documented cryptography OpenSSL backend issue
Full Changelog: https://github.com/jondepalma/didlite-pkg/blob/main/CHANGELOG.md
🔍 Verification
Run Tests
pip install -e ".[test]"
pytest --cov=didlite --cov-report=term-missing
# Expected: 233 passed, 3 skipped, Coverage: 97.2%Performance Benchmarks
python -c "
import time
from didlite import AgentIdentity, create_jws, extract_signer_did
agent = AgentIdentity()
payload = {'test': 'data'}
# Benchmark token creation
start = time.time()
for _ in range(1000):
token = create_jws(agent, payload)
print(f'Token creation: {(time.time()-start)*1000/1000:.2f}ms per token')
# Benchmark DID extraction
tokens = [create_jws(agent, payload) for _ in range(100)]
start = time.time()
for t in tokens:
did = extract_signer_did(t)
print(f'DID extraction: {(time.time()-start)*1000/100:.2f}ms per extraction')
"🙏 Acknowledgments
- All security testing and validation performed with Claude Code
- Performance benchmarks on Raspberry Pi 5 8GB
📝 Checklist
- All tests pass (233/236, 3 skipped)
- Coverage ≥ 95% (97.2%)
- Performance benchmarks updated
- Documentation comprehensive
- Migration guide provided
- Security regression tests added
- Breaking changes documented
🤖 Generated with Claude Code
Co-Authored-By: Claude Sonnet 4.5 noreply@anthropic.com