import bcrypt from 'bcrypt'; import crypto from 'crypto'; const SALT_ROUNDS = 12; export async function hashPassword(password: string): Promise { if (password.length < 8) { throw new Error('Пароль должен содержать минимум 8 символов'); } const hasUpperCase = /[A-Z]/.test(password); const hasLowerCase = /[a-z]/.test(password); const hasNumbers = /\d/.test(password); const hasSpecialChar = /[!@#$%^&*(),.?":{}|<>]/.test(password); if (!hasUpperCase || !hasLowerCase || !hasNumbers || !hasSpecialChar) { throw new Error('Пароль должен содержать заглавные и строчные буквы, цифры и специальные символы'); } return await bcrypt.hash(password, SALT_ROUNDS); } export async function verifyPassword(password: string, hash: string): Promise { return await bcrypt.compare(password, hash); } export function generateTempPassword(): string { const lower = 'abcdefghijklmnopqrstuvwxyz'; const upper = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; const digits = '0123456789'; const special = '!@#$%^&*'; const charset = lower + upper + digits + special; const pick = (set: string) => set[crypto.randomInt(set.length)]; const chars: string[] = [ pick(lower), pick(upper), pick(digits), pick(special), ...Array.from({ length: 8 }, () => pick(charset)), ]; // Shuffle using Fisher-Yates with crypto.randomInt for (let i = chars.length - 1; i > 0; i--) { const j = crypto.randomInt(i + 1); [chars[i], chars[j]] = [chars[j], chars[i]]; } return chars.join(''); }