Python SDK for PARAMANT — post-quantum file transport (ML-KEM-768 + ML-DSA-65, wire format v1)
Project description
Paramant SDK for Python — real post-quantum file encryption
Python client for the PARAMANT post-quantum relay.
v3.0.0 swaps the v2.x kyber-py dependency (whose own README explicitly
warns against production use: not constant-time, timing-attack vulnerable)
and the silent ECDH fallback for pqcrypto
— a thin CFFI wrapper around the audited PQClean C implementations. The SDK
now produces wire-format v1 blobs (PQHB magic) and negotiates algorithm
support with the relay via GET /v2/capabilities before the first send.
Default algorithms: ML-KEM-768 (NIST FIPS 203) for key encapsulation and ML-DSA-65 (NIST FIPS 204) for signatures.
Install
pip install 'paramant-sdk>=3'
pqcrypto ships pre-built wheels for Linux, macOS and Windows — no compiler
needed. If the install fails because wheels are missing for your platform, the
SDK will raise a clear ImportError at module load rather than silently
degrading.
Quick start
from paramant_sdk import GhostPipe
# Defaults: ML-KEM-768 + ML-DSA-65, wire format v1
gp = GhostPipe(api_key='pgp_your_key', device='sender-001')
gp.receive_setup()
# Send
blob_hash, inclusion_proof = gp.send(b'encrypt me', recipient='receiver-001')
# Receive (burn-on-read)
data, receipt = gp.receive(blob_hash)
Overriding algorithms
# Anonymous (unsigned) blob: still ML-KEM-768, but no sender identity attached
gp = GhostPipe('pgp_...', 'device', sig_id=0x0000)
# Future: when the relay loads Falcon-512 for signatures
gp = GhostPipe('pgp_...', 'device', sig_id=0x0100)
The client calls /v2/capabilities before the first blob and validates that
the relay supports the requested kem_id / sig_id. Unsupported combination
→ CapabilityMismatch. No silent fallback.
Capabilities introspection
caps = gp.capabilities()
print(caps.wire_version) # 1
print(caps.kem_names()) # ['ML-KEM-512', 'ML-KEM-768', 'ML-KEM-1024']
print(caps.sig_names()) # ['none', 'ML-DSA-44', 'ML-DSA-65', 'Falcon-512', ...]
Breaking changes from 2.x
- Dependency swap:
kyber-pyremoved,pqcrypto>=0.4,<1.0required. kyber-py was author-declared not production-safe (see its own README). - ECDH silent fallback removed. v2.x degraded to ECDH-P256 + AES-GCM when
kyber-pywas absent while still advertising post-quantum protection. v3 raisesImportErrorat module load ifpqcryptois missing. - Wire format: legacy 0x02 format is gone. v3 produces and consumes wire
format v1 (
PQHBmagic, 10-byte header, algorithm IDs, length-prefixed fields). Seedocs/wire-format-v1.md. - Capability negotiation: the client calls
/v2/capabilitieson construction. Disable withnegotiate_on_init=Falsefor offline testing only. - Keypair file (
~/.paramant/<device>.keypair.json): v2.x files withoutml_kem_pub/ml_dsa_pubare renamed to*.v2.bakon first use and a fresh v3 keypair is generated. v2 blobs cannot be decrypted by v3. - Python: minimum 3.10 (unchanged).
Migration
# 2.x: silent ECDH fallback, empty ML-KEM hex, wire format 0x02
from paramant_sdk import GhostPipe
gp = GhostPipe('pgp_...', 'device') # may have silently used ECDH
gp.send(data) # blob starts with 0x00 00 00 ?? length prefix
# 3.x: real ML-KEM-768 + ML-DSA-65, wire format v1 (PQHB)
from paramant_sdk import GhostPipe
gp = GhostPipe('pgp_...', 'device') # ImportError if pqcrypto missing
gp.send(data) # blob starts with 50 51 48 42 (PQHB)
In-flight 2.x blobs will not decrypt under v3 — plan a drain window or re-upload.
Algorithm matrix
| Component | Algorithm | ID (wire) | Source |
|---|---|---|---|
| KEM | ML-KEM-768 | 0x0002 |
pqcrypto / PQClean |
| Signature | ML-DSA-65 | 0x0002 |
pqcrypto / PQClean |
| Signature | (none, anon) | 0x0000 |
skips signature section |
| AEAD | AES-256-GCM | — | cryptography |
| KDF | HKDF-SHA-256 | — | cryptography |
The relay may load additional algorithms (ML-KEM-512/1024, ML-DSA-44/87,
Falcon-512/1024, SLH-DSA). Check gp.capabilities() at runtime.
Security properties
- Post-quantum KEM: ML-KEM-768 meets NIST FIPS 203 category 3.
- Post-quantum signatures: ML-DSA-65 meets NIST FIPS 204 category 3.
- Header integrity: the 10-byte wire header (magic, version, KEM_ID, SIG_ID, FLAGS) is bound to the payload via GCM AAD. A bit-flip in the algorithm IDs aborts decryption.
- Key zeroization: best-effort
ctypes.memsetof shared secrets and derived AES keys on CPython. Non-CPython runtimes emit a warning.
Version
Current: 3.0.0 — matches relay v3 wire format, interoperable with
sdk-js >= 3 and the Chromium / Outlook clients.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file paramant_sdk-3.0.0.tar.gz.
File metadata
- Download URL: paramant_sdk-3.0.0.tar.gz
- Upload date:
- Size: 26.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
234bc1f9b5202c3c1bbf6a45ba459ac900038b9a8565a1d55d25aa45c6b5eace
|
|
| MD5 |
b2210293e46842aefccd5400e45cca89
|
|
| BLAKE2b-256 |
1e21dfac826e181ea8ad212c23b9834dc8e391358ab67fec53fb249455417c50
|
File details
Details for the file paramant_sdk-3.0.0-py3-none-any.whl.
File metadata
- Download URL: paramant_sdk-3.0.0-py3-none-any.whl
- Upload date:
- Size: 21.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
658bff6e978ccfe6edeb14d705b748aaf403176b68bcd5848493a3cc2ac4c24a
|
|
| MD5 |
91ebda939d930bb08cf330b944141ebd
|
|
| BLAKE2b-256 |
115cdbcf1361165532ee2c6586a0c17b4ed7adb3bb0b1052d256fe7909d355ee
|