Key-derivation functions.

These run natively because interpreting thousands of HMAC rounds per call would be prohibitively slow. For plain hashes see ::hot::hash, for HMAC see ::hot::hmac.

Functions

pbkdf2-hmac-sha256

fn (password: Str | Bytes, salt: Str | Bytes, iterations: Int): Bytes
fn (password: Str | Bytes, salt: Str | Bytes, iterations: Int, length: Int): Bytes

PBKDF2 key derivation using HMAC-SHA256 (RFC 2898). This is the Hi() function from SCRAM-SHA-256 (RFC 5802/7677), used by Postgres and other SASL-based protocols to derive the salted password.

Returns the derived key as Bytes. The default length is 32 bytes (the SHA-256 output size); pass length to derive more or fewer.

Example

::crypto ::hot::crypto
::hex ::hot::hex

key ::crypto/pbkdf2-hmac-sha256("password", "salt", 1)
::hex/encode(key)
// "120fb6cffcf8b32c43e7225256c4f837a86548c92ccc35480805987cb70be17b"

// SCRAM-SHA-256 SaltedPassword (RFC 7677 test vector)
::b64 ::hot::base64
salt ::b64/decode("W22ZaJ0SNY7soEsUEjb6gQ==")
salted ::crypto/pbkdf2-hmac-sha256("pencil", salt, 4096)

rsa-sha256-sign

fn (private-key-pem: Str, message: Str | Bytes): Bytes

Sign a message with RSASSA-PKCS1-v1_5 / SHA-256 (the JWT RS256 algorithm). Returns the raw signature Bytes — base64url-encode them for a JWT. Accepts PKCS#8 (BEGIN PRIVATE KEY, e.g. Google service accounts) and PKCS#1 (BEGIN RSA PRIVATE KEY, e.g. GitHub Apps) PEM private keys.

Example

::crypto ::hot::crypto
::b64 ::hot::base64

signature ::crypto/rsa-sha256-sign(private-key-pem, `${header}.${payload}`)
jwt `${header}.${payload}.${::b64/encode-url(signature)}`

rsa-sha256-verify

fn (n: Bytes, e: Bytes, message: Str | Bytes, signature: Bytes): Bool

Verify an RSASSA-PKCS1-v1_5 / SHA-256 (RS256) signature against RSA public key components. n (modulus) and e (exponent) are big-endian Bytes — exactly the JWKS n/e fields after base64url decoding. Returns false for a bad signature.

Example

::crypto ::hot::crypto
::b64 ::hot::base64

n ::b64/decode-url(jwk.n)
e ::b64/decode-url(jwk.e)
valid ::crypto/rsa-sha256-verify(n, e, `${header}.${payload}`, signature)