std/crypto
Message authentication, keys made from passwords and other keys, random values from the system, and authenticated encryption, in the runtime's C, which takes the same time whatever the secrets are: AES computes its S-box rather than looking it up, and uses the processor's AES instructions where x86-64 has them. Checked against the RFCs' vectors and Python's cryptography.
import "std/crypto"
bytes key = new_key()
bytes sealed = seal(key, to_bytes("the plan"))
print(from_utf8_lossy(open(key, sealed)?))
bytes mac = hmac("sha256", key, to_bytes("a message"))
str token = random_token()| Function | Result |
|---|---|
hmac(algorithm, key, data), hmac_verify(algorithm, key, data, mac) |
HMAC with a hash of std/hash, and its check in constant time |
constant_time_equal(a, b) |
whether bytes are equal, in time that depends only on their lengths (a built-in) |
hkdf(algorithm, secret, salt, info, length) |
HKDF (RFC 5869) |
pbkdf2(algorithm, password, salt, iterations, length) |
PBKDF2 (RFC 8018) |
scrypt(password, salt, n, r, p, length) |
scrypt (RFC 7914); 32,768, 8, 1, and 32 unless given |
argon2id(password, salt, time, memory_kib, lanes, length, secret, data) |
Argon2id (RFC 9106), as passwords should be hashed; 3 passes over 64 MiB in 4 lanes unless given |
secure_random_bytes(n) |
random bytes from the system: getrandom, arc4random_buf, BCryptGenRandom, or getentropy; a runtime error, never weaker bytes, when there are none (a built-in) |
random_token(count) |
count random bytes (32) in unpadded base64url |
random_int(low, high) |
a random i64 from low to high, each as likely, without modulo bias |
random_choice(items), random_id(length) |
an item at random; an identifier of 21 letters, digits, _, and - |
new_key() |
32 random bytes |
seal(key, plaintext, data), open(key, sealed, data) |
XChaCha20-Poly1305 with a new random nonce, carried in front of what seal gives; open gives an ERROR of kind "authentication" when the message, its tag, or data changed, or the key is not its key |
encrypt(algorithm, key, nonce, plaintext, data), decrypt(...) |
one of CIPHERS: "xchacha20-poly1305" (a key of 32 bytes, a nonce of 24), "chacha20-poly1305" (32 and 12), or "aes-gcm" (16, 24, or 32, and 12); never use a nonce twice with one key |
sign_value(key, value), verify_value(key, signed) |
a value with its HMAC-SHA256, as a cookie or a link carries it, and the value back; an ERROR of kind "authentication" when either changed |
hash_password(password, time, memory_kib, lanes) |
Argon2id with a new random salt, in the PHC string format ($argon2id$v=19$m=65536,t=3,p=4$...), which says how to check it again |
verify_password(password, hashed) |
whether the password is the one hashed, in constant time; false for a hash it cannot read. It reads Argon2id hashes other programs wrote in the PHC format |
The random numbers of random and std/random are for games and samples,
not secrets.