Metadata-Version: 2.4
Name: qpher
Version: 1.4.0
Summary: 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-URL: Homepage, https://qpher.ai
Project-URL: Documentation, https://docs.qpher.ai/sdks/python
Project-URL: Repository, https://github.com/qpher/Qpher
Project-URL: Issues, https://github.com/qpher/Qpher/issues
Author-email: Qpher <sdk@qpher.ai>
License-Expression: MIT
License-File: LICENSE
Keywords: cli,cryptography,dilithium,encryption,fips-203,fips-204,fips-205,kem,kyber,ml-dsa,ml-kem,nist-pqc,post-quantum,pqc,quantum-safe,signatures,slh-dsa,sphincs-plus,x-wing
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Security :: Cryptography
Requires-Python: >=3.9
Requires-Dist: click>=8.1.0
Requires-Dist: cryptography>=41.0.0
Requires-Dist: requests>=2.31.0
Requires-Dist: tomli-w>=1.0.0
Requires-Dist: tomli>=2.0.0; python_version < '3.11'
Provides-Extra: dev
Requires-Dist: pytest-cov>=4.1.0; extra == 'dev'
Requires-Dist: pytest>=7.4.0; extra == 'dev'
Requires-Dist: responses>=0.24.0; extra == 'dev'
Description-Content-Type: text/markdown

# Qpher Python SDK

Official Python SDK for the [Qpher](https://qpher.ai) Post-Quantum Cryptography API.

## Installation

```bash
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

```python
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

```python
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`.

```python
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

```python
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`.

```python
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

```python
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:

```python
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

```python
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

```python
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

```python
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

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

#### Retire Key

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

## Error Handling

```python
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](LICENSE) for details.

## Links

- [Qpher Website](https://qpher.ai)
- [API Documentation](https://docs.qpher.ai)
- [API Reference](https://docs.qpher.ai/api-reference)
- [Code Examples](https://github.com/qpher/qpher-python/tree/main/examples)
- [GitHub Repository](https://github.com/qpher/qpher-python)
- [FIPS 203 — ML-KEM (Kyber768)](https://csrc.nist.gov/pubs/fips/203/final)
- [FIPS 204 — ML-DSA (Dilithium3)](https://csrc.nist.gov/pubs/fips/204/final)

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