Node.js: Code Outside the Browser / Built in Modules

Crypto Module

📦 The crypto Module

crypto is a built-in Node.js module for cryptographic operations — hashing, generating random values, and encrypting/decrypting data. It's what powers things like password hashing, secure tokens, and signed data under the hood.

const crypto = require('crypto');

🔒 Hashing

A hash turns data into a fixed-length string. The same input always produces the same hash, but you can't reverse a hash back into the original data.

const hash = crypto.createHash('sha256').update('hello world').digest('hex');
console.log(hash);
// 'b94d27b9934d3e08a52e52d7da7dacefbd2af3a4c...'
  • createHash('sha256') picks the hashing algorithm — SHA-256 is a common, secure choice.

  • .update(data) feeds in the data you want to hash.

  • .digest('hex') outputs the result as a readable hex string (you could also use 'base64').

  • Same input → same hash, every time. Useful for checking if a file changed, or comparing data without storing the original.

⚠️ Don't use plain hashing for passwords — it's fast, which makes it easy to brute-force. Use a slow, purpose-built algorithm instead (see below).


🔑 HMAC (Hashing with a Secret Key)

An HMAC is a hash that also requires a secret key — so only someone with the key can generate or verify it.

const hmac = crypto.createHmac('sha256', 'my-secret-key').update('hello world').digest('hex');
console.log(hmac);
  • Same idea as createHash, but createHmac takes a secret key as the second argument.

  • Used to verify that a message came from someone who has the key, and wasn't tampered with — common in API request signing.


🎲 Random Values

const randomBytes = crypto.randomBytes(16).toString('hex');
console.log(randomBytes);
// e.g. 'a3f5c9d1e8b74f2a0c6d5e9f1b3a7c8d'
  • randomBytes(16) generates 16 cryptographically secure random bytes — safe to use for tokens, session IDs, or password reset links, unlike Math.random().

  • .toString('hex') converts the raw bytes into a readable string.

🆔 Generating a UUID

const id = crypto.randomUUID();
console.log(id);
// e.g. '3b241101-e2bb-4255-8caf-4136c566a962'
  • randomUUID() generates a unique ID in standard UUID format — handy for database record IDs or tracking requests.


🔐 Encrypting & Decrypting Data

Unlike hashing, encryption is reversible — anyone with the right key can decrypt the data back to its original form.

  • key and iv (initialization vector) are both required to encrypt and decrypt — losing either means the data can't be recovered.

  • The iv doesn't need to be secret, but it must be random and unique for every encryption.

  • cipher.update() processes the data, and cipher.final() wraps up the encryption — both parts are needed to get the complete result.

  • In a real app, key and iv are generated once and stored securely (e.g. in environment variables), not regenerated on every run — otherwise you can't decrypt data encrypted earlier.


💡 Why Use crypto?

  • 🔒 Hashing — checksums, data integrity checks, non-reversible fingerprints of data

  • 🔑 HMAC — verifying a message's sender and that it wasn't altered

  • 🎲 Random values — secure tokens, session IDs, UUIDs

  • 🔐 Encryption — protecting sensitive data (files, messages) that needs to be readable again later

⚠️ For passwords specifically, use a dedicated library like bcrypt instead of crypto directly — it's built to be slow on purpose, which makes brute-forcing much harder.