Menu
×
   ❮     
HTML CSS JAVASCRIPT SQL PYTHON JAVA PHP HOW TO W3.CSS C C++ C# BOOTSTRAP REACT MYSQL JQUERY EXCEL XML DJANGO NUMPY PANDAS NODEJS DSA TYPESCRIPT ANGULAR GIT POSTGRESQL MONGODB ASP AI R GO KOTLIN SASS VUE GEN AI SCIPY CYBERSECURITY DATA SCIENCE INTRO TO PROGRAMMING BASH RUST

Node.js Tutorial

Node HOME Node Intro Node Get Started Node JS Requirements Node.js vs Browser Node Cmd Line Node V8 Engine Node Architecture Node Event Loop

Asynchronous

Node Async Node Promises Node Async/Await Node Errors Handling

Module Basics

Node Modules Node ES Modules Node NPM Node package.json Node NPM Scripts Node Manage Dep Node Publish Packages

Core Modules

HTTP Module HTTPS Module File System (fs) Path Module OS Module URL Module Events Module Stream Module Buffer Module Crypto Module Timers Module DNS Module Assert Module Util Module Readline Module

JS & TS Features

Node ES6+ Node Process Node TypeScript Node Adv. TypeScript Node Lint & Formatting

Building Applications

Node Frameworks Express.js Middleware Concept REST API Design API Authentication Node.js with Frontend

Database Integration

MySQL Get Started MySQL Create Database MySQL Create Table MySQL Insert Into MySQL Select From MySQL Where MySQL Order By MySQL Delete MySQL Drop Table MySQL Update MySQL Limit MySQL Join
MongoDB Get Started MongoDB Create DB MongoDB Collection MongoDB Insert MongoDB Find MongoDB Query MongoDB Sort MongoDB Delete MongoDB Drop Collection MongoDB Update MongoDB Limit MongoDB Join

Advanced Communication

GraphQL Socket.IO WebSockets

Testing & Debugging

Node Adv. Debugging Node Testing Apps Node Test Frameworks Node Test Runner

Node.js Deployment

Node Env Variables Node Dev vs Prod Node CI/CD Node Security Node Deployment

Perfomance & Scaling

Node Logging Node Monitoring Node Performance Child Process Module Cluster Module Worker Threads

Node.js Advanced

Microservices Node WebAssembly HTTP2 Module Perf_hooks Module VM Module TLS/SSL Module Net Module Zlib Module Real-World Examples

Hardware & IoT

RasPi Get Started RasPi GPIO Introduction RasPi Blinking LED RasPi LED & Pushbutton RasPi Flowing LEDs RasPi WebSocket RasPi RGB LED WebSocket RasPi Components

Node.js Reference

Built-in Modules EventEmitter (events) Worker (cluster) Cipher (crypto) Decipher (crypto) DiffieHellman (crypto) ECDH (crypto) Hash (crypto) Hmac (crypto) Sign (crypto) Verify (crypto) Socket (dgram, net, tls) ReadStream (fs, stream) WriteStream (fs, stream) Server (http, https, net, tls) Agent (http, https) Request (http) Response (http) Message (http) Interface (readline)

Resources & Tools

Node.js Compiler Node.js Server Node.js Quiz Node.js Exercises Node.js Syllabus Node.js Study Plan Node.js Certificate

Node.js Crypto Module


What is the Crypto Module?

The Crypto module is a built-in Node.js module that provides cryptographic functionality including:

  • Hash functions (SHA-256, SHA-512, etc.)
  • HMAC (Hash-based Message Authentication Code)
  • Symmetric encryption (AES, DES, etc.)
  • Asymmetric encryption (RSA, ECDSA, etc.)
  • Digital signatures and verification
  • Secure random number generation

The Crypto module is essential for applications that need to handle sensitive information securely.

The Crypto module wraps the OpenSSL library, providing access to well-established and tested cryptographic algorithms.

This module is often used to handle sensitive data, such as:

  • User authentication and password storage
  • Secure data transmission
  • File encryption and decryption
  • Secure communication channels

Getting Started with Crypto

