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"));
AlgorithmUse
sha256 / sha512General-purpose hashing, checksums
sha1 / md5Legacy compatibility only — broken for security
blake2b512Fast 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 use createCipheriv with 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+; the node:crypto module is the richer Node-specific API.