qpher 0.1.0
Official Python SDK for the Qpher Post-Quantum Cryptography API
Requires Python: >=3.9
Keywords: cryptography, dilithium, encryption, kyber, post-quantum, pqc, signatures

# 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 | KEM (Encryption) | NIST Level 3 |
| Dilithium3 | Digital Signatures | NIST Level 3 |

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