kryptos/crypto
The crypto module provides cryptographic primitives.
- One-shot hashing via
hash()and HMAC viahmac() - Key derivation: HKDF (RFC 5869), PBKDF2 (RFC 8018), Concat KDF (NIST SP 800-56A)
- Random bytes via
random_bytes()and UUID v4 viarandom_uuid() - Constant-time comparison via
constant_time_equal()
Example
import kryptos/crypto
// Generate 32 random bytes (suitable for a 256-bit key)
let key = crypto.random_bytes(32)
Values
pub fn concat_kdf(
algorithm: hash.HashAlgorithm,
secret secret: BitArray,
info info: BitArray,
length length: Int,
) -> Result(BitArray, Nil)
Derives key material using Concat KDF (NIST SP 800-56A). Also called the single-step or one-step key derivation function.
Concat KDF is a single-step key derivation function that uses a hash function to derive key material from a shared secret and context-specific information.
Parameters
algorithm: The hash algorithm to use (SHA-1, SHA-2, or SHA-3 family)secret: The shared secret from key agreement (e.g., ECDH)info: Context and application specific informationlength: Desired output length in bytes (max: 255 * hash_length)
Returns
Ok(BitArray) containing the derived key material of the requested
length, or Error(Nil) if the algorithm is not supported or length
is invalid.
Example
import kryptos/crypto
import kryptos/hash
let secret = crypto.random_bytes(32)
let assert Ok(derived) =
crypto.concat_kdf(hash.Sha256, secret:, info: <<"context":utf8>>, length: 32)
pub const constant_time_equal: fn(BitArray, BitArray) -> Bool
Compares two BitArray in constant time.
Use this function when comparing secrets like MACs, password hashes, API tokens, or any other security-sensitive data.
Parameters
a: The first bit array to compareb: The second bit array to compare
Returns
True if a and b are equal, False otherwise. The comparison
takes the same amount of time regardless of where the arrays differ,
preventing timing attacks.
Example
let expected_mac = compute_mac(message, key)
let received_mac = get_mac_from_request()
// Safe: constant-time comparison prevents timing attacks
case crypto.constant_time_equal(expected_mac, received_mac) {
True -> accept_message()
False -> reject_message()
}
pub fn hash(
algorithm: hash.HashAlgorithm,
data: BitArray,
) -> Result(BitArray, Nil)
Computes the hash digest of input data in one call.
Parameters
algorithm: The hash algorithm to usedata: The data to hash
Returns
Ok(BitArray) containing the hash digest, or Error(Nil) if the hash
algorithm is not supported by the runtime.
Example
import kryptos/crypto
import kryptos/hash
let assert Ok(digest) = crypto.hash(hash.Sha256, <<"hello":utf8>>)
pub fn hkdf(
algorithm: hash.HashAlgorithm,
input ikm: BitArray,
salt salt: option.Option(BitArray),
info info: BitArray,
length length: Int,
) -> Result(BitArray, Nil)
Derives key material using HKDF (RFC 5869).
HKDF combines an extract-then-expand approach to derive cryptographically strong key material from input key material.
Parameters
algorithm: The hash algorithm to use (must be HMAC-compatible)input: Input key material (IKM) - the source keying materialsalt: Optional salt value (None uses hash-length zeros per RFC 5869)info: Context and application specific informationlength: Desired output length in bytes (max: 255 * hash_length)
Returns
Ok(BitArray) containing the derived key material of the requested
length, or Error(Nil) if the algorithm is not supported or length
exceeds the maximum.
Example
import gleam/option
import kryptos/crypto
import kryptos/hash
let ikm = crypto.random_bytes(32)
let salt = option.Some(crypto.random_bytes(16))
let assert Ok(derived) =
crypto.hkdf(hash.Sha256, input: ikm, salt:, info: <<"app":utf8>>, length: 32)
pub fn hmac(
algorithm: hash.HashAlgorithm,
key key: BitArray,
data data: BitArray,
) -> Result(BitArray, Nil)
Computes the HMAC of input data in one call.
Parameters
algorithm: The hash algorithm to use for the HMACkey: The secret key for authenticationdata: The data to authenticate
Returns
Ok(BitArray) containing the message authentication code, or
Error(Nil) if the hash algorithm is not supported.
Example
import kryptos/crypto
import kryptos/hash
let assert Ok(mac) = crypto.hmac(hash.Sha256, key: <<"secret":utf8>>, data: <<"hello":utf8>>)
pub fn pbkdf2(
algorithm: hash.HashAlgorithm,
password password: BitArray,
salt salt: BitArray,
iterations iterations: Int,
length length: Int,
) -> Result(BitArray, Nil)
Derives key material from a password using PBKDF2 (RFC 8018).
PBKDF2 applies a pseudorandom function (HMAC) to derive keys from passwords. It is designed to be computationally expensive to resist brute-force attacks.
Note: For password hashing in production applications, consider using Argus which provides Argon2 an algorithm specifically designed for password storage. PBKDF2 is primarily useful for interoperability with systems that require it.
Parameters
algorithm: The hash algorithm to use for HMAC (must be HMAC-compatible). SHA-256 or stronger is recommended; MD5 and SHA-1 are weak for password hashing.password: The password to derive the key fromsalt: A random salt value (should be unique per password)iterations: Number of iterations (higher = slower but more secure)length: Desired output length in bytes
Returns
Ok(BitArray) containing the derived key material of the requested
length, or Error(Nil) if the algorithm is not supported,
iterations <= 0, or length <= 0.
Example
import kryptos/crypto
import kryptos/hash
let salt = crypto.random_bytes(16)
let assert Ok(derived) =
crypto.pbkdf2(
hash.Sha256,
password: <<"hunter2":utf8>>,
salt:,
iterations: 100_000,
length: 32,
)
pub fn random_bytes(length: Int) -> BitArray
Generates cryptographically secure random bytes using the platform’s cryptographically secure random number generator.
Parameters
length: The number of random bytes to generate. If negative, returns an emptyBitArray.
Returns
A BitArray containing the generated random bytes.
pub fn random_uuid() -> String
Generates a cryptographically secure random UUID v4.
Returns
A String containing a UUID v4.