Metadata-Version: 2.4
Name: lycan
Version: 0.1.0
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Rust
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Programming Language :: Python :: 3.15
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Programming Language :: Python :: Implementation :: PyPy
Classifier: Topic :: Security :: Cryptography
Summary: Python bindings for RustCrypto algorithms
Requires-Python: >=3.10
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM

# Lycan

Python bindings for selected RustCrypto post-quantum algorithms.

Lycan currently wraps:

- ML-KEM from RustCrypto `ml-kem`
- ML-DSA from RustCrypto `ml-dsa`
- SLH-DSA from RustCrypto `slh-dsa`

## Security Warning

The underlying RustCrypto implementations wrapped by Lycan have not all been independently audited.

USE AT YOUR OWN RISK.

Lycan also adds a Python FFI layer. Keep secret-key objects in their Rust-backed classes when possible. Export helpers such as `to_seed()` and `to_private_bytes()` create immutable Python `bytes` copies, and Lycan cannot reliably zeroize Python-managed memory after those copies exist.

## Install for development

```bash
uv run maturin develop
```

## ML-KEM

```python
import lycan

secret_key, public_key = lycan.ml_kem_keygen("ML-KEM-768")
ciphertext, sender_secret = lycan.ml_kem_encapsulate(public_key, "ML-KEM-768")
receiver_secret = secret_key.decapsulate(ciphertext)

assert sender_secret == receiver_secret
```

Available ML-KEM algorithms:

```python
lycan.ml_kem_algorithms()
```

## ML-DSA

```python
secret_key, public_key = lycan.ml_dsa_keygen("ML-DSA-65")
signature = secret_key.sign(b"message", context=b"example")

assert lycan.ml_dsa_verify(
    "ML-DSA-65", public_key, b"message", signature, context=b"example"
)
```

Available ML-DSA algorithms:

```python
lycan.ml_dsa_algorithms()
```

## SLH-DSA

```python
secret_key, public_key = lycan.slh_dsa_keygen("SLH-DSA-SHAKE-128f")
signature = secret_key.sign(b"message", context=b"example")

assert lycan.slh_dsa_verify(
    "SLH-DSA-SHAKE-128f", public_key, b"message", signature, context=b"example"
)
```

Available SLH-DSA algorithms:

```python
lycan.slh_dsa_algorithms()
```

