Crypto & Passwords
ID and random value generation, constant-time comparison, and PBKDF2 password hashing, all on the Web Crypto API.
@codexa/core/crypto covers the cryptographic primitives a typical backend needs, IDs, random values, and password hashing, without adding a native dependency, everything runs on the standard Web Crypto API.
IDs and random values
import { generateId, randomBytes, generateOtp } from '@codexa/core/crypto';
generateId(); // a UUID v4 string
randomBytes(16); // 16 random bytes as a 32-character hex string
generateOtp(6); // a 6-digit numeric code, e.g. "042817"randomBytesRaw(length) returns the same random bytes as a Uint8Array instead of a hex string, useful when you need the raw bytes for something like a salt.
Password hashing
import { hashPassword, verifyPassword } from '@codexa/core/crypto';
const stored = await hashPassword('user-supplied-password');
// "pbkdf2$310000$<saltHex>$<hashHex>"
const ok = await verifyPassword('user-supplied-password', stored);hashPassword uses PBKDF2-SHA256 with 310,000 iterations by default, matching current OWASP guidance, and returns a single self-describing string with the iteration count and salt embedded. verifyPassword reads the iteration count back out of that string, so hashes created with a different iteration count in the past still verify correctly even after you raise the default later.
verifyPassword compares hashes with a constant-time comparison, not ===, specifically to avoid a timing attack that could otherwise leak how many leading bytes of a guessed hash were correct.
Constant-time comparison
import { timingSafeEqual } from '@codexa/core/crypto';
timingSafeEqual(providedToken, expectedToken);Use this whenever comparing a secret, a token, an API key, a webhook signature, against a known value. A plain === short-circuits on the first mismatched character, which measurably leaks information through response timing. timingSafeEqual always takes the same time regardless of where the strings first differ.
Encoding helpers
import { base32Encode, base32Decode, toBase64Url, fromBase64Url } from '@codexa/core/crypto';
base32Encode(bytes); // RFC 4648 Base32, no padding, the format TOTP secrets use
toBase64Url(bytes); // base64url, no padding, safe to put directly in a URLIntegrity digests
import { blake2bDigest } from '@codexa/core/crypto';
blake2bDigest(`${walletId}:${currency}:${balance}`); // a hex digest, 32 bytes by defaultA fast, non-cryptographic-strength-dependent digest for detecting whether a piece of data changed, not a password hash. Pass a second argument to change the output length in bytes.