Metadata-Version: 2.4
Name: larzcrypt
Version: 0.1.1
Summary: Batteries-included pure-Python cryptography: hashing, HKDF, ChaCha20-Poly1305, X25519, Ed25519, ECDSA, JWT, sealed boxes. Zero dependencies.
Author: larz-scripter
License: MIT
Project-URL: Homepage, https://github.com/larz-scripter/larzcrypt
Project-URL: Repository, https://github.com/larz-scripter/larzcrypt
Project-URL: Documentation, https://github.com/larz-scripter/larzcrypt#readme
Project-URL: Issues, https://github.com/larz-scripter/larzcrypt/issues
Keywords: cryptography,crypto,ed25519,x25519,chacha20,poly1305,secp256k1,ecdsa,jwt,hkdf,scrypt,aead,sealed-box,signatures,encryption,zero-dependency,pure-python
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.8
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: Programming Language :: Python :: 3.13
Classifier: Topic :: Security :: Cryptography
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Provides-Extra: fast
Requires-Dist: coincurve>=18; extra == "fast"
Dynamic: license-file

# larzcrypt

**Batteries-included, pure-Python cryptography. Zero dependencies.**

The primitives you actually reach for — hashing, HMAC, key derivation, password
hashing, authenticated encryption, key agreement, and signatures — behind one
small, hard-to-misuse import surface, with nothing to compile and nothing to
install.

```python
from larzcrypt import ed25519, seal, unseal, hash_password, check_password

# sign & verify
priv, pub = ed25519.generate_keypair()
sig = ed25519.sign(priv, b"ship it")
assert ed25519.verify(pub, b"ship it", sig)

# encrypt to someone's public key (they alone can open it)
blob = seal(their_x25519_pubkey, b"for your eyes only")

# store passwords safely
stored = hash_password("correct horse battery staple")
assert check_password("correct horse battery staple", stored)
```

## What's inside

Everything is verified against the relevant standard's official test vectors.

| area | what | standard |
|---|---|---|
| hashing / HMAC | SHA-2/3, BLAKE2, RIPEMD-160, `sha256d`, `hash160`, constant-time compare | FIPS / RFC 4231 |
| key derivation | HKDF, PBKDF2, scrypt | RFC 5869 |
| password hashing | scrypt → self-describing storable strings | — |
| AEAD | ChaCha20-Poly1305 | RFC 8439 |
| key agreement | X25519 Diffie-Hellman | RFC 7748 |
| signatures | Ed25519; ECDSA over secp256k1 (deterministic RFC 6979) | RFC 8032 / 6979 |
| public-key encryption | anonymous `seal`/`unseal` + authenticated `Box` | — |
| tokens | CSPRNG tokens, URL-safe base64 | — |
| JWT | HS256/384/512, EdDSA, ES256K — with **safe verify** | RFC 7519 |

## Install

```bash
pip install larzcrypt
```

Zero required dependencies. Optionally `pip install larzcrypt[fast]` to pull in
`coincurve` — larzcrypt will auto-use it for secp256k1 **only after** a self-test
proves it produces byte-identical signatures, so it speeds things up without ever
changing your output.

## Highlights

### Authenticated encryption that can't be silently tampered

```python
from larzcrypt import chacha20poly1305 as aead, token_bytes

key, nonce = token_bytes(32), token_bytes(12)   # nonce unique per message!
ct = aead.encrypt(key, nonce, b"secret", aad=b"header")
pt = aead.decrypt(key, nonce, ct, aad=b"header")   # raises if tampered
```

### Encrypt to a public key (sealed boxes)

```python
from larzcrypt import x25519, seal, unseal

priv, pub = x25519.generate_keypair()
blob = seal(pub, b"hello")          # anyone can seal to `pub`
unseal(priv, blob)                  # only `priv` can open it  -> b"hello"
```

Or an authenticated two-way channel where each side knows the other:

```python
from larzcrypt import x25519, Box

a_priv, a_pub = x25519.generate_keypair()
b_priv, b_pub = x25519.generate_keypair()
a, b = Box(a_priv, b_pub), Box(b_priv, a_pub)
b.decrypt(a.encrypt(b"ping"))       # -> b"ping", and forgery is impossible
```

### JWTs without the footguns

`decode()` takes the expected algorithm as a **required argument** and ignores
the token's own `alg` header — so the classic `alg:none` and RS256→HS256
confusion attacks simply can't happen.

```python
from larzcrypt import jwt, ed25519

priv, pub = ed25519.generate_keypair()
token = jwt.encode({"sub": "42", "exp": 1893456000}, priv, alg="EdDSA")
jwt.decode(token, pub, alg="EdDSA")           # {"sub": "42", ...}, or raises
```

### Password storage you don't have to think about

```python
from larzcrypt import hash_password, check_password

stored = hash_password("hunter2")             # 'scrypt$16384$8$1$<salt>$<hash>'
check_password("hunter2", stored)             # True — params are in the string
```

## A note on trust

Pure-Python crypto is **auditable and dependency-free**, and every primitive
here matches its standard's test vectors. It is not, and does not claim to be,
side-channel hardened to the level of a C library like libsodium. Use it freely
for signing, tokens, KDFs, app-level encryption, JWTs, and blockchain keys. For
deployments where an attacker can measure precise timing of your secret-key
operations at scale, pair it with a hardened backend (secp256k1 already
auto-uses `coincurve` when available).

Don't invent protocols on top of these primitives without knowing what you're
doing — reach for the high-level `seal`/`Box`/`jwt`/`hash_password` helpers,
which compose them correctly for you.

## Tests

```bash
python -m unittest discover -s tests -v      # 37 tests incl. RFC vectors, zero deps
```

## The Larz stack

Pure-Python, zero-dependency building blocks:

- **[larz](https://github.com/larz-scripter/larz)** — money-native web framework
- **[larzchain](https://github.com/larz-scripter/larzchain)** — from-scratch PoW blockchain
- **[larzmoney](https://github.com/larz-scripter/larzmoney)** — exact, penny-perfect money
- **larzcrypt** — this library

## License

MIT © larz-scripter
