Password-based key derivation functions for generating cryptographic keys from passwords or passphrases. These functions apply computational cost to make brute-force attacks more difficult and derive keys suitable for cryptographic operations.
PBKDF2 with configurable iteration count and hash function. Recommended for modern applications with high iteration counts.
/**
* Derives a key from password using PBKDF2
* @param password - String or WordArray password/passphrase
* @param salt - String or WordArray salt value
* @param cfg - Configuration object with keySize, iterations, and hasher
* @returns WordArray containing the derived key
*/
CryptoJS.PBKDF2(password, salt, cfg)Usage Examples:
var CryptoJS = require("crypto-js");
// Basic PBKDF2 key derivation
var password = "user-password";
var salt = CryptoJS.lib.WordArray.random(128/8); // Random 128-bit salt
var key = CryptoJS.PBKDF2(password, salt, {
keySize: 256/32, // 256-bit key (8 words)
iterations: 250000 // High iteration count for security
});
console.log("Derived key:", key.toString());
console.log("Salt:", salt.toString());
// PBKDF2 with custom hash function
var keyWithSHA512 = CryptoJS.PBKDF2(password, salt, {
keySize: 512/32, // 512-bit key
iterations: 100000,
hasher: CryptoJS.algo.SHA512 // Use SHA-512 instead of default SHA-256
});
// PBKDF2 for AES key generation
var aesKey = CryptoJS.PBKDF2("strong-password", salt, {
keySize: 256/32, // AES-256 key size
iterations: 250000
});
var message = "Secret data";
var encrypted = CryptoJS.AES.encrypt(message, aesKey);
console.log("Encrypted with PBKDF2 key:", encrypted.toString());OpenSSL-compatible key derivation function for compatibility with OpenSSL encrypted data.
/**
* Derives a key from password using OpenSSL EVP KDF
* @param password - String or WordArray password/passphrase
* @param salt - String or WordArray salt value
* @param cfg - Configuration object with keySize and iterations
* @returns WordArray containing the derived key
*/
CryptoJS.EvpKDF(password, salt, cfg)Usage Examples:
var CryptoJS = require("crypto-js");
// Basic EvpKDF key derivation
var password = "password123";
var salt = CryptoJS.enc.Hex.parse("0123456789abcdef"); // 8-byte salt
var key = CryptoJS.EvpKDF(password, salt, {
keySize: 128/32, // 128-bit key (4 words)
iterations: 1 // Default iteration count (legacy compatibility)
});
console.log("EvpKDF derived key:", key.toString());
// EvpKDF for OpenSSL compatibility
var opensslKey = CryptoJS.EvpKDF(password, salt, {
keySize: 256/32 + 128/32, // Key + IV size for AES-256
iterations: 1
});
// Split key and IV
var keyPart = CryptoJS.lib.WordArray.create(opensslKey.words.slice(0, 8)); // First 8 words (256 bits)
var ivPart = CryptoJS.lib.WordArray.create(opensslKey.words.slice(8, 12)); // Next 4 words (128 bits)
var message = "OpenSSL compatible data";
var encrypted = CryptoJS.AES.encrypt(message, keyPart, { iv: ivPart });var CryptoJS = require("crypto-js");
function deriveKeyWithSalt(password, storedSalt) {
// If no salt provided, generate a new one
var salt = storedSalt || CryptoJS.lib.WordArray.random(128/8);
var key = CryptoJS.PBKDF2(password, salt, {
keySize: 256/32,
iterations: 250000
});
return {
key: key,
salt: salt
};
}
// First time - generate salt
var result = deriveKeyWithSalt("user-password");
console.log("Salt to store:", result.salt.toString());
// Later - use stored salt
var storedSalt = CryptoJS.enc.Hex.parse(result.salt.toString());
var derivedAgain = deriveKeyWithSalt("user-password", storedSalt);
console.log("Keys match:", result.key.toString() === derivedAgain.key.toString());var CryptoJS = require("crypto-js");
function deriveMultipleKeys(masterPassword, salt, purposes) {
var keys = {};
purposes.forEach(function(purpose, index) {
// Create unique salt for each purpose
var purposeSalt = CryptoJS.lib.WordArray.create(salt.words.concat([index]));
keys[purpose] = CryptoJS.PBKDF2(masterPassword, purposeSalt, {
keySize: 256/32,
iterations: 150000
});
});
return keys;
}
// Usage
var masterPassword = "master-secret";
var salt = CryptoJS.lib.WordArray.random(128/8);
var keys = deriveMultipleKeys(masterPassword, salt, [
'encryption',
'authentication',
'signing'
]);
console.log("Encryption key:", keys.encryption.toString());
console.log("Authentication key:", keys.authentication.toString());
console.log("Signing key:", keys.signing.toString());var CryptoJS = require("crypto-js");
function hashPasswordForStorage(password, salt, iterations) {
salt = salt || CryptoJS.lib.WordArray.random(128/8);
iterations = iterations || 250000;
var hash = CryptoJS.PBKDF2(password, salt, {
keySize: 256/32,
iterations: iterations
});
return {
hash: hash.toString(),
salt: salt.toString(),
iterations: iterations
};
}
function verifyPassword(password, stored) {
var salt = CryptoJS.enc.Hex.parse(stored.salt);
var hash = CryptoJS.PBKDF2(password, salt, {
keySize: 256/32,
iterations: stored.iterations
});
return hash.toString() === stored.hash;
}
// Usage
var stored = hashPasswordForStorage("user-password");
console.log("Stored hash:", stored.hash);
var isValid = verifyPassword("user-password", stored);
console.log("Password valid:", isValid);var CryptoJS = require("crypto-js");
function benchmarkKDF(password, salt, iterations) {
var start = Date.now();
var key = CryptoJS.PBKDF2(password, salt, {
keySize: 256/32,
iterations: iterations
});
var duration = Date.now() - start;
return {
key: key,
duration: duration,
iterationsPerSecond: Math.round(iterations / (duration / 1000))
};
}
// Find optimal iteration count for ~100ms derivation time
var testSalt = CryptoJS.lib.WordArray.random(128/8);
var testIterations = [10000, 50000, 100000, 250000, 500000];
testIterations.forEach(function(iterations) {
var result = benchmarkKDF("test-password", testSalt, iterations);
console.log(`${iterations} iterations: ${result.duration}ms (${result.iterationsPerSecond} iter/sec)`);
});// PBKDF2 Configuration
PBKDF2Config {
keySize?: number; // Key size in words (default: 4, i.e., 128 bits)
iterations?: number; // Iteration count (default: 250000)
hasher?: Object; // Hash function (default: SHA256)
}
// EvpKDF Configuration
EvpKDFConfig {
keySize?: number; // Key size in words (default: 4, i.e., 128 bits)
iterations?: number; // Iteration count (default: 1)
}
// Key Derivation Result
WordArray {
words: number[]; // Array of 32-bit words containing the key
sigBytes: number; // Number of significant bytes
toString(encoder?): string; // Convert to string representation
clone(): WordArray; // Create a copy of the key
}