Here's a quick example of using the Crypto module to hash a string:

Basic Hashing Example

const crypto = require('crypto');

// Create a SHA-256 hash of a string
const hash = crypto.createHash('sha256')
  .update('Hello, Node.js!')
  .digest('hex');
console.log('SHA-256 Hash:', hash);
Try it Yourself »

Installing the Crypto Module

The Crypto module is included in Node.js by default.

You can use it by requiring it in your script:

const crypto = require('crypto');

Hash Functions

Hashing is a one-way transformation of data into a fixed-length string of characters.

Hash functions have several important properties:

  • Deterministic: Same input always produces the same output
  • Fixed Length: Output is always the same size regardless of input size
  • One-Way: Extremely difficult to reverse the process
  • Avalanche Effect: Small changes in input produce significant changes in output

Common use cases include:

  • Password storage
  • Data integrity verification
  • Digital signatures
  • Content addressing (e.g., Git, IPFS)

Creating a Hash

const crypto = require('crypto');

// Create a hash object
const hash = crypto.createHash('sha256');

// Update the hash with data
hash.update('Hello, World!');

// Get the digest in hexadecimal format
const digest = hash.digest('hex');
console.log(digest);
Try it Yourself »

In this example:

  • createHash() creates a hash object with the specified algorithm
  • update() updates the hash content with the given data
  • digest() calculates the digest and outputs it in the specified format


Common Hash Algorithms

const crypto = require('crypto');
const data = 'Hello, World!';

// MD5 (not recommended for security-critical applications)
const md5 = crypto.createHash('md5').update(data).digest('hex');
console.log('MD5:', md5);

// SHA-1 (not recommended for security-critical applications)
const sha1 = crypto.createHash('sha1').update(data).digest('hex');
console.log('SHA-1:', sha1);

// SHA-256
const sha256 = crypto.createHash('sha256').update(data).digest('hex');
console.log('SHA-256:', sha256);

// SHA-512
const sha512 = crypto.createHash('sha512').update(data).digest('hex');
console.log('SHA-512:', sha512);
Try it Yourself »

Warning: MD5 and SHA-1 are considered cryptographically weak and should not be used for security-critical applications.

Use SHA-256, SHA-384, or SHA-512 instead.


Password Security

When handling passwords, it's crucial to use specialized password hashing functions that are designed to be computationally expensive to prevent brute-force attacks.

Here's why simple hashes are insufficient:

Never store passwords in plain text or with simple hashes like MD5 or SHA-1.

These can be easily cracked using rainbow tables or brute-force attacks.

Key Concepts for Password Security

  1. Salting: Add a unique random value to each password before hashing
  2. Key Stretching: Make the hashing process intentionally slow to prevent brute-force attacks
  3. Work Factor: Control how computationally intensive the hashing process is

Here's how to properly hash passwords in Node.js:

What is a salt?
A salt is a random string that is unique to each user.

It's combined with the password before hashing to ensure that even if two users have the same password, their hashes will be different.

This prevents attackers from using precomputed tables (like rainbow tables) to crack multiple passwords at once.

const crypto = require('crypto');

// Function to hash a password
function hashPassword(password) {
  // Generate a random salt (16 bytes)
  const salt = crypto.randomBytes(16).toString('hex');

  // Use scrypt for password hashing (recommended)
  const hash = crypto.scryptSync(password, salt, 64).toString('hex');

  // Return both salt and hash for storage
  return { salt, hash };
}

// Function to verify a password
function verifyPassword(password, salt, hash) {
  const hashedPassword = crypto.scryptSync(password, salt, 64).toString('hex');
  return hashedPassword === hash;
}

// Example usage
const password = 'mySecurePassword';

// Hash the password for storage
const { salt, hash } = hashPassword(password);
console.log('Salt:', salt);
console.log('Hash:', hash);

// Verify a login attempt
const isValid = verifyPassword(password, salt, hash);
console.log('Password valid:', isValid); // true

const isInvalid = verifyPassword('wrongPassword', salt, hash);
console.log('Wrong password valid:', isInvalid); // false
Run example »

