pqblocks-jose
Post-quantum hybrid JOSE (Javascript Object Signing and Encryption) library providing hybrid JWS (JSON Web Signature) and hybrid JWE (JSON Web Encryption) tokens.
pqblocks-jose combines NIST post-quantum primitives (FIPS 203 ML-KEM-768 and FIPS 204 ML-DSA-65) with classical counterparts (X25519, Ed25519) to ensure security against both quantum and classical adversaries without compromising backwards security.
Key Features
- Hybrid JWS (Signatures): ML-DSA-65 + Ed25519 dual composite signature. Both signatures must verify; if either fails, the token is rejected.
- Hybrid JWE (Encryption): Dual-KEM encapsulation using X25519 and ML-KEM-768 combined via HKDF-SHA256 (X-Wing combiner architecture) protecting AES-256-GCM authenticated payload encryption.
- Misuse-Resistant API:
- Enforced
Policyobjects controlling accepted algorithms, token byte length limits, and KDF labels. - Strict asymmetric enforcement: Decryption requires a private key; public keys cannot decrypt.
- Hardened against algorithm downgrade and parameter manipulation.
- Enforced
- Standards & KAT Tested:
- Primitives verified against NIST ACVP (FIPS 203 / FIPS 204) and Google Project Wycheproof test vectors.
- CLI Utility: Bundled CLI for generating keypairs, encoding/decoding JWS, and encrypting/decrypting JWE.
Installation
pip install pqblocks-jose
System Dependencies
pqblocks-jose uses cryptography (OpenSSL-backed) for underlying cryptographic operations. If using the optional liboqs acceleration backend, ensure liboqs.so is available on your library search path:
export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH
Quickstart
from pqblocks_jose import Policy, generate_keypair, encode_jws, decode_jws, encrypt_jwe, decrypt_jwe
# 1. Define an enforceable policy
policy = Policy(
version=1,
kem="X25519+MLKEM768", # Hybrid KEM for JWE
sig="MLDSA65+Ed25519", # Hybrid signature for JWS
kdf="HKDF-SHA256", # Mandatory KDF enforcement
max_token_bytes=8192, # Header-safe limit
kdf_info="JOSE_PostQuantum_Traditional_Hybrid X25519MLKEM768",
sig_alg_std="ML-DSA-65-Ed25519"
)
# 2. Generate hybrid keypairs
sign_keypair = generate_keypair("ML-DSA-65-Ed25519", seed=12345)
enc_keypair = generate_keypair("X25519+MLKEM768", seed=12345)
# 3. Sign & verify a JWS token
payload = {"sub": "alice@example.com", "iat": 1700000000, "aud": "api.internal"}
jws_result = encode_jws(payload, policy, private_key=sign_keypair.private_key)
# Verify with public key
verification = decode_jws(
token=jws_result.compact_serialization,
policy=policy,
public_key=sign_keypair.public_key
)
print(f"JWS verified: {verification.signature_verified}")
print(f"JWS token size: {len(jws_result.compact_serialization)} bytes")
# 4. Encrypt & decrypt a JWE token
plaintext = b"session_key:random123nonce"
jwe_result = encrypt_jwe(plaintext, policy, public_key=enc_keypair.public_key)
# Decrypt with private key
decryption = decrypt_jwe(
token=jwe_result.compact_serialization,
policy=policy,
private_key=enc_keypair.private_key
)
print(f"JWE decrypted matches: {decryption.plaintext == plaintext}")
CLI Usage
The package installs the pqblocks-jose command-line tool:
# Print version and help
pqblocks-jose --version
pqblocks-jose --help
# Generate a hybrid keypair
pqblocks-jose generate keypair --algorithm "ML-DSA-65-Ed25519"
# Encode and decode JWS
pqblocks-jose encode jws --payload '{"sub":"admin","scope":"ops"}'
pqblocks-jose decode jws --token <TOKEN>
# Encrypt and decrypt JWE
pqblocks-jose encrypt jwe --plaintext "c2VjcmV0IGRhdGE="
pqblocks-jose decrypt jwe --token <TOKEN>
Security Model & Non-Claims
License
This project is licensed under the Apache 2.0 License. See LICENSE and NOTICE for details.
Metadata
Release files for pqblocks-jose 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| pqblocks_jose-0.1.0.tar.gz | 72.3 kB | Without provenance | Details for pqblocks_jose-0.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| pqblocks_jose-0.1.0-py3-none-any.whl | Python 3 | none | any | Details for pqblocks_jose-0.1.0-py3-none-any.whl |
Total release size: 119.9 kB
Release files / pqblocks_jose-0.1.0.tar.gz
| Download URL | pqblocks_jose-0.1.0.tar.gz |
|---|---|
| Size | 72.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
179937f6a75ab446bb9e96a46d610ed4317ac04691287a6e44bda44a81d1714e
|
|
BLAKE2b-256 checksum How to use checksums |
6a88820e556a215d935f8351f968eaa7d1c63e235a6cb1b3a264f1c3284ec0f6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / pqblocks_jose-0.1.0-py3-none-any.whl
| Download URL | pqblocks_jose-0.1.0-py3-none-any.whl |
|---|---|
| Size | 47.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
475165f869fb47f89a4ce869bdc22224e9d6d81aa4cc6f66bbd7b5948ca62acb
|
|
BLAKE2b-256 checksum How to use checksums |
b6bf68427eb5557aace0d474aa6d6f55697ecf2bfda1ba1ff50a5e0efa14998a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Security for pqblocks-jose 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.