import blake2b from 'blakejs'; const BACKEND_SECRET = process.env.BACKEND_SECRET || 'changeme_secret_key_for_production'; /** * Hash a token with Blake2b-256 (2 iterations). * This must match the Spring/Rust implementation exactly: * - Uses Blake2b-256 (32 bytes output) * - 2 iterations of hashing * - Combines token + secret + salt (group name) * - Returns hex-encoded hash (64 characters) */ export function hashToken(token: string, salt: string): string { // First iteration: hash(token + secret + salt) const input1 = token + BACKEND_SECRET + salt; const hash1 = blake2b.blake2b(input1, undefined, 32); // Second iteration: hash(hash1) const hash2 = blake2b.blake2b(hash1, undefined, 32); // Return hex-encoded (lowercase) return Buffer.from(hash2).toString('hex').toLowerCase(); } /** * Verify if a token matches the stored hash. */ export function verifyToken(token: string, salt: string, storedHash: string): boolean { try { const computedHash = hashToken(token, salt); return computedHash === storedHash.toLowerCase(); } catch { return false; } }