Подтвердить что ты не робот

Генерировать случайную строку пароля с требованиями в 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);
        }
4b9b3361

Ответ 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)