jwk-simple
[!WARNING] This project is a work in progress. The API may change.
A Rust library for working with JSON Web Keys (JWK) and JWK Sets (JWKS) as defined in RFC 7517, with WASM compatibility and optional jwt-simple integration.
Features
- Full RFC compliance: Supports RFC 7517 (JWK), RFC 7518 (algorithms), RFC 8037 (EdDSA), and RFC 7638 (thumbprints)
- Multiple key types: RSA, EC (P-256, P-384, P-521, secp256k1), Symmetric (HMAC), and OKP (Ed25519, Ed448, X25519, X448)
- WASM compatible: Core functionality works in WebAssembly environments
- Security-first: Zeroize support for sensitive data, constant-time comparisons
- jwt-simple integration: Optional feature for converting JWKs to jwt-simple key types
- Remote fetching: Load JWKS from HTTP endpoints with caching support
- Caching: Optional TTL-based caching of decoded keys
Quick Start
Add to your Cargo.toml:
[]
= "0.1"
Parse a JWKS and find a key:
use KeySet;
let json = r#"{
"keys": [{
"kty": "RSA",
"kid": "my-key-id",
"use": "sig",
"n": "0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMstn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbISD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw",
"e": "AQAB"
}]
}"#;
let jwks: KeySet = from_str?;
let key = jwks.find_by_kid.expect;
assert!;
Feature Flags
| Feature | Default | Description |
|---|---|---|
jwt-simple |
❌ | Integration with the jwt-simple crate |
http |
❌ | Async HTTP fetching with caching support (reqwest) |
cloudflare |
❌ | Cloudflare Workers KV cache support |
Usage Examples
Basic JWKS Parsing
use ;
// Parse from JSON string
let jwks: KeySet = from_str?;
// Find keys by various criteria
let key = jwks.find_by_kid;
let rsa_keys = jwks.find_by_kty;
let signing_keys = jwks.find_by_use;
// Get the first signing key (common pattern)
let first_signing = jwks.first_signing_key;
// Iterate over all keys
for key in &jwks
Converting to jwt-simple Keys
With the jwt-simple feature enabled:
use KeySet;
use *;
let jwks: KeySet = from_str?;
let jwk = jwks.find_by_kid.unwrap;
// Convert to jwt-simple key type using TryFrom/TryInto
let key: RS256PublicKey = jwk.try_into?;
// Verify a JWT
let claims = key.?;
Fetching from HTTP
With the http feature enabled:
use ;
use Duration;
// Create remote key set (uses default 30s timeout)
let remote = new;
// For custom timeout, use a custom client
let client = builder
.timeout
.build?;
let remote = new_with_client;
// Fetch the JWKS
let jwks = remote.get_keyset.await?;
// For production, wrap with caching (5 minute TTL)
let cached = with_ttl;
let key = cached.get_key.await?;
Caching Keys
With the http feature enabled:
use ;
use Duration;
// Create a cached remote key source
let cached = with_ttl;
// Keys are automatically cached on first access
let key = cached.get_key.await?;
// Invalidate the entire cache when needed
cached.invalidate.await;
// Or invalidate a specific key
cached.invalidate_key.await;
JWK Thumbprints (RFC 7638)
use KeySet;
let jwks: KeySet = from_str?;
let key = jwks.first.unwrap;
// Calculate thumbprint (base64url-encoded SHA-256)
let thumbprint = key.thumbprint;
// Find key by thumbprint
let key = jwks.find_by_thumbprint;
Supported Key Types
RSA (kty: "RSA")
- Public keys: n, e
- Private keys: n, e, d, p, q, dp, dq, qi
- Algorithms: RS256, RS384, RS512, PS256, PS384, PS512
Elliptic Curve (kty: "EC")
- Curves: P-256, P-384, P-521, secp256k1
- Public keys: crv, x, y
- Private keys: crv, x, y, d
- Algorithms: ES256, ES384, ES512, ES256K
Symmetric (kty: "oct")
- Keys: k
- Algorithms: HS256, HS384, HS512, A128KW, A192KW, A256KW
Octet Key Pair (kty: "OKP")
- Curves: Ed25519, Ed448, X25519, X448
- Public keys: crv, x
- Private keys: crv, x, d
- Algorithms: EdDSA
Comparison to Other Libraries
| Feature | jwk-simple | jwks-client | jsonwebkey | jwt-simple | jsonwebtoken |
|---|---|---|---|---|---|
| Full JWKS spec | ✅ | ✅ | ❌ | ❌ | ❌ |
| RSA keys | ✅ | ✅ | ✅ | ✅ | ✅ |
| EC keys (P-256/384/521) | ✅ | ⚠️ | ✅ | ✅ | ✅ |
| EdDSA (Ed25519) | ✅ | ❌ | ❌ | ✅ | ✅ |
| Symmetric keys | ✅ | ❌ | ✅ | ✅ | ✅ |
| OKP keys (X25519) | ✅ | ❌ | ❌ | ❌ | ❌ |
| WASM support | ✅ | ❌ | ❓ | ✅ | ❓ |
| jwt-simple integration | ✅ | ❌ | ❌ | N/A | ❌ |
| HTTP fetching | ✅ | ✅ | ❌ | ❌ | ❌ |
| Caching | ✅ | ✅ | ❌ | ❌ | ❌ |
| Zeroize support | ✅ | ❌ | ✅ | ✅ | ❌ |
| No-panic guarantee | ✅ | ✅ | ❌ | ✅ | ❌ |
| JWK thumbprint (RFC 7638) | ✅ | ❌ | ❌ | ❌ | ❌ |
| TryFrom/TryInto traits | ✅ | ❌ | ❌ | ❌ | ✅ |
| Private key support | ✅ | ❌ | ✅ | ✅ | ❌ |
When to use jwk-simple
- You need jwt-simple integration - Direct conversion to jwt-simple key types
- You're building Cloudflare Workers - Native KV cache support
- You need WASM support - Core parsing works in browser
- You want full spec compliance - All key types including OKP
When to use alternatives
- jwks-client - If you only need RSA and want mature async HTTP
- jsonwebkey - If you need key generation and PEM/DER conversion
- jwt-simple - If you only need JWT operations, not JWKS
- jsonwebtoken - If you want the most widely-used JWT library
Security Considerations
This crate prioritizes security:
- Zeroize: Private key parameters are zeroed from memory on drop via the
zeroizecrate - Constant-time base64: Base64 encoding uses constant-time operations via
base64ct - Debug redaction: Debug output redacts sensitive key material
- No panics: All public functions return
Resulttypes - Input validation: Key parameters are validated for correct sizes
WASM Usage
Core JWKS parsing works in WebAssembly environments. The following features are NOT available in WASM:
http- No async HTTP in WASM (use browser fetch and pass JSON string)- File-based sources - No filesystem access
Example for WASM:
use KeySet;
// In WASM, fetch JWKS via browser APIs, then parse
let jwks: KeySet = from_str?;
let key = jwks.find_by_kid.expect;
License
The project is licensed under the MIT License.