Генерировать случайную строку пароля с требованиями в javascript
Я хочу создать случайную строку, которая должна иметь 5 букв из a-z и 3 числа.
Как я могу сделать это с помощью JavaScript?
У меня есть следующий скрипт, но он не соответствует моим требованиям.
var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
var string_length = 8;
var randomstring = '';
for (var i=0; i<string_length; i++) {
var rnum = Math.floor(Math.random() * chars.length);
randomstring += chars.substring(rnum,rnum+1);
}
Ответы
Ответ 1
Принуждение фиксированного количества символов является идеей bad. Это не улучшает качество пароля. Хуже того, это уменьшает количество возможных паролей, так что взломать с помощью bruteforcing становится легче.
Чтобы создать случайное слово, состоящее из буквенно-цифровых символов, используйте:
var randomstring = Math.random().toString(36).slice(-8);
Как это работает?
Math.random() // Generate random number, eg: 0.123456
.toString(36) // Convert to base-36 : "0.4fzyo82mvyr"
.slice(-8);// Cut off last 8 characters : "yo82mvyr"
Документация для Number.prototype.toString
и string.prototype.slice
.
Ответ 2
Немного более удобный и безопасный подход.
var Password = {
_pattern : /[a-zA-Z0-9_\-\+\.]/,
_getRandomByte : function()
{
// http://caniuse.com/#feat=getrandomvalues
if(window.crypto && window.crypto.getRandomValues)
{
var result = new Uint8Array(1);
window.crypto.getRandomValues(result);
return result[0];
}
else if(window.msCrypto && window.msCrypto.getRandomValues)
{
var result = new Uint8Array(1);
window.msCrypto.getRandomValues(result);
return result[0];
}
else
{
return Math.floor(Math.random() * 256);
}
},
generate : function(length)
{
return Array.apply(null, {'length': length})
.map(function()
{
var result;
while(true)
{
result = String.fromCharCode(this._getRandomByte());
if(this._pattern.test(result))
{
return result;
}
}
}, this)
.join('');
}
};
<input type='text' id='p'/><br/>
<input type='button' value ='generate' onclick='document.getElementById("p").value = Password.generate(16)'>
Ответ 3
Многие ответы (включая оригинал этого) не отвечают требованиям letter- и подсчета количества в ОП. Ниже приведены два решения: общее (без минимальных букв/цифр) и с правилами.
Генеральный:
Я считаю, что это лучшее общее решение, чем выше, потому что:
- это более безопасный, чем принятый/получивший наибольшее количество голосов ответ, а также более универсальный, поскольку он поддерживает любой набор символов с учетом регистра
- это более кратко, чем другие ответы (для общего решения, максимум 3 строки; может быть однострочным)
- он использует только нативный Javascript- не требует установки или других библиотек
Обратите внимание, что
- чтобы это работало в IE, прототип Array.fill() должен быть заполнен
- если доступно, лучше использовать window.crypto.getRandomValues() вместо Math.random() (спасибо @BenjaminH за указание)
Три лайнера:
var pwdChars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
var pwdLen = 10;
var randPassword = Array(pwdLen).fill(pwdChars).map(function(x) { return x[Math.floor(Math.random() * x.length)] }).join('');
Или, как однострочник:
var randPassword = Array(10).fill("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz").map(function(x) { return x[Math.floor(Math.random() * x.length)] }).join('');
С правилами букв/цифр
Теперь вариация на вышесказанное. Это сгенерирует три случайные строки из заданных наборов символов (буквы, числа, либо) и затем скремблирует результат.
Обратите внимание, что ниже используется sort() только для иллюстративных целей. Для производственного использования замените приведенную ниже функцию sort() на функцию случайного отображения, например, Durstenfeld.
Во-первых, как функция:
function randPassword(letters, numbers, either) {
var chars = [
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", // letters
"0123456789", // numbers
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" // either
];
return [letters, numbers, either].map(function(len, i) {
return Array(len).fill(chars[i]).map(function(x) {
return x[Math.floor(Math.random() * x.length)];
}).join('');
}).concat().join('').split('').sort(function(){
return 0.5-Math.random();
}).join('')
}
// invoke like so: randPassword(5,3,2);
То же самое, что и 2-строчный (правда, очень длинный и некрасивый lines-- и не будет 1-строчным, если вы используете правильную функцию перемешивания. Не рекомендуется, но иногда все равно весело):
var chars = ["ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz","0123456789", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"];
var randPwd = [5,3,2].map(function(len, i) { return Array(len).fill(chars[i]).map(function(x) { return x[Math.floor(Math.random() * x.length)] }).join('') }).concat().join('').split('').sort(function(){return 0.5-Math.random()}).join('');
Ответ 4
Это не точно оптимизировано, но оно должно работать.
var chars = "ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz";
var string_length = 8;
var randomstring = '';
var charCount = 0;
var numCount = 0;
for (var i=0; i<string_length; i++) {
// If random bit is 0, there are less than 3 digits already saved, and there are not already 5 characters saved, generate a numeric value.
if((Math.floor(Math.random() * 2) == 0) && numCount < 3 || charCount >= 5) {
var rnum = Math.floor(Math.random() * 10);
randomstring += rnum;
numCount += 1;
} else {
// If any of the above criteria fail, go ahead and generate an alpha character from the chars string
var rnum = Math.floor(Math.random() * chars.length);
randomstring += chars.substring(rnum,rnum+1);
charCount += 1;
}
}
alert(randomstring);
Здесь jsfiddle для тестирования: http://jsfiddle.net/sJGW4/3/
Ответ 5
Я написал маленький, вдохновленный вашим ответом:
(function(){g=function(){c='0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';p='';for(i=0;i<8;i++){p+=c.charAt(Math.floor(Math.random()*62));}return p;};p=g();while(!/[A-Z]/.test(p)||!/[0-9]/.test(p)||!/[a-z]/.test(p)){p=g();}return p;})()
Эта функция возвращает пароль и может использоваться в букмаркете наподобие:
javascript:alert(TheCodeOfTheFunction);
Ответ 6
Для кого-то, кто ищет самый простой сценарий. Нет while (true)
, нет if/else
, нет декларации.
Основывается на ответе mwag, но этот использует crypto.getRandomValues
, более сильный случай, чем Math.random
.
Array(20)
.fill('0[email protected]-#$')
.map(x => x[Math.floor(crypto.getRandomValues(new Uint32Array(1))[0] / (0xffffffff + 1) * x.length)])
.join('');
Смотрите это для магии 0xffffffff
.
Откройте консоль и проверьте себя:
for (let i = 0 ; i < 100; i++)
console.log(
Array(20)
.fill('0[email protected]-#$')
.map(x => x[Math.floor(crypto.getRandomValues(new Uint32Array(1))[0] / (0xffffffff + 1) * x.length)])
.join('')
)
Если вы считаете производительность, вы можете попробовать это:
var generate = (
length = 20,
wishlist = "0[email protected]-#$"
) => Array(length)
.fill('') // fill an empty will reduce memory usage
.map(() => wishlist[Math.floor(crypto.getRandomValues(new Uint32Array(1))[0] / (0xffffffff + 1) * wishlist.length)])
.join('');
// Generate 100 passwords
for (var i = 0; i < 100; i++) console.log(generate());
Ответ 7
В случае, если вам нужен пароль, сгенерированный, по крайней мере, с 1 цифрой, 1 символом верхнего регистра и 1 символом нижнего регистра:
function generatePassword(passwordLength) {
var numberChars = "0123456789";
var upperChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
var lowerChars = "abcdefghijklmnopqrstuvwxyz";
var allChars = numberChars + upperChars + lowerChars;
var randPasswordArray = Array(passwordLength);
randPasswordArray[0] = numberChars;
randPasswordArray[1] = upperChars;
randPasswordArray[2] = lowerChars;
randPasswordArray = randPasswordArray.fill(allChars, 3);
return shuffleArray(randPasswordArray.map(function(x) { return x[Math.floor(Math.random() * x.length)] })).join('');
}
function shuffleArray(array) {
for (var i = array.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = array[i];
array[i] = array[j];
array[j] = temp;
}
return array;
}
alert(generatePassword(12));
Вот скрипка, если вы хотите играть/тестировать: http://jsfiddle.net/sJGW4/155/
Рекомендую @mwag за то, что он дал мне начало создавать это.
Ответ 8
Как отмечает @RobW, ограничение пароля на фиксированное количество символов, предложенное в схеме OP, - это плохая идея. Но хуже, ответы, предлагающие код, основанный на Math.random
, являются, ну, действительно плохой идеей.
Начните с плохой идеи. Код OP произвольно выбирает строку из 8 символов из набора из 62. Ограничение случайной строки на 5 букв и 3 числа означает, что результирующие пароли будут иметь в лучшем случае, 28,5 бит энтропии (как против потенциала 47,6 бит, если ограничение на распространение 5 букв и 3 номера было удалено). Это не очень хорошо. Но на самом деле ситуация еще хуже. в лучшем аспекте кода уничтожается с помощью Math.random
в качестве средства генерации энтропии для паролей. Math.random
- генератор псевдослучайных чисел. Из-за детерминированного характера генераторов псевдослучайных чисел энтропия полученных паролей действительно плоха, что делает любое такое предлагаемое решение действительно плохим идеей. Предполагая, что эти пароли выдаются конечным пользователям (о/о, что точка), активный противник, который получает такой пароль, имеет очень хорошие шансы предсказывать будущие пароли, предоставленные другим пользователям, и это, вероятно, не очень хорошо.
Но вернемся к просто плохой идее. Предположим, что вместо Math.random
используется криптографически сильный генератор псевдослучайных чисел. Почему вы ограничиваете пароли 28,5 бит? Как уже отмечалось, это не очень хорошо. Предположительно, 5 букв, 3 цифры схемы, чтобы помочь пользователям в управлении случайным образом устаревших паролей. Но позвольте ему взглянуть на это, вы должны сбалансировать удобство использования против ценности использования, а 28,5 бит энтропии не имеют большого значения в защите против активного противника.
Но достаточно плохо. Предложим путь вперед. Я буду использовать библиотеку JavaScript EntropyString, которая "эффективно генерирует криптографически сильные случайные строки указанной энтропии из разных наборов символов". Вместо символов OP 62 я использую набор символов с 32 символами, выбранными для уменьшения использования легко запутанных символов или формирования английских слов. И вместо схемы с 5 буквами, которая имеет слишком мало энтропии, я провозглашу, что пароль будет содержать 60 бит энтропии (это баланс легкости и ценности).
import {Random, charSet32} from 'entropy-string'
const random = new Random(charSet32)
const string = random.string(60)
"Q7LfR8Jn7RDp"
Обратите внимание, что аргумент random.string
- это требуемые биты энтропии, а не более часто встречающиеся решения для генерации случайных строк, которые определяют передачу в длину строки (которая является как ошибочной, так и обычно неопределенной, но эта другая история).
Ответ 9
var letters = ['a','b','c','d','e','f','g','h','i','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'];
var numbers = [0,1,2,3,4,5,6,7,8,9];
var randomstring = '';
for(var i=0;i<5;i++){
var rlet = Math.floor(Math.random()*letters.length);
randomstring += letters[rlet];
}
for(var i=0;i<3;i++){
var rnum = Math.floor(Math.random()*numbers.length);
randomstring += numbers[rnum];
}
alert(randomstring);
Ответ 10
Я бы не рекомендовал использовать принудительный пароль, поскольку он ограничивает безопасность пользователя, но каким-либо образом есть несколько способов сделать это -
Традиционный метод JavaScript -
Math.random().toString(36).slice(-8);
Использование случайной строки
Установить случайную строку:
npm install randomstring
Используя его в App.js -
var randStr = require('randomstring');
var yourString = randStr.generate(8);
Значение вашего пароля удерживается в переменной yourString
.
Не используйте принудительный пароль!
Принудительный пароль может нанести вред вашей безопасности, поскольку все пароли будут находиться под одним и тем же набором символов, что может быть легко нарушено!
Ответ 11
И, наконец, без использования взломов с плавающей запятой:
function genpasswd(n) {
// 36 ** 11 > Number.MAX_SAFE_INTEGER
if (n > 10)
throw new Error('Too big n for this function');
var x = "0000000000" + Math.floor(Number.MAX_SAFE_INTEGER * Math.random()).toString(36);
return x.slice(-n);
}
Ответ 12
Мой Crypto основан на проблеме. Использование ES6 и отсутствие каких-либо проверок функций браузера. Любые комментарии по безопасности или производительности?
const generatePassword = (
passwordLength = 12,
passwordChars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz',
) =>
[...window.crypto.getRandomValues(new Uint32Array(passwordLength))]
.map(x => passwordChars[x % passwordChars.length])
.join('');
Ответ 13
Существует генератор строки случайных паролей с выбранной длиной
let input = document.querySelector("textarea");
let button = document.querySelector("button");
let length = document.querySelector("input");
function generatePassword(n)
{
let pwd = "";
while(!pwd || pwd.length < n)
{
pwd += Math.random().toString(36).slice(-22);
}
return pwd.substring(0, n);
}
button.addEventListener("click", function()
{
input.value = generatePassword(length.value);
});
<div>password:</div>
<div><textarea cols="70" rows="10"></textarea></div>
<div>length:</div>
<div><input type="number" value="200"></div>
<br>
<button>gen</button>
Ответ 14
Безопасный пароль с одним символом верхнего регистра.
let once = false;
let newPassword = Math.random().toString(36).substr(2, 8).split('').map((char) => {
if(!Number(char) && !once){
once = true;
return char.toUpperCase();
}
return char;
}).join('');
console.log(newPassword)
Ответ 15
Попробуйте это, это работает. Загрузите скрипт в приложение javascript и вызовите функцию randomPassword() https://gist.github.com/enishant/4ba920c71f338e83c7089dc5d6f33a64