Crypto
Crypto module: general-purpose cryptographic primitives.
Exposes hashing, HMAC, password hashing/verification, random generation, and Base64 encoding as a public API. The underlying implementations are provided by the March runtime (Digestif SHA-256/512, PBKDF2, CSPRNG).
Password hashing uses PBKDF2-SHA256 with a 16-byte random salt and
- The stored format is:
"pbkdf2:sha256:100000:<salt_hex>:<hash_hex>" This is intentionally simple to verify without external libraries.
All hex output is lowercase.
Functions
Compute the SHA-256 hash of data, returning a lowercase hex string.
Crypto.sha256("hello") -- "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824"
The argument may be a String or Bytes value.
Compute the SHA-512 hash of data, returning a lowercase hex string.
The argument may be a String or Bytes value.
Compute an HMAC using the given algorithm.
Crypto.hmac(:sha256, "secret", "message") -- lowercase hex string of the HMAC-SHA256 result
Supported algorithms: :sha256. Returns the HMAC as a lowercase hex string. The key and data may each be a String or Bytes value.
Hash a plaintext password using PBKDF2-SHA256 with a random salt.
let h = Crypto.hash_password("my-secret") -- "pbkdf2:sha256:100000:<salt_hex>:<hash_hex>"
The result is safe to store in a database. Use verify_password/2 to check a candidate password against the stored hash.
Uses 100 000 PBKDF2 iterations with a 16-byte random salt and 32-byte output.
Verify a plaintext password against a stored hash produced by hash_password/1.
let h = Crypto.hash_password("correct-horse-battery-staple") Crypto.verify_password("correct-horse-battery-staple", h) -- true Crypto.verify_password("wrong-password", h) -- false
Returns false if the hash format is unrecognised.
Generate n cryptographically random bytes.
Crypto.random_bytes(16) -- Bytes value with 16 random bytes
Generate n random bytes and return them as a lowercase hex string (2n chars).
Crypto.random_hex(16) -- 32-character lowercase hex string
Compare two strings in constant time with respect to their length.
Prevents timing attacks when comparing secrets such as tokens or HMAC digests. Returns true if the strings are equal, false otherwise.
Note: the interpreter does not guarantee constant time at the machine level; this function nonetheless avoids early exits that would reveal prefix length.
Crypto.secure_compare("abc", "abc") -- true Crypto.secure_compare("abc", "abd") -- false
Base64-encode a Bytes value (standard alphabet with padding).
let b = Crypto.random_bytes(12) Crypto.base64_encode(b) -- 16-character Base64 string
Decode a standard Base64 string to Bytes.
Crypto.base64_decode("SGVsbG8=") -- Ok(Bytes for "Hello") Crypto.base64_decode("!!") -- Err("base64_decode: ...")
Base64-encode using the URL-safe alphabet (- and _ instead of + and /), with no padding characters.
Crypto.base64_url_encode(Crypto.random_bytes(16)) -- URL-safe 22-character string
Decode a URL-safe Base64 string (- and _, no padding) to Bytes.
Crypto.base64_url_decode("SGVsbG8") -- Ok(Bytes) Crypto.base64_url_decode("!!") -- Err(...)