kryptos
A cryptography library for Gleam targeting both Erlang and JavaScript runtimes.
Why kryptos?
- Dual-runtime support — Works on both Erlang and JavaScript (Node.js), wrapping each platform’s native crypto APIs for consistent behavior.
- No custom cryptography — All cryptographic operations delegate to the
runtime’s battle-tested implementations (Erlang’s
cryptomodule, Node.jscryptomodule). This library is a wrapper, not a reimplementation. - Misuse-resistant API — Inspired by Go’s crypto library, the API guides you toward safe defaults and makes dangerous operations explicit.
- Tested against Wycheproof — Validated against Google’s Wycheproof test vectors to catch edge-case vulnerabilities.
Installation
gleam add kryptos
Features
| Module | Algorithms |
|---|---|
| hash | SHA-1, SHA-2, SHA-3, BLAKE2 |
| hmac | All hash algorithms |
| aead | AES-GCM, AES-CCM, ChaCha20-Poly1305 |
| block | AES-128, AES-192, AES-256 |
| ecdsa | P-256, P-384, P-521 |
| eddsa | Ed25519, Ed448 |
| ecdh | P-256, P-384, P-521 |
| xdh | X25519, X448 |
| rsa | OAEP, PKCS#1 v1.5, PSS, PKCS#1 v1.5 signatures |
| crypto | HKDF, PBKDF2, random bytes |
Getting Started
Encrypt and decrypt data using AES-GCM:
import kryptos/aead
import kryptos/block
import kryptos/crypto
pub fn main() {
// Generate a random 256-bit key
let assert Ok(cipher) = block.aes_256(crypto.random_bytes(32))
let ctx = aead.gcm(cipher)
// Generate a random nonce (never reuse with the same key!)
let nonce = crypto.random_bytes(aead.nonce_size(ctx))
// Encrypt
let plaintext = <<"hello, world!":utf8>>
let assert Ok(#(ciphertext, tag)) = aead.seal(ctx, nonce:, plaintext:)
// Decrypt
let assert Ok(decrypted) = aead.open(ctx, nonce:, ciphertext:, tag:)
// decrypted == plaintext
}
Security
For guidance on choosing cryptographic primitives, see Cryptographic Right Answers.