Password-Based Key Derivation Function 2 (PBKDF2) for securely deriving cryptographic keys from passwords with salt and iteration count protection against brute-force attacks.
Derives a key from a password using PBKDF2 asynchronously.
/**
* Derive key from password using PBKDF2 (asynchronous)
* @param {string|Buffer} password - Password string or Buffer
* @param {string|Buffer} salt - Salt string or Buffer (should be random and unique per password)
* @param {number} iterations - Number of iterations (higher = more secure but slower)
* @param {number} keylen - Desired key length in bytes
* @param {string} digest - Hash algorithm to use (e.g., 'sha256', 'sha512')
* @param {function} callback - Callback function with (err, derivedKey)
* @param {Error|null} callback.err - Error object or null
* @param {Buffer} callback.derivedKey - Derived key as Buffer
*/
function pbkdf2(password, salt, iterations, keylen, digest, callback) { }Usage Examples:
const crypto = require('crypto-browserify');
// Basic key derivation
const password = 'user-password';
const salt = crypto.randomBytes(16); // Generate random salt
const iterations = 100000; // Industry standard minimum
const keyLength = 32; // 256-bit key
crypto.pbkdf2(password, salt, iterations, keyLength, 'sha256', (err, derivedKey) => {
if (err) throw err;
console.log('Derived key:', derivedKey.toString('hex'));
console.log('Salt used:', salt.toString('hex'));
});
// Key derivation for encryption
const userPassword = 'MySecurePassword123!';
const randomSalt = crypto.randomBytes(16);
crypto.pbkdf2(userPassword, randomSalt, 100000, 32, 'sha512', (err, encryptionKey) => {
if (err) {
console.error('Key derivation failed:', err);
return;
}
// Use the derived key for AES encryption
const cipher = crypto.createCipher('aes-256-cbc', encryptionKey);
// ... encryption logic
});
// Storing password hashes
function hashPassword(password, callback) {
const salt = crypto.randomBytes(16);
crypto.pbkdf2(password, salt, 100000, 64, 'sha512', (err, hash) => {
if (err) return callback(err);
// Store both salt and hash
const result = {
salt: salt.toString('hex'),
hash: hash.toString('hex'),
iterations: 100000
};
callback(null, result);
});
}Derives a key from a password using PBKDF2 synchronously.
/**
* Derive key from password using PBKDF2 (synchronous)
* @param {string|Buffer} password - Password string or Buffer
* @param {string|Buffer} salt - Salt string or Buffer (should be random and unique per password)
* @param {number} iterations - Number of iterations (higher = more secure but slower)
* @param {number} keylen - Desired key length in bytes
* @param {string} digest - Hash algorithm to use (e.g., 'sha256', 'sha512')
* @returns {Buffer} Derived key as Buffer
*/
function pbkdf2Sync(password, salt, iterations, keylen, digest) { }Usage Examples:
const crypto = require('crypto-browserify');
// Synchronous key derivation
const password = 'user-password';
const salt = crypto.randomBytes(16);
const derivedKey = crypto.pbkdf2Sync(password, salt, 100000, 32, 'sha256');
console.log('Derived key:', derivedKey.toString('hex'));
// Key stretching for master password
function deriveMasterKey(userPassword, userSalt) {
try {
return crypto.pbkdf2Sync(userPassword, userSalt, 100000, 32, 'sha512');
} catch (err) {
console.error('Failed to derive master key:', err.message);
return null;
}
}
// Multiple keys from single password
const basePassword = 'MyStrongPassword';
const baseSalt = Buffer.from('application-salt', 'utf8');
// Derive different keys for different purposes
const encryptionKey = crypto.pbkdf2Sync(basePassword, baseSalt + '-encrypt', 100000, 32, 'sha256');
const signingKey = crypto.pbkdf2Sync(basePassword, baseSalt + '-sign', 100000, 32, 'sha256');
const authKey = crypto.pbkdf2Sync(basePassword, baseSalt + '-auth', 100000, 32, 'sha256');Securely hash passwords for database storage with salt and iterations.
const crypto = require('crypto-browserify');
class PasswordManager {
static hashPassword(password) {
const salt = crypto.randomBytes(16);
const hash = crypto.pbkdf2Sync(password, salt, 100000, 64, 'sha512');
return {
salt: salt.toString('hex'),
hash: hash.toString('hex'),
iterations: 100000,
algorithm: 'sha512'
};
}
static verifyPassword(password, stored) {
const salt = Buffer.from(stored.salt, 'hex');
const hash = crypto.pbkdf2Sync(password, salt, stored.iterations, 64, stored.algorithm);
return hash.toString('hex') === stored.hash;
}
}
// Usage
const userPassword = 'MySecurePassword123!';
const hashedData = PasswordManager.hashPassword(userPassword);
console.log('Stored hash data:', hashedData);
const isValid = PasswordManager.verifyPassword(userPassword, hashedData);
console.log('Password valid:', isValid);Derive strong encryption keys from user passwords.
const crypto = require('crypto-browserify');
function encryptData(plaintext, password) {
// Generate random salt and IV
const salt = crypto.randomBytes(16);
const iv = crypto.randomBytes(16);
// Derive encryption key from password
const key = crypto.pbkdf2Sync(password, salt, 100000, 32, 'sha256');
// Encrypt data
const cipher = crypto.createCipheriv('aes-256-cbc', key, iv);
let encrypted = cipher.update(plaintext, 'utf8', 'hex');
encrypted += cipher.final('hex');
// Return salt, IV, and encrypted data
return {
salt: salt.toString('hex'),
iv: iv.toString('hex'),
encrypted: encrypted
};
}
function decryptData(encryptedData, password) {
const salt = Buffer.from(encryptedData.salt, 'hex');
const iv = Buffer.from(encryptedData.iv, 'hex');
// Derive the same key from password and salt
const key = crypto.pbkdf2Sync(password, salt, 100000, 32, 'sha256');
// Decrypt data
const decipher = crypto.createDecipheriv('aes-256-cbc', key, iv);
let decrypted = decipher.update(encryptedData.encrypted, 'hex', 'utf8');
decrypted += decipher.final('utf8');
return decrypted;
}Use a high iteration count to slow down brute-force attacks:
Always use a unique, random salt for each password:
Choose strong hash algorithms:
PBKDF2 functions may throw errors in the following scenarios:
const crypto = require('crypto-browserify');
try {
// Invalid parameters will throw
const key = crypto.pbkdf2Sync('password', 'salt', -1, 32, 'sha256');
} catch (err) {
console.error('Invalid PBKDF2 parameters:', err.message);
}
try {
// Unsupported algorithm will throw
const key = crypto.pbkdf2Sync('password', 'salt', 1000, 32, 'unsupported');
} catch (err) {
console.error('Unsupported hash algorithm:', err.message);
}
// Async error handling
crypto.pbkdf2('password', 'salt', 1000, 32, 'sha256', (err, key) => {
if (err) {
console.error('PBKDF2 failed:', err.message);
return;
}
console.log('Key derived successfully');
});