Note: For password hashing in a production environment, consider using a dedicated library like bcrypt or argon2 that is specifically designed for secure password handling.


HMAC (Hash-based Message Authentication Code)

HMAC is a specific type of message authentication code (MAC) involving a cryptographic hash function and a secret cryptographic key.

It provides both data integrity and authentication.

When to Use HMAC

  • API request verification
  • Secure cookies and sessions
  • Data integrity checks
  • Webhook verification

HMAC Security Properties

  • Message Integrity: Any change to the message will produce a different HMAC
  • Authenticity: Only parties with the secret key can generate valid HMACs
  • No Encryption: HMAC doesn't encrypt the message, only verifies its integrity
const crypto = require('crypto');

// Secret key
const secretKey = 'mySecretKey';

// Create an HMAC
const hmac = crypto.createHmac('sha256', secretKey);

// Update with data
hmac.update('Hello, World!');

// Get the digest
const hmacDigest = hmac.digest('hex');
console.log('HMAC:', hmacDigest);
Try it Yourself »

HMAC for Message Verification

const crypto = require('crypto');

// Function to create an HMAC for a message
function createSignature(message, key) {
  const hmac = crypto.createHmac('sha256', key);
  hmac.update(message);
  return hmac.digest('hex');
}

// Function to verify a message's signature
function verifySignature(message, signature, key) {
  const expectedSignature = createSignature(message, key);
  return crypto.timingSafeEqual(
    Buffer.from(signature, 'hex'),
    Buffer.from(expectedSignature, 'hex')
  );
}

// Example usage
const secretKey = 'verySecretKey';
const message = 'Important message to verify';

// Sender creates a signature
const signature = createSignature(message, secretKey);
console.log('Message:', message);
console.log('Signature:', signature);

// Receiver verifies the signature
try {
  const isValid = verifySignature(message, signature, secretKey);
  console.log('Signature valid:', isValid); // true

  // Try with a tampered message
  const isInvalid = verifySignature('Tampered message', signature, secretKey);
  console.log('Tampered message valid:', isInvalid); // false
} catch (error) {
  console.error('Verification error:', error.message);
}
Try it Yourself »

Note: Always use timingSafeEqual() for cryptographic comparisons to prevent timing attacks.


Symmetric Encryption

Symmetric encryption uses the same key for both encryption and decryption.

It's generally faster than asymmetric encryption and is ideal for:

  • Bulk data encryption
  • Database encryption
  • Filesystem encryption
  • Secure messaging (combined with key exchange)

Common Symmetric Algorithms

Algorithm Key Size Block Size Notes
AES-256 256 bits 128 bits Current standard, widely used
ChaCha20 256 bits 512 bits Faster in software, used in TLS 1.3
3DES 168 bits 64 bits Legacy, not recommended for new systems
Blowfish 32-448 bits 64 bits Legacy, use Twofish or AES instead

Note: Always use authenticated encryption modes like AES-GCM or AES-CCM when possible, as they provide both confidentiality and authenticity.


AES (Advanced Encryption Standard)

const crypto = require('crypto');

// Function to encrypt data
function encrypt(text, key) {
  // Generate a random initialization vector
  const iv = crypto.randomBytes(16);

  // Create cipher with AES-256-CBC
  const cipher = crypto.createCipheriv('aes-256-cbc', key, iv);

  // Encrypt the data
  let encrypted = cipher.update(text, 'utf8', 'hex');
  encrypted += cipher.final('hex');

  // Return both the encrypted data and the IV
  return {
    iv: iv.toString('hex'),
    encryptedData: encrypted
  };
}

// Function to decrypt data
function decrypt(encryptedData, iv, key) {
  // Create decipher
  const decipher = crypto.createDecipheriv(
    'aes-256-cbc',
    key,
    Buffer.from(iv, 'hex')
  );

  // Decrypt the data
  let decrypted = decipher.update(encryptedData, 'hex', 'utf8');
  decrypted += decipher.final('utf8');

  return decrypted;
}

// Example usage
// Note: In a real application, use a properly generated and securely stored key
const key = crypto.scryptSync('secretPassword', 'salt', 32); // 32 bytes = 256 bits
const message = 'This is a secret message';

