Skip to content

v0.2.3 - JWS Header Enhancements and Security Hardening

Choose a tag to compare

@jondepalma jondepalma released this 31 Dec 03:10
· 22 commits to main since this release
e5305a1

🚀 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, iat cannot 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 use verify_jws() for auth

3. Header Timestamp (iat) (#43)

  • Both header and payload contain iat claim
  • 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 kid header 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 typ headers 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.3

Upgrade from v0.2.2

pip install --upgrade didlite

Migration Steps:

  1. Update verify_jws() calls to destructure tuple: header, payload = verify_jws(token)
  2. Run tests to verify compatibility
  3. (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

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 kid header 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