|
The Crypto module provides cryptographic functionality including hashing, encryption, and random number generation.
|
|
|
Import crypto functions
|
import {
randomBytes, randomUUID, randomInt,
createHash, createHmac,
createCipheriv, createDecipheriv,
scrypt, scryptSync,
generateKeyPairSync,
createSign, createVerify,
timingSafeEqual
} from 'node:crypto';
|
|
Random Data Generation
Generate cryptographically secure random data.
Random bytes
Random UUID (v4)
Random integer in range
|
const bytes = randomBytes(16);
console.log('Random bytes:', bytes.toString('hex'));
const uuid = randomUUID();
console.log('UUID:', uuid);
const num = randomInt(1, 100);
console.log('Random int:', num);
|
|
Hashing
Create one-way hashes of data.
SHA-256 (most common)
MD5 (not secure, but useful for checksums)
Update multiple times
Different output formats
|
const sha256 = createHash('sha256')
.update('Hello World')
.digest('hex');
console.log('SHA-256:', sha256);
const md5 = createHash('md5')
.update('Hello World')
.digest('hex');
console.log('MD5:', md5);
const multiHash = createHash('sha256');
multiHash.update('Hello ');
multiHash.update('World');
console.log('Multi-update:', multiHash.digest('hex'));
const hash = createHash('sha256').update('test');
console.log('Hex:', hash.copy().digest('hex'));
console.log('Base64:', hash.copy().digest('base64'));
console.log('Buffer:', hash.digest());
|
|
Hashing Files
Hash file contents efficiently using streams.
hashFile('./example.txt').then(console.log);
|
import { createReadStream } from 'node:fs';
async function hashFile(filepath) {
const hash = createHash('sha256');
const stream = createReadStream(filepath);
for await (const chunk of stream) {
hash.update(chunk);
}
return hash.digest('hex');
}
|
|
HMAC (Hash-based Message Authentication Code)
Create authenticated hashes using a secret key.
Verify HMAC
|
const secret = 'my-secret-key';
const hmac = createHmac('sha256', secret)
.update('Hello World')
.digest('hex');
console.log('HMAC:', hmac);
function verifyHmac(message, receivedHmac, secret) {
const expected = createHmac('sha256', secret)
.update(message)
.digest();
const received = Buffer.from(receivedHmac, 'hex');
return timingSafeEqual(expected, received);
}
|
|
Password Hashing with scrypt
Securely hash passwords (slow by design).
Usage
|
async function hashPassword(password) {
const salt = randomBytes(16);
return new Promise((resolve, reject) => {
scrypt(password, salt, 64, (err, derivedKey) => {
if (err) reject(err);
resolve(salt.toString('hex') + ':' + derivedKey.toString('hex'));
});
});
}
async function verifyPassword(password, stored) {
const [saltHex, hashHex] = stored.split(':');
const salt = Buffer.from(saltHex, 'hex');
const storedHash = Buffer.from(hashHex, 'hex');
return new Promise((resolve, reject) => {
scrypt(password, salt, 64, (err, derivedKey) => {
if (err) reject(err);
resolve(timingSafeEqual(storedHash, derivedKey));
});
});
}
hashPassword('myPassword123').then(async (hashed) => {
console.log('Hashed password:', hashed.substring(0, 50) + '...');
const valid = await verifyPassword('myPassword123', hashed);
console.log('Password valid:', valid);
});
|
|
Symmetric Encryption (AES)
Encrypt and decrypt data with a shared key.
Key must be 32 bytes for AES-256
|
function encrypt(text, key) {
const iv = randomBytes(16);
const cipher = createCipheriv('aes-256-cbc', key, iv);
let encrypted = cipher.update(text, 'utf8', 'hex');
encrypted += cipher.final('hex');
return iv.toString('hex') + ':' + encrypted;
}
function decrypt(encryptedData, key) {
const [ivHex, encrypted] = encryptedData.split(':');
const iv = Buffer.from(ivHex, 'hex');
const decipher = createDecipheriv('aes-256-cbc', key, iv);
let decrypted = decipher.update(encrypted, 'hex', 'utf8');
decrypted += decipher.final('utf8');
return decrypted;
}
const encryptionKey = randomBytes(32);
const encrypted = encrypt('Secret message', encryptionKey);
const decrypted = decrypt(encrypted, encryptionKey);
console.log('Encrypted:', encrypted);
console.log('Decrypted:', decrypted);
|
|
Asymmetric Encryption (RSA)
Generate key pairs and sign/verify data.
Generate RSA key pair
|
const { publicKey, privateKey } = generateKeyPairSync('rsa', {
modulusLength: 2048,
publicKeyEncoding: { type: 'spki', format: 'pem' },
privateKeyEncoding: { type: 'pkcs8', format: 'pem' }
});
console.log('Public key generated:', publicKey.substring(0, 50) + '...');
|
|
Digital Signatures
Sign data with private key, verify with public key.
|
function signData(data, privateKey) {
const sign = createSign('SHA256');
sign.update(data);
return sign.sign(privateKey, 'hex');
}
function verifySignature(data, signature, publicKey) {
const verify = createVerify('SHA256');
verify.update(data);
return verify.verify(publicKey, signature, 'hex');
}
const message = 'Important message';
const signature = signData(message, privateKey);
const isValid = verifySignature(message, signature, publicKey);
console.log('Signature:', signature.substring(0, 50) + '...');
console.log('Signature valid:', isValid);
|
|
Timing-Safe Comparison
Prevent timing attacks when comparing secrets.
|
function safeCompare(a, b) {
const bufA = Buffer.from(a);
const bufB = Buffer.from(b);
if (bufA.length !== bufB.length) {
return false;
}
return timingSafeEqual(bufA, bufB);
}
|
|
Practical Example: Token Generation
Generate secure tokens for auth, CSRF, etc.
|
function generateToken(length = 32) {
return randomBytes(length).toString('base64url');
}
function generateApiKey() {
const prefix = 'sk_live_';
const key = randomBytes(24).toString('base64url');
return prefix + key;
}
console.log('Token:', generateToken());
console.log('API Key:', generateApiKey());
|
|
Practical Example: Secure Session ID
Generate collision-resistant session identifiers.
|
function generateSessionId() {
const timestamp = Date.now().toString(36);
const random = randomBytes(16).toString('base64url');
return `${timestamp}_${random}`;
}
console.log('Session ID:', generateSessionId());
|