Node.js Cheatsheet
Crypto (Hashing, HMAC, Encryption)
Use this Node.js reference while you build software engineering projects, review code for technical interview prep, or polish examples for a software engineer resume.
Hashing
import crypto from "node:crypto"; // One-shot (Node 21.7+) — fastest for a single input crypto.hash("sha256", "hello"); // hex digest string crypto.hash("sha256", buffer, "base64"); // Streaming interface const hash = crypto.createHash("sha256"); hash.update("chunk 1"); hash.update("chunk 2"); hash.digest("hex"); // "hex" | "base64" | "base64url" | Buffer if omitted // Hash a file without loading it into memory import fs from "node:fs"; import { pipeline } from "node:stream/promises"; const h = crypto.createHash("sha256"); await pipeline(fs.createReadStream("big.iso"), h); console.log(h.digest("hex"));
| Algorithm | Use |
|---|---|
sha256 / sha512 | General-purpose hashing, checksums |
sha1 / md5 | Legacy compatibility only — broken for security |
blake2b512 | Fast modern hash |
Never hash passwords with a plain digest — use
scrypt(below) or argon2.
HMAC (Keyed Hashing)
// Message authentication — signature verification, webhooks const sig = crypto.createHmac("sha256", secret) .update(payload) .digest("hex"); // Compare signatures in constant time (prevents timing attacks) const expected = Buffer.from(sig, "hex"); const received = Buffer.from(theirSig, "hex"); const valid = expected.length === received.length && crypto.timingSafeEqual(expected, received);
Random Values
crypto.randomUUID(); // "36b8f84d-df4e-4d49-b662-bcde71a8764f" (v4) crypto.randomBytes(32); // Buffer of 32 CSPRNG bytes crypto.randomBytes(32).toString("hex"); // 64-char token crypto.randomInt(1, 7); // int in [1, 7) — unbiased crypto.randomInt(100, (err, n) => { /* async form */ }); // Fill an existing typed array crypto.getRandomValues(new Uint32Array(4));
Password Hashing (scrypt)
import { scrypt, randomBytes, timingSafeEqual } from "node:crypto"; import { promisify } from "node:util"; const scryptAsync = promisify(scrypt); async function hashPassword(password) { const salt = randomBytes(16).toString("hex"); const derived = await scryptAsync(password, salt, 64); return `${salt}:${derived.toString("hex")}`; } async function verifyPassword(password, stored) { const [salt, hash] = stored.split(":"); const derived = await scryptAsync(password, salt, 64); return timingSafeEqual(Buffer.from(hash, "hex"), derived); }
Symmetric Encryption (AES-256-GCM)
// GCM = authenticated encryption; a unique IV per key per message is REQUIRED const key = crypto.randomBytes(32); // 256-bit key (store in a secret manager) function encrypt(plaintext) { const iv = crypto.randomBytes(12); const cipher = crypto.createCipheriv("aes-256-gcm", key, iv); const enc = Buffer.concat([cipher.update(plaintext, "utf8"), cipher.final()]); const tag = cipher.getAuthTag(); // 16-byte integrity tag return Buffer.concat([iv, tag, enc]).toString("base64"); } function decrypt(payload) { const buf = Buffer.from(payload, "base64"); const iv = buf.subarray(0, 12); const tag = buf.subarray(12, 28); const enc = buf.subarray(28); const decipher = crypto.createDecipheriv("aes-256-gcm", key, iv); decipher.setAuthTag(tag); // throws on tamper return Buffer.concat([decipher.update(enc), decipher.final()]).toString("utf8"); }
crypto.createCipher(alg, password)is removed (Node 22+) — always usecreateCipherivwith an explicit key and IV.
Sign and Verify (Asymmetric)
// Generate a key pair const { publicKey, privateKey } = crypto.generateKeyPairSync("ed25519"); // Ed25519 / RSA signing const signature = crypto.sign(null, Buffer.from(message), privateKey); crypto.verify(null, Buffer.from(message), publicKey, signature); // boolean // RSA needs a digest algorithm const { publicKey: pub, privateKey: priv } = crypto.generateKeyPairSync("rsa", { modulusLength: 2048, }); const sig = crypto.sign("sha256", data, priv); crypto.verify("sha256", data, pub, sig);
Web Crypto API
// The standards-based API — same code runs in browsers, workers, Deno, Bun const digest = await crypto.subtle.digest("SHA-256", new TextEncoder().encode("hi")); Buffer.from(digest).toString("hex"); const cryptoKey = await crypto.subtle.generateKey( { name: "AES-GCM", length: 256 }, true, // extractable ["encrypt", "decrypt"], ); const iv = crypto.getRandomValues(new Uint8Array(12)); const ct = await crypto.subtle.encrypt({ name: "AES-GCM", iv }, cryptoKey, data);
globalThis.crypto(Web Crypto) is available without any import in Node 19+; thenode:cryptomodule is the richer Node-specific API.