Install & Compatibility
Where this runs
tested against v1.5.9 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
muslpy 3.10–3.95 runs
installs and imports cleanly · install 0.0s · import 0.348s · 35.7MB
glibcpy 3.10–3.95 runs
installs and imports cleanly · install 2.5s · import 0.336s · 36MB
34MB installed
● package 34MB
Code
Verified usage
Verified import paths — ran on the pinned version, not inferred.
JWK
✓ from jwcrypto import jwk
JWS
✓ from jwcrypto import jws
JWE
✓ from jwcrypto import jwe
JWT
✓ from jwcrypto import jwt
json_encode, json_decode
✓ from jwcrypto.common import json_encode, json_decode
This quickstart demonstrates how to generate a symmetric key, sign a payload using JWS, and then verify the signed token. It utilizes `jwk` for key management and `jws` for signature operations, along with `jwcrypto.common` for JSON encoding.
from jwcrypto import jwk, jws
from jwcrypto.common import json_encode
# 1. Generate a symmetric key
key = jwk.JWK.generate(kty='oct', size=256)
# 2. Define the payload and JWS headers
payload = "My Integrity protected message"
jwstoken = jws.JWS(payload.encode('utf-8'))
# 3. Add signature to the token
jwstoken.add_signature(
key,
None,
json_encode({"alg": "HS256"}),
json_encode({"kid": key.thumbprint()})
)
# 4. Serialize the JWS token
signed_token = jwstoken.serialize()
print(f"Signed JWS: {signed_token}")
# 5. Verify the JWS token
verifier_token = jws.JWS()
verifier_token.deserialize(signed_token)
verifier_token.verify(key)
# 6. Access the verified payload
verified_payload = verifier_token.payload.decode('utf-8')
print(f"Verified Payload: {verified_payload}")
Debug
Known issues
breakingThe JWT module introduced security fixes in v1.4.0 (CVE-2022-3102) that prevent token type substitution attacks. This required changes to token validation, defaulting to 'JWS' unless explicitly set or inferred. Old applications might break if they relied on implicit auto-detection without specifying `expect_type` or allowing mixed-type tokens.fixExplicitly set the `expect_type` argument in `jwt.JWT` validation, or ensure that only appropriate algorithms are used to prevent type confusion. A 'born-deprecated' module-level variable can temporarily restore old behavior, but refactoring is strongly recommended.
affects: >=1.4.0
deprecatedThe `RSA1_5` algorithm is considered deprecated due to severe security vulnerabilities (Bleichenbacher RSA padding oracle, Million messages attack). Using it can lead to decryption of intercepted messages or forging signatures.fixAvoid using `RSA1_5`. If absolutely necessary, it requires explicit re-enabling at object instantiation. Consider migrating to `RSA-OAEP` or `RSASSA-PSS` for secure RSA operations.
affects: All versions, deprecated since 2020.12.11
breakingSupport for Python 3.6 and 3.7 was dropped starting with version 1.5.3. Installations on these Python versions will likely encounter compatibility issues.fixUpgrade your Python environment to version 3.8 or newer to ensure compatibility and receive continued updates and security patches.
affects: >=1.5.3
breakingThe minimum required version for the `cryptography` library was raised to 3.4 in `jwcrypto` v1.5.0. Older versions of `cryptography` will cause dependency resolution failures or runtime errors.fixEnsure `cryptography>=3.4` is installed. `pip install --upgrade cryptography` can resolve this.
affects: >=1.5.0
gotchaJWT payloads are base64-encoded, not encrypted. This means anyone with the token can easily decode and read its contents. Storing sensitive information directly in a JWT payload is a major security risk.fixNever store sensitive, confidential, or personally identifiable information (PII) directly in a JWT payload. Use JWE (JSON Web Encryption) if the content needs to be confidential, or store sensitive data securely on the server and use the JWT to reference it.
affects: All versions
gotchaLack of proper validation for the `kid` (Key ID) header parameter can lead to key confusion attacks, where an attacker might influence which key is used for verification.fixImplement strict validation of the `kid` parameter to ensure it corresponds to an expected key from a trusted source. Do not allow arbitrary `kid` values to dictate key selection without proper authorization.
affects: All versions
gotchaVersions 1.5.1 and 1.5.6 addressed potential Denial of Service (DoS) vulnerabilities related to PBKDF2 symmetric keys (v1.5.1) and high compression ratios (v1.5.6). Older versions might be susceptible.fixUpgrade to the latest version of `jwcrypto` (1.5.6 or newer) to patch these potential DoS vectors and ensure your application is protected against these specific attacks.
affects: <1.5.1 and <1.5.6
Errors
Common errors & fixes
ModuleNotFoundError: No module named 'jwcrypto'
The `jwcrypto` package is not installed in the Python environment.
fixRun `pip install jwcrypto` to install the library.
jwcrypto.jwe.InvalidJWEData: No recipient matched the provided key
The JWE token cannot be decrypted because the provided key does not match any of the recipient keys in the token, or the token itself is malformed or tampered with, resulting in an 'Invalid Tag' during decryption.
fixEnsure the correct decryption key (JWK object) is being used and that it corresponds to one of the recipients in the JWE token. Verify the token's integrity and source.
jwcrypto.common.JWKeyNotFound: The key needed to complete the operation was not found
An operation requiring a specific key (e.g., by 'kid' or 'use' parameter) was attempted on a JWKSet, but the necessary key was not present in the set.
fixEnsure the JWKSet contains the required key for the operation, or provide the specific key directly if it's not part of a set.
jwcrypto.common.InvalidJWAAlgorithm: Invalid JWA Algorithm name
An unsupported or incorrect algorithm name was specified in the JOSE header for a JWS or JWE operation.
fixRefer to the JWCrypto documentation for supported algorithms and ensure the 'alg' or 'enc' parameter in your header matches an implemented algorithm.
TypeError: object of type '_RSAPrivateKey' has no len()
This error typically occurs when an asymmetric key (like an RSA private key) is mistakenly used with a symmetric algorithm (like HS256), which expects a symmetric secret (bytes or string that can determine length) for operations like signing.
fixEnsure that the cryptographic algorithm specified in the JWT/JWS header matches the type of key being used. Use appropriate asymmetric algorithms (e.g., RS256, PS256) for RSA keys, and symmetric algorithms (e.g., HS256, HS512) for symmetric shared secrets (oct keys).
Upgrade
Version history
1.5.9latest on PyPI · released Aug 26, 2026
Audit
Dependencies
cryptographyrequiredCore cryptographic operations are delegated to this library.
typing_extensionsrequiredUsed for backported and experimental type hints.