#!/usr/bin/env node import { webcrypto } from 'node:crypto'; const password = process.argv[2]; if (!password) { console.error('Usage: node tools/hash.mjs '); process.exit(1); } const PBKDF2_ITERATIONS = 100_000; const SALT_BYTES = 16; async function hashPassword(pw) { const enc = new TextEncoder(); const salt = webcrypto.getRandomValues(new Uint8Array(SALT_BYTES)); const baseKey = await webcrypto.subtle.importKey('raw', enc.encode(pw), 'PBKDF2', false, ['deriveBits']); const bits = await webcrypto.subtle.deriveBits( { name: 'PBKDF2', salt, iterations: PBKDF2_ITERATIONS, hash: 'SHA-256' }, baseKey, 256 ); const hashArr = new Uint8Array(bits); const saltHex = [...salt].map((b) => b.toString(16).padStart(2, '0')).join(''); const hashHex = [...hashArr].map((b) => b.toString(16).padStart(2, '0')).join(''); return `pbkdf2:${PBKDF2_ITERATIONS}:${saltHex}:${hashHex}`; } hashPassword(password).then((h) => { console.log(h); });