Metadata-Version: 2.4
Name: qpher
Version: 1.0.0
Summary: Official Python SDK and CLI for the Qpher Post-Quantum Cryptography API
Project-URL: Homepage, https://qpher.ai
Project-URL: Documentation, https://docs.qpher.ai/sdks/python
Project-URL: Repository, https://github.com/qpher/qpher-python
Project-URL: Issues, https://github.com/qpher/qpher-python/issues
Author-email: Qpher <sdk@qpher.ai>
License-Expression: MIT
License-File: LICENSE
Keywords: cli,cryptography,dilithium,encryption,kyber,post-quantum,pqc,signatures
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
pip install qpher
```

## Requirements

- Python 3.9+

## Quick Start

```python
from qpher import Qpher

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

# Encrypt data using Kyber768 KEM
result = client.kem.encrypt(
    plaintext=b"Hello, Quantum World!",
    key_version=1,
)
print(f"Ciphertext: {result.ciphertext.hex()}")

# Decrypt data
decrypted = client.kem.decrypt(
    ciphertext=result.ciphertext,
    key_version=result.key_version,
)
print(f"Plaintext: {decrypted.plaintext}")

# Sign a message using Dilithium3
sig_result = client.signatures.sign(
    message=b"Invoice #12345",
    key_version=1,
)
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_live_your_api_key",  # Required
    base_url="https://api.qpher.ai",  # Optional, default
    timeout=30,                        # Optional, seconds
    max_retries=3,                     # Optional
)
```

### KEM Operations (Kyber768)

#### Encrypt

```python
result = client.kem.encrypt(
    plaintext=b"secret data",
    key_version=1,
    mode="standard",      # Optional: "standard" or "deterministic"
    salt=b"...",          # Required if mode="deterministic" (min 32 bytes)
)
# result.ciphertext: bytes
# result.key_version: int
# result.algorithm: str ("Kyber768")
# result.request_id: str
```

#### 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

```python
result = client.signatures.sign(
    message=b"document to sign",
    key_version=1,
)
# result.signature: bytes (3,293 bytes)
# result.key_version: int
# result.algorithm: str ("Dilithium3")
# result.request_id: str
```

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

### 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 |

> **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)
- [GitHub Repository](https://github.com/qpher/qpher-python)
