Skip to main content

Official Python SDK for the Qpher Post-Quantum Cryptography API — ML-KEM-768 (FIPS 203) encryption, ML-DSA-65 (FIPS 204) digital signatures, and SLH-DSA (FIPS 205) hash-based signatures. Alternative to liboqs.

Project description

Qpher Python SDK

Official Python SDK for the Qpher Post-Quantum Cryptography API.

Installation

python -m venv .venv && source .venv/bin/activate   # recommended; avoids "externally-managed-environment" errors
pip install qpher

Requirements

  • Python 3.9+

Quick Start

Get a free API key (no credit card): https://portal.qpher.ai/register

from qpher import Qpher

# Initialize the client
client = Qpher(api_key="qph_your_api_key")

# Encrypt data using Kyber768 KEM.
# key_version is optional — omit it and the server uses your active key.
result = client.kem.encrypt(
    plaintext=b"Hello, Quantum World!",
)
print(f"Ciphertext: {result.ciphertext.hex()}")

# Decrypt data — decrypt always needs the exact key_version that encrypted it.
decrypted = client.kem.decrypt(
    ciphertext=result.ciphertext,
    key_version=result.key_version,
)
print(f"Plaintext: {decrypted.plaintext}")

# Sign a message using Dilithium3 (key_version optional — defaults to active key).
sig_result = client.signatures.sign(
    message=b"Invoice #12345",
)
print(f"Signature: {sig_result.signature.hex()}")

# Verify a signature
verify_result = client.signatures.verify(
    message=b"Invoice #12345",
    signature=sig_result.signature,
    key_version=sig_result.key_version,
)
print(f"Valid: {verify_result.valid}")

API Reference

Client Initialization

from qpher import Qpher

client = Qpher(
    api_key="qph_your_api_key",  # Required
    base_url="https://api.qpher.ai",  # Optional, default
    timeout=30,                        # Optional, seconds
    max_retries=3,                     # Optional
)

Some operations require MFA step-up re-verification — see https://docs.qpher.ai/security/mfa

KEM Operations (Kyber768)

Encrypt

key_version is optional. Omit it and the server encrypts with your tenant's active key; the resolved version is returned on result.key_version.

result = client.kem.encrypt(
    plaintext=b"secret data",
    mode="standard",      # Optional: "standard" or "deterministic"
    salt=b"...",          # Required if mode="deterministic" (min 32 bytes)
)
# result.ciphertext: bytes
# result.key_version: int   (the server-resolved active version)
# result.algorithm: str ("Kyber768")
# result.request_id: str

# To pin a specific version instead, pass key_version explicitly:
result = client.kem.encrypt(plaintext=b"secret data", key_version=5)

Decrypt

result = client.kem.decrypt(
    ciphertext=encrypted_data,
    key_version=1,
)
# result.plaintext: bytes
# result.key_version: int
# result.algorithm: str
# result.request_id: str

Signature Operations (Dilithium3)

Sign

key_version is optional. Omit it and the server signs with your tenant's active key; the resolved version is returned on result.key_version.

result = client.signatures.sign(
    message=b"document to sign",
)
# result.signature: bytes (3,293 bytes)
# result.key_version: int   (the server-resolved active version)
# result.algorithm: str ("Dilithium3")
# result.request_id: str

# To pin a specific version instead, pass key_version explicitly:
result = client.signatures.sign(message=b"document to sign", key_version=5)

Verify

result = client.signatures.verify(
    message=b"document to sign",
    signature=signature_bytes,
    key_version=1,
)
# result.valid: bool
# result.key_version: int
# result.algorithm: str
# result.request_id: str

Post-Quantum Hash-Based Signatures (SLH-DSA / FIPS 205)

Qpher implements FIPS 205 algorithms (SLH-DSA, also known as SPHINCS+), NIST-standardised hash-based signatures. SLH-DSA derives its security from cryptographic hash functions only, providing a conservative alternative to lattice-based signatures like ML-DSA (Dilithium3) for long-term archival and high-assurance workloads.

Algorithm value NIST Level Signature size Use case
SLH-DSA-SHA2-128s 1 ~7.9 KB Small signatures; slower signing
SLH-DSA-SHA2-128f 1 ~17 KB Faster signing for high-throughput
SLH-DSA-SHA2-192s 3 ~16 KB Recommended for long-term archive (30+ years)
SLH-DSA-SHA2-256s 5 ~29 KB Highest security; sovereign / compliance use

Pass the algorithm value through the existing sign / verify API:

result = client.signatures.sign(
    message=b"contract.pdf bytes",
    key_version=1,
    algorithm="SLH-DSA-SHA2-192s",
)
# result.signature: bytes (~16 KB for SHA2-192s)
# result.algorithm: str ("SLH-DSA-SHA2-192s")

verified = client.signatures.verify(
    message=b"contract.pdf bytes",
    signature=result.signature,
    key_version=1,
    algorithm="SLH-DSA-SHA2-192s",
)
# verified.valid: bool

Plan gating: SLH-DSA requires Personal+ plan. See https://qpher.ai/pricing.

