crypto
stableCryptographic primitives including hashing (SHA-256/384/512/1/MD5), HMAC, AES-256-GCM encryption, PBKDF2 key derivation, base64/hex encoding, and secure random bytes.
use plugin crypto::{hash, hmac, hmac_verify, …} Functions (13)
- hash Hash data with a named algorithm
- hmac Compute HMAC signature for a message
- hmac_verify Verify an HMAC tag against a message
- random_bytes Generate cryptographically secure random bytes
- base64_encode Encode bytes or a string to base64
- base64_decode Decode a base64 string to bytes
- hex_encode Encode bytes or a string to lowercase hex
- hex_decode Decode a hex string to bytes
- aes_encrypt Encrypt data with AES-256-GCM
- aes_decrypt Decrypt AES-256-GCM ciphertext
- generate_key Generate a random AES key (128 or 256 bits)
- constant_time_equal Compare two values in constant time
- pbkdf2 Derive a key from password with PBKDF2-HMAC-SHA256
Overview
The crypto plugin provides production-grade cryptographic primitives backed by
the ring library: hashing, HMAC message authentication, AES-256-GCM
authenticated encryption, PBKDF2 password-based key derivation, and a
cryptographically secure random source. Binary data flows through the plugin as
bytes values, and most functions accept either a string or bytes for their
input, so you can hash text directly or pipe raw bytes from one call into the
next. Encoded output (hashes, HMAC tags, hex) is returned as a lowercase hex or
base64 string, while key material, nonces, and ciphertext are returned as
bytes. Reach for this plugin whenever you need to fingerprint data, sign and
verify messages, encrypt secrets at rest, or derive a key from a password.
Common patterns
Encrypt and decrypt a secret round-trip. Generate a key, encrypt to a nonce plus ciphertext, then decrypt with the same key and stored nonce.
use plugin crypto::{generate_key, aes_encrypt, aes_decrypt}
let key = generate_key(256)
let enc = aes_encrypt(key, "transfer $1000 to account 42")
let plain = aes_decrypt(key, enc["nonce"], enc["ciphertext"])
print("recovered len: {#plain}")
Sign a message and verify it safely. Produce an HMAC tag, then use
hmac_verify (constant-time) rather than comparing tags with ==.
use plugin crypto::{hmac, hmac_verify}
let key = "shared-secret"
let body = "POST /webhook payload"
let tag = hmac("sha256", key, body)
if hmac_verify("sha256", key, body, tag) {
print("signature ok")
}
Derive an encryption key from a password. Use a random salt with PBKDF2 to turn a low-entropy password into a 32-byte AES key.
use plugin crypto::{pbkdf2, random_bytes, aes_encrypt}
let salt = random_bytes(16)
let key = pbkdf2("correct horse battery staple", salt, 100000, 32)
let enc = aes_encrypt(key, "diary entry")
print("encrypted with derived key")
Hash data with a named algorithm
Computes a hash of data and returns the result as a lowercase hex string.
Supported algorithms: "sha256", "sha384", "sha512", "sha1", "md5".
data may be a string or bytes.
use plugin crypto::{hash}
let digest = hash("sha256", "hello world")
print(digest)
let md5sum = hash("md5", "test")
print(md5sum)
Because hash accepts bytes, you can fingerprint binary data such as random
keys or decoded payloads, not just text.
use plugin crypto::{hash, random_bytes}
let blob = random_bytes(64)
let fingerprint = hash("sha512", blob)
print("sha512: {fingerprint}")
Compute HMAC signature for a message
Computes an HMAC signature and returns it as a lowercase hex string.
Supported algorithms: "sha256", "sha384", "sha512".
Both key and message may be strings or bytes.
use plugin crypto::{hmac}
let tag = hmac("sha256", "secret-key", "the message to sign")
print(tag)
Verify an HMAC tag against a message
Verifies a hex-encoded HMAC tag against a message using constant-time comparison. Returns true if the tag is valid.
use plugin crypto::{hmac, hmac_verify}
let key = "my-secret"
let msg = "payload"
let tag = hmac("sha256", key, msg)
let valid = hmac_verify("sha256", key, msg, tag)
print("valid: {valid}")
Generate cryptographically secure random bytes
Generates length cryptographically secure random bytes using the OS random
source. Maximum 1 MB per call.
use plugin crypto::{random_bytes, hex_encode}
let raw = random_bytes(32)
print("random hex: {hex_encode(raw)}")
Use a short call to mint a unique token or salt, then base64-encode it for safe transport in URLs or headers.
use plugin crypto::{random_bytes, base64_encode}
let token = base64_encode(random_bytes(24))
print("session token: {token}")
Encode bytes or a string to base64
Encodes a string or bytes value to standard base64.
use plugin crypto::{base64_encode, base64_decode}
let encoded = base64_encode("hello world")
print(encoded)
Pair it with base64_decode for a full round-trip; the decoded value comes back
as bytes.
use plugin crypto::{base64_encode, base64_decode, hash}
let encoded = base64_encode("payload")
let raw = base64_decode(encoded)
print("decoded fingerprint: {hash("sha256", raw)}")
Decode a base64 string to bytes
Decodes a base64 string to raw bytes.
use plugin crypto::{base64_encode, base64_decode}
let encoded = base64_encode("hello")
let raw = base64_decode(encoded)
Encode bytes or a string to lowercase hex
Encodes a string or bytes value to lowercase hexadecimal.
use plugin crypto::{hex_encode}
let hex = hex_encode("ABC")
print(hex)
Decode a hex string to bytes
Decodes a lowercase hex string to raw bytes.
use plugin crypto::{hex_encode, hex_decode}
let hex = hex_encode("hello")
let raw = hex_decode(hex)
Encrypt data with AES-256-GCM
Encrypts plaintext with AES-256-GCM using a random 12-byte nonce. key
must be 32 bytes or a 64-character hex string. Returns a table with nonce
(bytes) and ciphertext (bytes). Store both — you need the nonce to decrypt.
use plugin crypto::{generate_key, aes_encrypt}
let key = generate_key(256)
let result = aes_encrypt(key, "secret message")
print("nonce len: {#result["nonce"]}")
print("ciphertext len: {#result["ciphertext"]}")
Decrypt AES-256-GCM ciphertext
Decrypts AES-256-GCM ciphertext. key must be 32 bytes or a hex string.
nonce must be the 12-byte bytes value returned by aes_encrypt.
use plugin crypto::{generate_key, aes_encrypt, aes_decrypt}
let key = generate_key(256)
let enc = aes_encrypt(key, "my secret data")
let plain = aes_decrypt(key, enc["nonce"], enc["ciphertext"])
Generate a random AES key (128 or 256 bits)
Generates a random AES key. bits must be 128 (16 bytes) or 256
(32 bytes, the default).
use plugin crypto::{generate_key, hex_encode}
let key128 = generate_key(128)
let key256 = generate_key(256)
print("128-bit key: {hex_encode(key128)}")
print("256-bit key: {hex_encode(key256)}")
Compare two values in constant time
Compares two strings or byte values in constant time, preventing timing side-channel attacks. Use this when comparing secrets such as HMAC tags or API tokens.
use plugin crypto::{constant_time_equal}
let expected = "secret-token-value"
let provided = "secret-token-value"
if constant_time_equal(expected, provided) {
print("tokens match")
}
A common use is checking an HMAC tag you computed against one supplied by a caller, without leaking timing information about where the first mismatch is.
use plugin crypto::{hmac, constant_time_equal}
let key = "webhook-secret"
let body = "event payload"
let expected = hmac("sha256", key, body)
let supplied = "deadbeef"
print("match: {constant_time_equal(expected, supplied)}")
Derive a key from password with PBKDF2-HMAC-SHA256
Derives a key from a password using PBKDF2-HMAC-SHA256. iterations defaults
to 100,000; key_len defaults to 32 bytes. Returns derived key bytes suitable
for use as an AES key.
use plugin crypto::{pbkdf2, random_bytes, hex_encode}
let salt = random_bytes(16)
let key = pbkdf2("user-password", salt, 100000, 32)
print("derived key: {hex_encode(key)}")
Since iterations and key_len are optional, you can call pbkdf2 with just a
password and salt to get the defaults (100,000 iterations, 32-byte key) and feed
the result straight into AES encryption.
use plugin crypto::{pbkdf2, random_bytes, aes_encrypt}
let salt = random_bytes(16)
let key = pbkdf2("login-passphrase", salt)
let enc = aes_encrypt(key, "protected note")
print("ciphertext len: {#enc["ciphertext"]}")