Как сгенерировать случайный пароль
Короткий ответ
Возьмите случайные байты из crypto.getRandomValues() и превратите каждый в символ из набора:
const generatePassword = (length = 16) => {
const chars = 'abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789!@#$%&*';
const values = crypto.getRandomValues(new Uint32Array(length));
return Array.from(values, (value) => chars[value % chars.length]).join('');
};
const password = generatePassword();
console.log(password.length);Результат:
16Хотя бы один символ каждой группы
Возьмите по одному символу из каждой группы, остальное доберите из всех символов и перемешайте результат:
const groups = ['abcdefghijkmnopqrstuvwxyz', 'ABCDEFGHJKLMNPQRSTUVWXYZ', '23456789', '!@#$%&*'];
const randomIndex = (max) => crypto.getRandomValues(new Uint32Array(1))[0] % max;
const pick = (set) => set[randomIndex(set.length)];
const generatePassword = (length = 12) => {
const all = groups.join('');
const chars = groups.map(pick);
while (chars.length < length) chars.push(pick(all));
for (let i = chars.length - 1; i > 0; i--) {
const j = randomIndex(i + 1);
[chars[i], chars[j]] = [chars[j], chars[i]];
}
return chars.join('');
};
const password = generatePassword();
console.log(password.length, groups.every((set) => [...password].some((char) => set.includes(char))));Результат:
12 trueЧастая ошибка
Math.random() не предназначен для секретов: его последовательность можно предсказать. Для паролей, токенов и кодов всегда используйте crypto.
// not for passwords
const weak = Math.random().toString(36).slice(2);Функции из этого ответа
- Array.from — Создаёт массив из строки, Set, Map или другого перебираемого объекта.
- crypto.randomUUID — Создаёт случайный уникальный идентификатор (UUID).