Feature flag: SLH-DSA is shipped in this SDK release; the backend launch is gated behind a per-request feature flag (SLH_DSA_ENABLED) until the public launch date. Customers who pass SLH-DSA values today get 503 ERR_SIG_022 — this is the expected transitional behaviour.

Key Management

Generate Key

result = client.keys.generate(algorithm="Kyber768")
# result.key_version: int
# result.algorithm: str
# result.status: str ("active")
# result.public_key: bytes
# result.created_at: str

Rotate Key

result = client.keys.rotate(algorithm="Kyber768")
# result.key_version: int (new)
# result.old_key_version: int
# result.algorithm: str
# result.public_key: bytes

Get Active Key

key_info = client.keys.get_active(algorithm="Kyber768")
# key_info.key_version: int
# key_info.algorithm: str
# key_info.status: str
# key_info.public_key: bytes
# key_info.created_at: str

List Keys

result = client.keys.list(
    algorithm="Kyber768",  # Optional filter
    status="active",       # Optional filter: "active", "retired", "archived"
)
# result.keys: List[KeyInfo]
# result.total: int

Retire Key

result = client.keys.retire(algorithm="Kyber768", key_version=1)
# result.key_version: int
# result.status: str ("retired")

Error Handling

from qpher import (
    Qpher,
    QpherError,
    AuthenticationError,
    ValidationError,
    NotFoundError,
    RateLimitError,
)

try:
    result = client.kem.encrypt(plaintext=b"data", key_version=99)
except NotFoundError as e:
    print(f"Key not found: {e.message}")
    print(f"Error code: {e.error_code}")
    print(f"Request ID: {e.request_id}")
except RateLimitError as e:
    print("Rate limit exceeded, please retry later")
except AuthenticationError as e:
    print("Invalid API key")
except ValidationError as e:
    print(f"Invalid input: {e.message}")
except QpherError as e:
    print(f"API error: {e.message}")

Error Types

Exception HTTP Status Description
AuthenticationError 401 Invalid or missing API key
ValidationError 400 Invalid request parameters
ForbiddenError 403 Operation not allowed
NotFoundError 404 Resource not found
RateLimitError 429 Rate limit exceeded
ServerError 500+ Server-side errors
TimeoutError 504 Request timed out
ConnectionError 503 Connection failed

Supported Algorithms

Algorithm Type Security Level
Kyber768 (ML-KEM-768) KEM (Encryption) NIST Level 3
Dilithium3 (ML-DSA-65) Digital Signatures NIST Level 3
X-Wing (X25519 + ML-KEM-768) Hybrid KEM NIST Level 3
Composite ML-DSA (ECDSA P-256 + ML-DSA-65) Hybrid Signatures NIST Level 3
SLH-DSA-SHA2-128s/128f (SPHINCS+) Hash-Based Signatures (FIPS 205) NIST Level 1
SLH-DSA-SHA2-192s Hash-Based Signatures (FIPS 205) NIST Level 3
SLH-DSA-SHA2-256s Hash-Based Signatures (FIPS 205) NIST Level 5

Hybrid Mode (Pro/Enterprise plans): Pass algorithm="X-Wing" for hybrid KEM or algorithm="Composite-ML-DSA" for hybrid signatures. Without the algorithm parameter, PQC-only algorithms are used (backward-compatible).

Hybrid mode combines PQC with classical cryptography for defense-in-depth: if a lattice cryptanalysis breakthrough weakens ML-KEM or ML-DSA, the classical component (X25519 / ECDSA) still protects your data.

License

MIT License - see LICENSE for details.

Links

Alternative to: liboqs, AWS KMS PQC, Google Cloud KMS PQC.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

qpher-1.4.0.tar.gz (40.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

qpher-1.4.0-py3-none-any.whl (34.4 kB view details)

Uploaded Python 3

File details

Details for the file qpher-1.4.0.tar.gz.

File metadata

  • Download URL: qpher-1.4.0.tar.gz
  • Upload date:
  • Size: 40.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for qpher-1.4.0.tar.gz
Algorithm Hash digest
SHA256 da945bae3b84642932012ccf06ae47a3cf9fff45bd75f2af6e5b60d4e6bdf027
MD5 ef8981a3b2e86e1a6143aeeb84ed46ca
BLAKE2b-256 ed3093da54703ac8a6a446d34f63cfe3cdd0399512ac192eb938c3205979c340

See more details on using hashes here.

Provenance

The following attestation bundles were made for qpher-1.4.0.tar.gz:

Publisher: sdk-publish.yml on qpher/Qpher

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file qpher-1.4.0-py3-none-any.whl.

File metadata

  • Download URL: qpher-1.4.0-py3-none-any.whl
  • Upload date:
  • Size: 34.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for qpher-1.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 5c05eb4e3bdb749ef9fc618f89a43cfa84365c8df99cf86fa5db452a18a96593
MD5 fdcf20909b55eade21d31a7d12283043
BLAKE2b-256 3ed7b5d4ce3202cb9ea74a82a0cf27f52471acd4f412160d9ebc7cdff5be81fa

See more details on using hashes here.

Provenance

The following attestation bundles were made for qpher-1.4.0-py3-none-any.whl:

Publisher: sdk-publish.yml on qpher/Qpher

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page