// Encrypt
const { iv, encryptedData } = encrypt(message, key);
console.log('Original:', message);
console.log('Encrypted:', encryptedData);
console.log('IV:', iv);

// Decrypt
const decrypted = decrypt(encryptedData, iv, key);
console.log('Decrypted:', decrypted);
Run example »

Warning: Never reuse the same initialization vector (IV) with the same key.

Always generate a new random IV for each encryption operation.


Other Symmetric Algorithms

The Crypto module supports various symmetric encryption algorithms.

You can see the available ciphers with:

const crypto = require('crypto');

// List available cipher algorithms
console.log(crypto.getCiphers());
Try it Yourself »

Asymmetric Encryption

Asymmetric encryption (public-key cryptography) uses a pair of mathematically related keys:

  • Public Key: Can be shared publicly, used for encryption
  • Private Key: Must be kept secret, used for decryption

Common Use Cases

  • Secure key exchange (e.g., TLS/SSL handshake)
  • Digital signatures
  • Email encryption (PGP/GPG)
  • Blockchain and cryptocurrencies

Common Asymmetric Algorithms

Algorithm Key Size Security Level Notes
RSA 2048+ bits High Widely used, good compatibility
ECDSA 256-521 bits High Used in TLS 1.3, Bitcoin
Ed25519 256 bits Very High Modern, efficient, used in SSH

Performance Note: Asymmetric encryption is much slower than symmetric encryption.

For encrypting large amounts of data, use a hybrid approach:

  1. Generate a random symmetric key
  2. Encrypt your data with the symmetric key
  3. Encrypt the symmetric key with the recipient's public key
  4. Send both the encrypted data and encrypted key

RSA (Rivest-Shamir-Adleman)

const crypto = require('crypto');

// Generate RSA key pair
function generateKeyPair() {
  return crypto.generateKeyPairSync('rsa', {
    modulusLength: 2048, // Key size in bits
    publicKeyEncoding: {
      type: 'spki',
      format: 'pem'
    },
    privateKeyEncoding: {
      type: 'pkcs8',
      format: 'pem'
    }
  });
}

// Encrypt with public key
function encryptWithPublicKey(text, publicKey) {
  const buffer = Buffer.from(text, 'utf8');
  const encrypted = crypto.publicEncrypt(
    {
      key: publicKey,
      padding: crypto.constants.RSA_PKCS1_OAEP_PADDING
    },
    buffer
  );
  return encrypted.toString('base64');
}

// Decrypt with private key
function decryptWithPrivateKey(encryptedText, privateKey) {
  const buffer = Buffer.from(encryptedText, 'base64');
  const decrypted = crypto.privateDecrypt(
    {
      key: privateKey,
      padding: crypto.constants.RSA_PKCS1_OAEP_PADDING
    },
    buffer
  );
  return decrypted.toString('utf8');
}

// Generate keys
const { publicKey, privateKey } = generateKeyPair();
console.log('Public Key:', publicKey.substring(0, 50) + '...');
console.log('Private Key:', privateKey.substring(0, 50) + '...');

// Example usage
const message = 'This message is encrypted with RSA';
const encrypted = encryptWithPublicKey(message, publicKey);
console.log('Encrypted:', encrypted.substring(0, 50) + '...');

const decrypted = decryptWithPrivateKey(encrypted, privateKey);
console.log('Decrypted:', decrypted);
Run example »

Note: RSA is typically used for encrypting small amounts of data (like encryption keys) due to performance constraints.

For larger data, use a hybrid approach: encrypt the data with a symmetric algorithm (like AES) and encrypt the symmetric key with RSA.


Digital Signatures

Digital signatures provide a way to verify the authenticity and integrity of messages, software, or digital documents.

const crypto = require('crypto');

// Generate RSA key pair
const { publicKey, privateKey } = crypto.generateKeyPairSync('rsa', {
  modulusLength: 2048,
  publicKeyEncoding: {
    type: 'spki',
    format: 'pem'
  },
  privateKeyEncoding: {
    type: 'pkcs8',
    format: 'pem'
  }
});

