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.
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
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
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)
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:
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.
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
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
python -m unittest discover -s tests -v # 37 tests incl. RFC vectors, zero deps
The Larz stack
Pure-Python, zero-dependency building blocks:
- larz — money-native web framework
- larzchain — from-scratch PoW blockchain
- larzmoney — exact, penny-perfect money
- larzcrypt — this library
License
MIT © larz-scripter
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file larzcrypt-0.1.1.tar.gz.
File metadata
- Download URL: larzcrypt-0.1.1.tar.gz
- Upload date:
- Size: 23.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c456499a06018b957f40e58320e9fc07020804282bd5acc36f4f9048c734f499
|
|
| MD5 |
0b9b1ade1aef683bceee7db3f148ef79
|
|
| BLAKE2b-256 |
7c48de6476f617dd4d0d2579193d60c7226b5f12a485ad8f6ad75ed6d862fa67
|
File details
Details for the file larzcrypt-0.1.1-py3-none-any.whl.
File metadata
- Download URL: larzcrypt-0.1.1-py3-none-any.whl
- Upload date:
- Size: 22.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9aa2bf451f2112e72f40ef6c0d5a4ea2d4130ab79f371695e3823eb9a29f83c2
|
|
| MD5 |
35e0a23e696dc5f093324fb4346cc1c9
|
|
| BLAKE2b-256 |
bb77d5d7e77c249cc0cbfcadabdaa51a27ff2e7ceab80bdb597e6b05880bd398
|