Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.
PASETO-PQ: Post-Quantum PASETO Tokens
A pure post-quantum implementation of PASETO tokens using ML-DSA (CRYSTALS-Dilithium) signatures and ChaCha20-Poly1305 encryption. This crate provides quantum-safe authentication and encryption tokens with comprehensive metadata support, resistant to attacks by quantum computers implementing Shor's algorithm.
๐ก๏ธ Security Level Selection
Default: ml-dsa-44 - Optimized for distributed systems and network protocols
- 128-bit post-quantum security (equivalent to AES-128)
- ~30% smaller tokens than ml-dsa-65
- Best for: networking protocols, authentication tokens, distributed systems
Upgrade to ml-dsa-65 for high-value or long-term secrets
- 192-bit post-quantum security
- Larger tokens but stronger security margin
- Best for: financial systems, sensitive data, compliance requirements
Upgrade to ml-dsa-87 for critical infrastructure
- 256-bit post-quantum security
- Largest tokens but maximum security
- Best for: government, military, long-term archival signatures
Usage
# Default (recommended for most applications)
= "0.1.0"
# High security applications
= { = "0.1.0", = ["balanced"] }
# Maximum security applications
= { = "0.1.0", = ["maximum-security"] }
# Explicit parameter set selection
= { = "0.1.0", = ["ml-dsa-65"], = false }
๐ Features
- ๐ Quantum-Safe: Uses ML-DSA (NIST FIPS 204) signatures and ML-KEM-768 key exchange
- ๐ฆ Pure Rust: No C dependencies, built on RustCrypto
- ๐ฏ Full PASETO Parity: Complete implementation with both public and local tokens
- โก Practical Performance: Optimized for real-world usage patterns
- ๐ง Easy Integration: Drop-in replacement for authentication and encryption tokens
- ๐ฆ Dual Token Types: Public (signatures) and Local (symmetric encryption)
- ๐ฆถ Footer Support: Authenticated metadata for key management and service integration
- ๐ Key Exchange: ML-KEM for post-quantum key establishment
- ๐ JSON Integration: Built-in JSON conversion for logging, databases, and tracing
- ๐ Token Parsing: Fast token inspection for debugging, middleware, and monitoring
- ๐ Token Size Estimation: Plan token usage and avoid deployment surprises
- ๐ RFC3339 Time Fields: Standard time serialization for maximum compatibility
- ๐ก๏ธ Memory Safe: Constant-time operations and proper secret zeroization
๐ Quick Start
Add this to your Cargo.toml:
[]
= "0.1.0" # Uses ml-dsa-44 by default for optimal network performance
= { = "0.3", = ["serde", "formatting", "parsing"] }
= "0.10.0-rc.1"
Public Tokens (Asymmetric Signatures)
use ;
use OffsetDateTime;
use rng;
Local Tokens (Symmetric Encryption)
use ;
use OffsetDateTime;
use rng;
Footer Support
PASETO-PQ supports authenticated footers for metadata that doesn't belong in claims:
use ;
use OffsetDateTime;
use rng;
๐ Token Formats
โ ๏ธ NON-STANDARD VERSIONING: PASETO-PQ uses a non-standard token format that is incompatible with official PASETO libraries. The pq1 version identifier clearly indicates "post-quantum era" tokens, distinguishing them from classical algorithms defined in the PASETO specification.
Compatibility Impact
- NOT compatible with existing PASETO libraries (paseto.js, paseto-dotnet, etc.)
- NOT compatible with standard PASETO tooling
- Cannot be verified by standard PASETO implementations
- Intentionally incompatible to prevent mixing with classical tokens
When To Use This Crate
- โ Greenfield applications requiring post-quantum security
- โ Internal systems where PASETO compatibility is not required
- โ Future migration paths when post-quantum PASETO standards emerge
- โ Systems requiring interoperability with existing PASETO ecosystems
Both token types support optional footers:
Public Tokens (Signatures)
# Without footer
paseto.pq1.public.<base64url-payload>.<base64url-signature>
# With footer
paseto.pq1.public.<base64url-payload>.<base64url-signature>.<base64url-footer>
paseto: Protocol identifierpq1: Post-quantum version identifier (non-standard, distinct from official PASETO)public: Purpose (signature-based tokens)payload: Base64url-encoded JSON claimssignature: Base64url-encoded ML-DSA signature (size varies by parameter set)footer: Base64url-encoded JSON metadata (optional, authenticated)
Local Tokens (Encryption)
# Without footer
paseto.pq1.local.<base64url-encrypted-payload>
# With footer
paseto.pq1.local.<base64url-encrypted-payload>.<base64url-footer>
paseto: Protocol identifierpq1: Post-quantum version identifier (non-standard, distinct from official PASETO)local: Purpose (symmetric encryption)encrypted-payload: Base64url-encoded nonce + ChaCha20-Poly1305 ciphertextfooter: Base64url-encoded JSON metadata (optional, encrypted with payload)
๐ Performance Characteristics
๐ง Performance & Size Comparison
| Parameter Set | Security Level | Signature Size | Public Key Size | Token Size (approx.) |
|---|---|---|---|---|
| ml-dsa-44 | 128-bit (default) | ~2,420 bytes | ~1,312 bytes | ~3.2-3.4KB |
| ml-dsa-65 | 192-bit | ~3,309 bytes | ~1,952 bytes | ~4.3-4.5KB |
| ml-dsa-87 | 256-bit | ~4,627 bytes | ~2,592 bytes | ~6.0-6.2KB |
Comparison to Classical Algorithms:
| Operation | ML-DSA (avg) | Ed25519 (reference) | Ratio |
|---|---|---|---|
| Key Generation | ~10-30ms | ~100ยตs | 100-300x slower |
| Signing | ~5-20ms | ~50ยตs | 100-400x slower |
| Verification | ~2-5ms | ~80ยตs | 25-60x slower |
| Signature Size | 2,420-4,627 bytes | 64 bytes | 38-72x larger |
| Public Key | 1,312-2,592 bytes | 32 bytes | 41-81x larger |
Local Tokens (ChaCha20-Poly1305)
| Operation | PASETO-PQ Local | Traditional PASETO v4.local | Ratio |
|---|---|---|---|
| Key Generation | ~1ยตs | ~1ยตs | ~1x |
| Encryption | ~1-5ยตs | ~1-5ยตs | ~1x |
| Decryption | ~1-5ยตs | ~1-5ยตs | ~1x |
| Token Overhead | ~30 bytes | ~30 bytes | ~1x |
| Symmetric Key | 32 bytes | 32 bytes | 1x |
| Token Size | ~100-300 bytes | ~100-300 bytes | ~1x |
Key Exchange (ML-KEM-768)
| Operation | ML-KEM-768 | ECDH P-256 (reference) | Ratio |
|---|---|---|---|
| Key Generation | ~100ยตs | ~50ยตs | 2x slower |
| Encapsulation | ~150ยตs | ~100ยตs | 1.5x slower |
| Decapsulation | ~200ยตs | ~100ยตs | 2x slower |
| Ciphertext Size | 1,088 bytes | 33 bytes | 33x larger |
| Public Key | 1,184 bytes | 33 bytes | 36x larger |
Note: Performance varies by hardware. These numbers are from benchmarks on modern x86-64.
Token Size Implications:
- Public tokens (~4.4KB): Not suitable for cookies or URLs but perfect for Authorization headers
- Local tokens (~200 bytes): Suitable for all transport methods including cookies
- Footer overhead: ~50-200 bytes depending on metadata complexity
๐ฏ Use Cases
Public Tokens (ML-DSA Signatures)
โ Recommended For:
- Inter-service authentication (API keys, service tokens)
- Authorization headers (4KB typical limit allows comfortable usage)
- Non-repudiation requirements (audit trails, legal evidence)
- Public key infrastructure (distributed verification)
- Long-term security (5+ year lifetime)
- High-security applications (financial, government, healthcare)
โ ๏ธ Consider Carefully:
- Browser cookies (4KB browser limit, no room for other data)
- URL parameters (2KB practical limit)
- High-frequency operations (>1000/sec per core)
- Real-time applications (signing latency considerations)
Local Tokens (Symmetric Encryption)
โ Recommended For:
- Session management (user sessions, temporary access)
- Cookie-based authentication (small size, fits easily)
- Confidential data transport (encrypted payloads)
- High-performance scenarios (fast encrypt/decrypt)
- Internal services (shared secret available)
- Mobile applications (bandwidth efficiency)
โ ๏ธ Consider Carefully:
- Key distribution (shared secret management complexity)
- Multi-party scenarios (single shared key limitation)
- Long-term storage (key rotation complexity)
Key Exchange (ML-KEM)
โ Recommended For:
- Establishing shared secrets for local tokens
- Hybrid workflows (KEM + local tokens)
- Forward secrecy requirements
- Quantum-safe key agreement
- Zero-knowledge protocols
๐ง Advanced Usage
Public Token Validation
use ;
use Duration;
let verified = verify_with_options?;
Footer Operations
use ;
// Create and populate footer
let mut footer = new;
footer.set_kid?;
footer.set_version?;
footer.add_custom?;
footer.add_custom?;
// Use with public tokens (footer is authenticated by signature)
let token = sign_with_footer?;
let verified = verify_with_footer?;
// Access footer data
if let Some = verified.footer
// Use with local tokens (footer is encrypted with payload)
let local_token = encrypt_with_footer?;
let decrypted = decrypt_with_footer?;
Local Token Validation
use ;
use Duration;
let verified = decrypt_with_options?;
Key Serialization
// Public/Private keys
let signing_bytes = keypair.signing_key_to_bytes;
let verifying_bytes = keypair.verifying_key_to_bytes;
let signing_key = signing_key_from_bytes?;
let verifying_key = verifying_key_from_bytes?;
// Symmetric keys
let sym_bytes = symmetric_key.to_bytes;
let symmetric_key = from_bytes?;
// KEM keys
let enc_bytes = kem_keypair.encapsulation_key_to_bytes;
let dec_bytes = kem_keypair.decapsulation_key_to_bytes;
let enc_key = encapsulation_key_from_bytes?;
let dec_key = decapsulation_key_from_bytes?;
Post-Quantum Key Exchange
use ;
use rng;
// Generate KEM keypair
let mut rng = rng;
let kem_keypair = generate;
// Sender: encapsulate shared secret
let = kem_keypair.encapsulate;
// Receiver: decapsulate shared secret
let shared_key_receiver = kem_keypair.decapsulate?;
// Both parties now have the same symmetric key
assert_eq!;
// Use for local tokens
let token = encrypt?;
let verified = decrypt?;
Custom Claims
let mut claims = new;
claims.set_subject?;
// Add custom business logic
claims.add_custom?;
claims.add_custom?;
claims.add_custom?;
// Works with both public and local tokens
let public_token = sign?;
let local_token = encrypt?;
// Access custom claims after verification/decryption
if let Some = verified_claims.get_custom
JSON Integration
PASETO-PQ provides seamless JSON integration for easy use with logging systems, databases, and distributed tracing:
use Claims;
use Value;
use OffsetDateTime;
let mut claims = new;
claims.set_subject?;
claims.set_issuer?;
claims.set_expiration?;
claims.add_custom?;
claims.add_custom?;
// Convert to JSON Value for flexible use
let json_value: Value = claims.clone.into;
// Convert to JSON string for logging
let json_string = claims.to_json_string?;
println!;
// Pretty JSON for debugging
let pretty_json = claims.to_json_string_pretty?;
// Time fields are RFC3339 strings for maximum compatibility
// {"exp": "2025-01-15T10:30:00Z", "iat": "2025-01-14T10:30:00Z"}
Integration Examples:
- Structured Logging: Direct JSON serialization for ELK Stack, Datadog, Splunk
- Database Storage: PostgreSQL JSONB, MongoDB document storage
- Distributed Tracing: OpenTelemetry span attributes, Jaeger context
- Audit Trails: Compliance logging with embedded claims data
- Monitoring: Grafana dashboards with JSON-queryable token data
Run the JSON integration demo:
Token Parsing
Parse tokens for inspection without expensive cryptographic operations. Perfect for debugging, middleware routing, logging, and monitoring:
use ;
let token = "paseto.pq1.public.ABC123...";
let parsed = parse?;
// Inspect token structure (no crypto operations)
println!; // "public" or "local"
println!; // "pq1"
println!;
println!;
println!;
println!;
// Middleware routing based on token type
match parsed.purpose
// Debugging information
println!;
if let Some = parsed.footer
// Quick access with PasetoPQ wrapper
let parsed_alt = parse_token?;
Use Cases:
- API Gateway Routing: Route tokens to appropriate handlers based on type
- Monitoring & Metrics: Collect token statistics without crypto overhead
- Debugging: Inspect malformed or problematic tokens quickly
- Load Balancing: Route based on token size or metadata
- Logging: Extract non-sensitive metadata for log correlation
Run the token parsing demo:
Token Size Estimation
Estimate token sizes before creation to avoid runtime surprises with HTTP headers, cookies, or URL length limits:
use ;
let mut claims = new;
claims.set_subject?;
claims.add_custom?;
claims.add_custom?;
// Estimate before creating
let estimator = public;
println!;
// Check transport compatibility
if !estimator.fits_in_cookie
if estimator.fits_in_header
if estimator.fits_in_url else
// Get detailed breakdown
let breakdown = estimator.breakdown;
println!;
println!;
println!;
println!;
println!;
// Get optimization suggestions
if estimator.total_bytes > 4000
// Compare token types
let public_est = estimate_public_size;
let local_est = estimate_local_size;
println!;
println!;
println!;
// Compare to JWT (for reference)
println!;
// Generate size summary
println!;
Size Limits & Recommendations:
- HTTP Cookies: 4KB browser limit (use local tokens or session storage)
- URL Parameters: 2KB practical limit (use Authorization header instead)
- HTTP Headers: 8KB typical server limit (public tokens fit comfortably)
- JSON Payloads: No practical limit (both token types work well)
Use Cases:
- Production Planning: Avoid deployment surprises and HTTP 413 errors
- Architecture Decisions: Choose between public/local tokens based on size
- Transport Selection: Select appropriate delivery method (header/cookie/body)
- Performance Optimization: Identify oversized tokens early
Run the token size estimation demo:
๐ฌ Security Considerations
Post-Quantum Security
- ML-DSA-65: NIST FIPS 204 standardized signature algorithm
- Security Level: NIST Level 3 (~192-bit classical security, quantum-safe)
- Quantum Resistance: Secure against Shor's algorithm and known quantum attacks
- ChaCha20-Poly1305: 256-bit symmetric encryption, quantum-resistant for key sizes
- ML-KEM-768: NIST-standardized key encapsulation, quantum-safe key establishment
Implementation Security
- Memory Safety: Pure Rust implementation prevents buffer overflows
- Constant-Time: Operations designed to prevent timing attacks where possible
- Secret Zeroization: Symmetric keys automatically zeroized on drop via
ZeroizeOnDroptrait - Key Cleanup: All key types implement
Dropfor automatic cleanup when out of scope - RustCrypto: Built on well-audited cryptographic primitives with zeroize features enabled
- HKDF Key Derivation: RFC 5869 HKDF-SHA256 for cryptographically sound key derivation from ML-KEM shared secrets
- No Side Channels: Careful implementation to prevent information leakage
Operational Security
- Token Parsing Safety:
ParsedToken::parse()performs no crypto operations, safe for untrusted input - Footer Authentication: Public token footers covered by ML-DSA signature
- Footer Confidentiality: Local token footers encrypted with ChaCha20-Poly1305
- Time Validation: Built-in expiration and not-before checks with configurable clock skew
- Audience Validation: Cryptographically enforced recipient verification
Token Size Security Implications
- Public tokens (~4.4KB): Large size makes them impractical for cookies but perfect for headers
- Information Leakage: Token size may reveal information about claims structure
- DoS Considerations: Large tokens consume more bandwidth and processing time
- Recommendation: Use local tokens for size-sensitive applications
๐๏ธ Feature Flags
[]
= { = "0.1.0", = ["logging"] }
Available Features
logging- Enable structured logging with tracingstd- Standard library support (enabled by default)serde: JSON serialization support (enabled by default)time: Time-based claims validation (enabled by default)
All major features are enabled by default for ease of use.
๐งช Testing
Run the complete test suite:
# Run all tests with full backtrace (recommended)
RUST_BACKTRACE=full
# Run specific test categories
# Run examples to verify functionality
# Run benchmarks
๐ค Contributing
We welcome contributions! Please see our Contributing Guide for details.
Development Setup
๐ License
Licensed under either of:
- Apache License, Version 2.0 (LICENSE-APACHE)
- MIT License (LICENSE-MIT)
at your option.
โ ๏ธ Security Warning
IMPORTANT: This implementation has not yet undergone independent security audit. While built on NIST-standardized algorithms and well-tested Rust cryptographic libraries, please conduct your own security review before using in production systems.
Cryptographic Foundations
- ML-DSA (Dilithium): NIST FIPS 204 standardized post-quantum signature scheme
- ChaCha20-Poly1305: RFC 8439 authenticated encryption
- ML-KEM (Kyber): NIST FIPS 203 standardized post-quantum KEM
- SHA-3: NIST FIPS 202 cryptographic hash function
Footer Security Properties
- Public Tokens: Footer authenticated by ML-DSA signature (tamper-evident)
- Local Tokens: Footer encrypted with ChaCha20-Poly1305 (confidential and authenticated)
- Size Considerations: Footers add ~50-200 bytes depending on metadata complexity
๐ Acknowledgments
- NIST Post-Quantum Cryptography Standardization team
- RustCrypto organization for cryptographic primitives
- PASETO specification contributors
- Rust community for excellent tooling and libraries