or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

cipher-config.mdencoding.mdencryption.mdhash-functions.mdhmac.mdindex.mdkey-derivation.md
tile.json

key-derivation.mddocs/

Key Derivation Functions

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.

Capabilities

PBKDF2 (Password-Based Key Derivation Function 2)

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());

EvpKDF (OpenSSL EVP Key Derivation Function)

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 });

Advanced Key Derivation Patterns

Secure Key Storage Pattern

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());

Multi-Purpose Key Derivation

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());

Password Stretching for Storage

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);

Key Derivation Timing Analysis

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)`);
});

Types

// 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
}