WebAssembly interface layer providing high-performance cryptographic functions for blockchain applications in the Polkadot ecosystem.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Password-based key derivation functions for generating cryptographic keys from passwords and salts, including PBKDF2 and Scrypt algorithms.
Password-Based Key Derivation Function 2 (PBKDF2) for deriving cryptographic keys from passwords.
/**
* Derives key using PBKDF2
* @param data - Password data as Uint8Array
* @param salt - Salt as Uint8Array (recommended: at least 16 bytes)
* @param rounds - Number of iterations (recommended: at least 10,000)
* @returns 64-byte derived key as Uint8Array
*/
function pbkdf2(data: Uint8Array, salt: Uint8Array, rounds: number): Uint8Array;Usage Example:
import { waitReady, pbkdf2 } from "@polkadot/wasm-crypto";
await waitReady();
const password = new TextEncoder().encode("my-secure-password");
const salt = new Uint8Array(16);
crypto.getRandomValues(salt); // Generate random salt
// Derive key with different iteration counts
const key10k = pbkdf2(password, salt, 10000);
const key100k = pbkdf2(password, salt, 100000);
console.log("PBKDF2 key length:", key10k.length); // 64
console.log("Keys are different:",
Array.from(key10k).join(',') !== Array.from(key100k).join(',')
); // trueScrypt key derivation function designed to be memory-hard and resist hardware attacks.
/**
* Derives key using Scrypt
* @param password - Password as Uint8Array
* @param salt - Salt as Uint8Array (recommended: at least 16 bytes)
* @param log2n - CPU/memory cost parameter (power of 2, e.g., 14 = 2^14 = 16384)
* @param r - Block size parameter (typically 8)
* @param p - Parallelization parameter (typically 1)
* @returns 64-byte derived key as Uint8Array
*/
function scrypt(password: Uint8Array, salt: Uint8Array, log2n: number, r: number, p: number): Uint8Array;Usage Example:
import { waitReady, scrypt } from "@polkadot/wasm-crypto";
await waitReady();
const password = new TextEncoder().encode("my-secure-password");
const salt = new Uint8Array(16);
crypto.getRandomValues(salt); // Generate random salt
// Common Scrypt parameters
const log2n = 14; // N = 2^14 = 16384 (memory cost)
const r = 8; // Block size
const p = 1; // Parallelization
const derivedKey = scrypt(password, salt, log2n, r, p);
console.log("Scrypt key length:", derivedKey.length); // 64import { waitReady, pbkdf2, scrypt } from "@polkadot/wasm-crypto";
async function demonstrateSecureKeyDerivation() {
await waitReady();
const password = new TextEncoder().encode("user-password");
// Generate cryptographically secure salt
const salt = new Uint8Array(32);
crypto.getRandomValues(salt);
// PBKDF2 with high iteration count
const pbkdf2Key = pbkdf2(password, salt, 100000);
// Scrypt with recommended parameters
const scryptKey = scrypt(password, salt, 14, 8, 1);
// Store salt alongside derived key for later verification
const storedData = {
salt: Array.from(salt),
pbkdf2Key: Array.from(pbkdf2Key),
scryptKey: Array.from(scryptKey)
};
console.log("Salt length:", salt.length); // 32
console.log("Both keys derived successfully");
return storedData;
}
demonstrateSecureKeyDerivation();import { waitReady, pbkdf2, scrypt } from "@polkadot/wasm-crypto";
async function compareKeyDerivationPerformance() {
await waitReady();
const password = new TextEncoder().encode("test-password");
const salt = new Uint8Array(32).fill(1); // Fixed salt for consistent timing
// Time PBKDF2
console.time("PBKDF2 (100k iterations)");
const pbkdf2Key = pbkdf2(password, salt, 100000);
console.timeEnd("PBKDF2 (100k iterations)");
// Time Scrypt
console.time("Scrypt (N=16384, r=8, p=1)");
const scryptKey = scrypt(password, salt, 14, 8, 1);
console.timeEnd("Scrypt (N=16384, r=8, p=1)");
console.log("PBKDF2 result length:", pbkdf2Key.length); // 64
console.log("Scrypt result length:", scryptKey.length); // 64
return { pbkdf2Key, scryptKey };
}
compareKeyDerivationPerformance();import { waitReady, pbkdf2, scrypt, hmacSha256 } from "@polkadot/wasm-crypto";
async function demonstrateKeyDerivationWorkflow() {
await waitReady();
// Simulate user registration
const userPassword = "user-secure-password-123";
const passwordBytes = new TextEncoder().encode(userPassword);
// Generate unique salt for this user
const userSalt = new Uint8Array(32);
crypto.getRandomValues(userSalt);
// Derive master key using Scrypt (more secure for password storage)
const masterKey = scrypt(passwordBytes, userSalt, 14, 8, 1);
// Derive application-specific keys using HMAC
const encryptionKey = hmacSha256(masterKey, new TextEncoder().encode("encryption"));
const authKey = hmacSha256(masterKey, new TextEncoder().encode("authentication"));
// For comparison, also show PBKDF2 derivation
const pbkdf2MasterKey = pbkdf2(passwordBytes, userSalt, 100000);
console.log("User salt:", Array.from(userSalt.slice(0, 8)).map(b => b.toString(16).padStart(2, '0')).join(''));
console.log("Scrypt master key:", Array.from(masterKey.slice(0, 8)).map(b => b.toString(16).padStart(2, '0')).join(''));
console.log("PBKDF2 master key:", Array.from(pbkdf2MasterKey.slice(0, 8)).map(b => b.toString(16).padStart(2, '0')).join(''));
console.log("Encryption key:", Array.from(encryptionKey.slice(0, 8)).map(b => b.toString(16).padStart(2, '0')).join(''));
console.log("Auth key:", Array.from(authKey.slice(0, 8)).map(b => b.toString(16).padStart(2, '0')).join(''));
return {
userSalt,
masterKey,
pbkdf2MasterKey,
encryptionKey,
authKey
};
}
demonstrateKeyDerivationWorkflow();Install with Tessl CLI
npx tessl i tessl/npm-polkadot--wasm-crypto