馃 distributed transcription service thistle.dunkirk.sh
at v0.1.0 1.2 kB view raw
1/** 2 * Client-side password hashing using PBKDF2. 3 * Uses aggressive iteration count to waste client CPU instead of server CPU. 4 * Server will apply lightweight Argon2 on top for storage. 5 */ 6 7const ITERATIONS = 1_000_000; // ~1-2 seconds on modern devices 8 9/** 10 * Hash password client-side using PBKDF2. 11 * @param password - Plaintext password 12 * @param email - Email address (used as salt) 13 * @returns Hex-encoded hash 14 */ 15export async function hashPasswordClient( 16 password: string, 17 email: string, 18): Promise<string> { 19 const encoder = new TextEncoder(); 20 21 // Import password as key 22 const keyMaterial = await crypto.subtle.importKey( 23 "raw", 24 encoder.encode(password), 25 { name: "PBKDF2" }, 26 false, 27 ["deriveBits"], 28 ); 29 30 // Use email as salt (deterministic, unique per user) 31 const salt = encoder.encode(email.toLowerCase()); 32 33 // Derive 256 bits using PBKDF2 34 const hashBuffer = await crypto.subtle.deriveBits( 35 { 36 name: "PBKDF2", 37 salt, 38 iterations: ITERATIONS, 39 hash: "SHA-256", 40 }, 41 keyMaterial, 42 256, // 256 bits = 32 bytes 43 ); 44 45 // Convert to hex string 46 const hashArray = Array.from(new Uint8Array(hashBuffer)); 47 return hashArray.map((b) => b.toString(16).padStart(2, "0")).join(""); 48}