clavium-q
SDK Python officiel pour l'API CLAVIUM-Q / CERTROPI — clés post-quantiques (ML-KEM FIPS 203, SLH-DSA FIPS 205) générées depuis une graine QRNG-DI certifiée Device-Independent.
Produit distinct d'Alea-Q — service séparé (api.clavium-q.com), clés kg_silv_/kg_plat_, pas de tier Ivory pour la PQC.
Installation
pip install clavium-q
# Avec déchiffrement local des enveloppes post-quantiques
pip install "clavium-q[verify]"
Démarrage rapide
from clavium_q import ClaviumQClient
# Clé API dans le constructeur ou variable d'env CLAVIUM_Q_API_KEY
client = ClaviumQClient(api_key="kg_plat_xxx")
# ML-KEM (FIPS 203) — encapsulation de clé
kp = client.platinum.mlkem_keygen(param_set="ML_KEM_768")
print(kp.ek, kp.dk)
encaps = client.platinum.mlkem_encaps(ek=kp.ek)
print(encaps.shared_key, encaps.ciphertext)
# SLH-DSA (FIPS 205) — génération de clé, signature, vérification
sig_kp = client.silver.slhdsa_keygen(param_set="SLH_DSA_SHAKE_256s")
signed = client.silver.slhdsa_sign(sk=sig_kp.sk, message="document à signer")
verified = client.silver.slhdsa_verify(
pk=sig_kp.pk, signature=signed.signature, message="document à signer",
)
print(verified.valid) # True — ne lève pas d'exception si False
Authentification
# Option 1 — clé dans le constructeur
client = ClaviumQClient(api_key="kg_plat_xxx")
# Option 2 — variable d'environnement
import os
os.environ["CLAVIUM_Q_API_KEY"] = "kg_plat_xxx"
client = ClaviumQClient()
Le tier est détecté automatiquement depuis le préfixe de la clé (kg_silv_ / kg_plat_) :
client = ClaviumQClient(api_key="kg_plat_xxx")
print(client.tier) # "platinum"
Provisioning : les clés kg_* sont attribuées manuellement — pas d'auto-inscription. Contactez le support CERTROPI pour un accès.
Tiers disponibles
| Tier | Source de la graine | Certification |
|---|---|---|
| Platinum | Ordinateur quantique réel | Device-Independent |
| Silver | DRBG seedé quantique | Seed quantique |
Aucun tier gratuit/self-service pour la PQC (contrairement à Alea-Q).
Post-quantique — ML-KEM (FIPS 203)
Disponible sur Silver et Platinum (client.silver.* / client.platinum.*, mêmes méthodes).
kp = client.platinum.mlkem_keygen(param_set="ML_KEM_768")
print(kp.ek, kp.dk)
encaps = client.platinum.mlkem_encaps(ek=kp.ek)
print(encaps.shared_key, encaps.ciphertext)
# Decaps est une opération LOCALE (le serveur ne voit jamais dk) —
# nécessite l'extra 'verify' : pip install 'clavium-q[verify]'
from clavium_q import mlkem_decaps
shared_key = mlkem_decaps(kp.dk, encaps.ciphertext, param_set=kp.param_set)
assert shared_key.hex() == encaps.shared_key # même secret des deux côtés
Post-quantique — SLH-DSA (FIPS 205)
Seule la génération de clé (slhdsa_keygen()) consomme une graine QRNG-DI. slhdsa_sign() / slhdsa_verify() sont des opérations crypto pures côté serveur sur des clés déjà fournies par le client — chaque appel fait un round-trip réseau, mais aucun des deux n'entame de quota d'entropie.
sig_kp = client.platinum.slhdsa_keygen(param_set="SLH_DSA_SHAKE_256s")
print(sig_kp.sk, sig_kp.pk)
signed = client.platinum.slhdsa_sign(
sk=sig_kp.sk,
message="document à signer",
param_set="SLH_DSA_SHAKE_256s",
)
print(signed.signature, signed.sig_size)
verified = client.platinum.slhdsa_verify(
pk=sig_kp.pk,
signature=signed.signature,
message="document à signer",
param_set="SLH_DSA_SHAKE_256s",
)
print(verified.valid)
Fichiers volumineux (sign_file / verify_file)
message/message_b64 sont bornés en taille (protection mémoire) — pour un fichier volumineux, utiliser les variantes multipart :
with open("document.pdf", "rb") as f:
signed = client.platinum.slhdsa_sign_file(sk=sig_kp.sk, file=f, filename="document.pdf")
with open("document.pdf", "rb") as f:
verified = client.platinum.slhdsa_verify_file(
pk=sig_kp.pk, signature=signed.signature, file=f, filename="document.pdf",
)
Livraison sécurisée de clé privée (Platinum, recipient_pk)
Pour ne jamais faire transiter une clé privée en clair, mlkem_keygen() et slhdsa_keygen() acceptent (Platinum uniquement) un recipient_pk — la clé privée générée revient alors enveloppée (ML-KEM + AES-256-GCM + signature SLH-DSA) dans .envelope au lieu d'être renvoyée en clair dans .dk / .sk :
import base64
from clavium_q import mlkem_decaps
kp = client.platinum.slhdsa_keygen(recipient_pk=my_mlkem_pubkey_hex)
if kp.envelope:
# kp.sk est vide — la clé réelle est dans kp.envelope["encrypted_payload"],
# chiffrée pour my_mlkem_pubkey_hex. my_mlkem_dk = dk ML-KEM du
# destinataire (généré localement, jamais transmis au serveur) — la
# décapsulation reste locale, le serveur ne voit jamais ni my_mlkem_dk
# ni le secret déchiffré.
#
# ATTENTION : les champs de l'enveloppe (ciphertext, encrypted_payload,
# nonce, signature, certropi_pk) sont en BASE64 — contrairement à
# dk/ek/shared_key (mlkem_keygen()/mlkem_encaps()) qui sont en HEX.
ciphertext = base64.b64decode(kp.envelope["ciphertext"])
shared_key = mlkem_decaps(my_mlkem_dk, ciphertext, param_set="ML_KEM_768")
# shared_key (32 octets) est la clé AES-256-GCM utilisée pour chiffrer
# kp.envelope["encrypted_payload"] (nonce en base64 lui aussi) —
# déchiffrement AES-GCM restant à la charge de l'appelant, non fourni
# par ce SDK à ce jour.
Context manager
with ClaviumQClient(api_key="kg_plat_xxx") as client:
kp = client.platinum.mlkem_keygen()
Client asynchrone
import asyncio
from clavium_q import AsyncClaviumQClient
async def main():
async with AsyncClaviumQClient(api_key="kg_plat_xxx") as client:
kp = await client.platinum.mlkem_keygen()
print(kp.ek, kp.dk)
asyncio.run(main())
Gestion des erreurs
from clavium_q import ClaviumQClient
from clavium_q.exceptions import AuthenticationError, BackendUnavailable, PermissionError
client = ClaviumQClient()
try:
kp = client.platinum.mlkem_keygen()
except BackendUnavailable as e:
print(f"Source d'entropie indisponible — réessayer dans {e.retry_after}s")
except AuthenticationError:
print("Clé API invalide")
except PermissionError:
print("Tier insuffisant, ou abonnement suspendu/expiré")
Configuration
| Variable d'env | Description | Défaut |
|---|---|---|
CLAVIUM_Q_API_KEY |
Clé API | — |
CLAVIUM_Q_BASE_URL |
URL de base de l'API | https://api.clavium-q.com |
CLAVIUM_Q_TIMEOUT |
Timeout HTTP en secondes | 60 |
Développement
pip install -e ".[dev]"
# Suite de tests (mock HTTP via respx — aucun accès réseau requis)
pytest
# Tests contre l'API réelle (marqués `smoke`, nécessitent CLAVIUM_Q_API_KEY
# et un accès réseau — exclus par défaut)
pytest -m smoke
Licence
Propriétaire — CERTROPI © 2026
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 clavium_q-0.1.0.tar.gz.
File metadata
- Download URL: clavium_q-0.1.0.tar.gz
- Upload date:
- Size: 17.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.11.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7d46bd75df7bfc5db74c2a15f4df98893c4c35fdd53e602ce63e9b1b080b6055
|
|
| MD5 |
27d865800f79cc05522086c73d2d96a6
|
|
| BLAKE2b-256 |
eedc0c005b0a4f37d3e47c19edbf1ebc1f8e25f7b7bf59375bcd626e085cf357
|
File details
Details for the file clavium_q-0.1.0-py3-none-any.whl.
File metadata
- Download URL: clavium_q-0.1.0-py3-none-any.whl
- Upload date:
- Size: 16.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.11.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8ae085a767ceded0731b3eb75309e104a66de27f6b1cbf8abde45391135cb464
|
|
| MD5 |
1f5ef74fb0c299b6b3fbfee386391d8d
|
|
| BLAKE2b-256 |
4b65cd92bd0126ddfcf69a9c40528da2f4bc32b9734526d78181e8751235f4e0
|