// Function to sign a message
function signMessage(message, privateKey) {
  const signer = crypto.createSign('sha256');
  signer.update(message);
  return signer.sign(privateKey, 'base64');
}

// Function to verify a signature
function verifySignature(message, signature, publicKey) {
  const verifier = crypto.createVerify('sha256');
  verifier.update(message);
  return verifier.verify(publicKey, signature, 'base64');
}

// Example usage
const message = 'This message needs to be signed';
const signature = signMessage(message, privateKey);
console.log('Message:', message);
console.log('Signature:', signature.substring(0, 50) + '...');

// Verify the signature
const isValid = verifySignature(message, signature, publicKey);
console.log('Signature valid:', isValid); // true

// Verify with a modified message
const isInvalid = verifySignature('Modified message', signature, publicKey);
console.log('Modified message valid:', isInvalid); // false
Run example »

Random Data Generation

Generating secure random data is important for many cryptographic operations, such as creating keys, salts, and initialization vectors.

const crypto = require('crypto');

// Generate random bytes
const randomBytes = crypto.randomBytes(16);
console.log('Random bytes:', randomBytes.toString('hex'));

// Generate a random string (Base64)
const randomString = crypto.randomBytes(32).toString('base64');
console.log('Random string:', randomString);

// Generate a random number between 1 and 100
function secureRandomNumber(min, max) {
  // Ensure we have enough randomness
  const range = max - min + 1;
  const bytesNeeded = Math.ceil(Math.log2(range) / 8);
  const maxValue = 256 ** bytesNeeded;

  // Generate random bytes and convert to a number
  const randomBytes = crypto.randomBytes(bytesNeeded);
  const randomValue = randomBytes.reduce((acc, byte, i) => {
    return acc + byte * (256 ** i);
  }, 0);

  // Scale to our range and shift by min
  return min + Math.floor((randomValue * range) / maxValue);
}

// Example: Generate 5 random numbers
for (let i = 0; i < 5; i++) {
  console.log(`Random number ${i+1}:`, secureRandomNumber(1, 100));
}
Run example »

Security Best Practices

When using the Crypto module, keep these best practices in mind:

  • Use modern algorithms: Avoid MD5, SHA-1, and other outdated algorithms
  • Secure key management: Store keys securely, rotate them regularly, and never hardcode them
  • Use random IVs: Generate a new random IV for each encryption operation
  • Add authentication: Use authenticated encryption modes like GCM when possible
  • Constant-time comparisons: Always use crypto.timingSafeEqual() for comparing security-critical values
  • Key derivation: Use appropriate key derivation functions like scrypt, bcrypt, or PBKDF2 for password-based keys
  • Stay updated: Keep Node.js updated to get security fixes and support for newer algorithms
  • Follow standards: Adhere to established cryptographic standards and protocols

Warning: Cryptography is complex, and mistakes can lead to serious security vulnerabilities.

When implementing critical security features, consider consulting a security specialist or using well-established libraries designed for specific cryptographic tasks.


Summary

The Node.js Crypto module provides a wide range of cryptographic functionality:

  • Hash functions for data integrity and fingerprinting
  • HMAC for authentication and integrity checks
  • Symmetric encryption for securing data with shared keys
  • Asymmetric encryption for secure communication and digital signatures
  • Random data generation for cryptographic operations
  • Digital signatures for authenticity verification

By understanding and properly implementing these cryptographic concepts, you can build secure applications that protect sensitive data and communications.




×

Contact Sales

If you want to use W3Schools services as an educational institution, team or enterprise, send us an e-mail:
sales@w3schools.com

Report Error

If you want to report an error, or if you want to make a suggestion, send us an e-mail:
help@w3schools.com

W3Schools is optimized for learning and training. Examples might be simplified to improve reading and learning. Tutorials, references, and examples are constantly reviewed to avoid errors, but we cannot warrant full correctness of all content. While using W3Schools, you agree to have read and accepted our terms of use, cookie and privacy policy.

Copyright 1999-2025 by Refsnes Data. All Rights Reserved. W3Schools is Powered by W3.CSS.