JavaScriptの要件を使用してランダムなパスワード文字列を生成する


94

私はazから5文字と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);
        }

6
それがあなたの要件を満たしている場合、それでは質問は何ですか?また、強制パスワード要件は悪い考えです。
Rob W


3
new Array(12).fill().map(() => String.fromCharCode(Math.random()*86+40)).join("") 非常に軽量なアプローチで特殊文字の上下限の数字を使用して12文字のパスワードを生成する
気の利いたライナー

回答:


313

固定数の文字を強制することは悪い考えです。パスワードの品質は向上しません。さらに悪いことに、可能なパスワードの数が減るため、ブルートフォーシングによるハッキングが容易になります。

英数字で構成されるランダムな単語を生成するには、以下を使用します。

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メソッドのドキュメント。


6
私は同意しますが、時々あなたは決定を
下す

39
これを使用しない:数値は2進数から10進数に変換され、10進数のスペース全体を「埋める」のに十分なビットがないため、最後の桁は特定の値のセットからのみ選択されます。たとえば、私のコンピュータでは、最後の桁は常に「i」、「r」、および「9」のみです。代わりにこれを使用してください:Math.random().toString(36).substr(2, 8)
Joel

1
36の機能を説明するには:Mozilla からtoString()メソッドは最初の引数を解析し、指定された基数(ベース)で文字列表現を返そうとします。10を超える基数の場合、アルファベットの文字は9より大きい数字を示します。たとえば、16進数(基数16)の場合、aからfが使用されます。したがって、これによれば、基数36を使用すると、0〜9の後にazが得られます。
Shishir Gupta 2016

2
@ShishirGupta .toStringは、36までのベースのみを受け入れます。この回答は、非暗号化ランダム文字列のワンライナーとして意図されています。大文字も使用する場合は、Math.random(またはcrypto.getRandomValues使用可能な場合)を使用して、結果をaz、AZ、0-9にマッピングします。たとえば、以下のsaajの回答を使用します。
Rob W

1
これがOPの要件「azからの5文字と3つの数字」にどのように対処するかを見ていません。私はそれを理解し、著者はそれは悪い考えだと思っています...しかしそれでもそれは要件です
mwag

38

もう少し保守可能で安全なアプローチ。

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)'>


さらに、これは常に生成されたコードに番号を追加しないとOPは最小3を望んでいる
qwertzman

ライブラリことがわかったのNode.jsでサポートwindow.crypto.getRandomValuesと作品だけでなく、github.com/bermi/password-generator
ユージン

ピンチでパスワードを生成するために何かが必要だと言いたかっただけで、これは完璧でした。ありがとうございました!
カイルK

29

多くの回答(元の回答を含む)は、OPの文字数と数の要件に対応していません。以下は2つの解決策です:一般(最小文字/数字なし)とルールあり。

一般:

これは上記よりも一般的な解決策であると私は信じています。

  • 大文字と小文字を区別する方法で任意の文字セットをサポートするため、受け入れられた/最も投票された回答よりも安全であり、さらに汎用性があります。
  • 他の回答よりも簡潔です(一般的な解決策では、最大3行、1行でもかまいません)
  • ネイティブJavascriptのみを使用-インストールやその他のライブラリは不要

ご了承ください

  • これをIEで機能させるには、Array.fill()プロトタイプをポリフィルする必要があります
  • 可能であれば、Math.random()の代わりにwindow.crypto.getRandomValues()を使用することをお勧めします(指摘のために@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('');

文字/数字のルールあり

さて、上記のバリエーション。これにより、指定された文字セット(文字、数字、どちらか)から3つのランダムな文字列が生成され、結果がスクランブルされます。

以下では、説明のみを目的として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ライナーと同じです(確かに、非常に長くて醜いラインです。適切なシャッフル関数を使用すると、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('');

良い答えですが、大文字のYは、生成するパスワードに表示されません。
Ryan Shillington 2017年

1
ありがとう。OPの質問で文字セットを使用しましたが、欠陥があったようです。今更新しました。
mwag 2017

あなたは「それは受け入れられた/最も投票された回答よりも安全です」と言います。その理由について詳しく教えてください。
BenjaminH

また、Math.random()の使用は予測可能です。したがって、パスワードを生成するには、window.crypto.getRandomValuesなどの関数を使用することをお勧めします。
BenjaminH

2
これがより安全である理由は、toString(36)を使用するよりもサポートされる出力の文字数が多いためです。固定出力長(例:8)で、最大36文字から選択できる場合は、62文字(例のように)の場合よりも順列がはるかに少なく、95文字全体が印刷可能(ASCII) )文字、またはユニコードを使用している場合は、バイトあたりの可能性の数がさらに多くなります。
mwag

11

最も単純なスクリプトを探している人のために。いいえwhile (true)、いいえif/else、いいえ宣言。

mwagの答えに基づいていますが、これはcrypto.getRandomValues、より強いランダムを使用していMath.randomます。

Array(20)
  .fill('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz~!@-#$')
  .map(x => x[Math.floor(crypto.getRandomValues(new Uint32Array(1))[0] / (0xffffffff + 1) * x.length)])
  .join('');

これを参照してください0xffffffff

代替案1

var generatePassword = (
  length = 20,
  wishlist = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz~!@-#$"
) => Array(length)
      .fill('')
      .map(() => wishlist[Math.floor(crypto.getRandomValues(new Uint32Array(1))[0] / (0xffffffff + 1) * wishlist.length)])
      .join('');

console.log(generatePassword());

代替案2

var generatePassword = (
  length = 20,
  wishlist = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz~!@-#$'
) =>
  Array.from(crypto.getRandomValues(new Uint32Array(length)))
    .map((x) => wishlist[x % wishlist.length])
    .join('')

console.log(generatePassword())

Node.js

const crypto = require('crypto')

const generatePassword = (
  length = 20,
  wishlist = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz~!@-#$'
) =>
  Array.from(crypto.randomFillSync(new Uint32Array(length)))
    .map((x) => wishlist[x % wishlist.length])
    .join('')

console.log(generatePassword())

1
オフセットが定義されていないため、これは長さが20のパスワードを一貫して提供しません。+ 1一部は不要であり、削除することができます。
bryc

良いキャッチ@bryc。更新しました。ありがとう。
Ninh Pham

1
便利で簡単なソリューション。NodeJS以内にこれを行うために探して誰でも簡単に置き換えることができcrypto.getRandomValuescrypto.randomFillSync
Rvy Pandey

Node.jsバージョンを追加しました。@Rvy Pandeyに感謝します。
ニンファム

8

これは正確には最適化されていませんが、動作するはずです。

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/


1
chars.substring(rnum, rnum+1)のようなものですchars.charAt(rnum)
Mad Echet 14

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に小道具をくれて、これを作成するためのスタートをくれてくれました。


1
あなたは小文字が不足していますj:Pそうでなければ、ここに良いものがあります。私の要件を満たすために少し変更しました。
Igor Yavych 2017

7

@RobWが指摘するように、OPスキームで提案されているように、パスワードを固定数の文字に制限することは悪い考えです。しかしさらに悪いことに、コードに基づいたコードを提案する回答Math.randomは、まあ、本当に悪い考えです。

悪い考えから始めましょう。OPコードは、62のセットから8文字の文字列をランダムに選択します。ランダムな文字列を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文字、3桁のスキーム(エントロピーが少なすぎる)ではなく、パスワードに60ビットのエントロピーがあることを宣言します(これは使いやすさと値のバランスです)。

import {Random, charSet32} from 'entropy-string'
const random = new Random(charSet32)
const string = random.string(60)

「Q7LfR8Jn7RDp」

への引数random.stringは、文字列の長さを渡すことを指定するランダムな文字列生成に対するより一般的に見られるソリューションとは対照的に、望ましいエントロピーのビットです(これは誤ったガイドであり、通常は指定が不十分ですが、それは別の話です)。


6

私はあなたの答えに触発された小さなものを書きました:

(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);

3

ユーザーのセキュリティを制限するため、強制パスワードの使用はお勧めしませんが、いくつかの方法があります-

従来のJavaScriptメソッド-

Math.random().toString(36).slice(-8);

ランダム文字列の使用

ランダムな文字列をインストールします。

npm install randomstring

App.jsでの使用-

var randStr = require('randomstring');

var yourString = randStr.generate(8);

パスワードの値は変数に保持されていますyourString

強制パスワードを使用しないでください!

強制パスワードは、すべてのパスワードが同じ文字セットであり、簡単に侵害される可能性があるため、セキュリティを損なう可能性があります。


3

わかりました。ランダムに配置された5つの文字と3つの数字を含み、長さが8文字で、majとminの文字を受け入れるランダムな文字列パスワードを取得しようとしていることをよく理解している場合は、次の関数でそれを行うことができます。 :

function randPass(lettersLength,numbersLength) {
    var j, x, i;
    var result           = '';
    var letters       = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
    var numbers       = '0123456789';
    for (i = 0; i < lettersLength; i++ ) {
        result += letters.charAt(Math.floor(Math.random() * letters.length));
    }
    for (i = 0; i < numbersLength; i++ ) {
        result += numbers.charAt(Math.floor(Math.random() * numbers.length));
    }
    result = result.split("");
    for (i = result.length - 1; i > 0; i--) {
        j = Math.floor(Math.random() * (i + 1));
        x = result[i];
        result[i] = result[j];
        result[j] = x;
    }
    result = result.join("");
    return result
}

function randPass(lettersLength,numbersLength) {
    var j, x, i;
    var result           = '';
    var letters       = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
    var numbers       = '0123456789';
    for (i = 0; i < lettersLength; i++ ) {
        result += letters.charAt(Math.floor(Math.random() * letters.length));
    }
    for (i = 0; i < numbersLength; i++ ) {
        result += numbers.charAt(Math.floor(Math.random() * numbers.length));
    }
    result = result.split("");
    for (i = result.length - 1; i > 0; i--) {
        j = Math.floor(Math.random() * (i + 1));
        x = result[i];
        result[i] = result[j];
        result[j] = x;
    }
    result = result.join("");
    return result
}
console.log(randPass(5,3))


2
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);

1

そして最後に、浮動小数点ハックを使用せずに:

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);
}

1

1つのupperCase文字でパスワードを保護します。

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)

1

私の暗号ベースの問題を取り上げます。ES6を使用し、ブラウザの機能チェックを省略します。セキュリティまたはパフォーマンスに関するコメントはありますか?

const generatePassword = (
  passwordLength = 12,
  passwordChars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz',
) =>
  [...window.crypto.getRandomValues(new Uint32Array(passwordLength))]
    .map(x => passwordChars[x % passwordChars.length])
    .join('');


1

PassswordGeneratorServiceというパスワードジェネレーターサービスを作成する

import { Injectable } from '@angular/core';

@Injectable()
export class PasswordGeneratorService {

  generatePassword(length:number,upper:boolean,numbers:boolean,symbols:boolean) {
    const passwordLength = length || 12;
    const addUpper =  upper;
    const addNumbers =  numbers;
    const addSymbols =  symbols;

    const lowerCharacters = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'];
    const upperCharacters = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];
    const numbers = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
    const symbols = ['!', '?', '@'];

    const getRandom = array => array[Math.floor(Math.random() * array.length)];

    let finalCharacters = '';

    if (addUpper) {
      finalCharacters = finalCharacters.concat(getRandom(upperCharacters));
    }

    if (addNumbers) {
      finalCharacters = finalCharacters.concat(getRandom(numbers));
    }

    if (addSymbols) {
      finalCharacters = finalCharacters.concat(getRandom(symbols));
    }

    for (let i = 1; i < passwordLength - 3; i++) {
      finalCharacters = finalCharacters.concat(getRandom(lowerCharacters));
    }

    return  finalCharacters.split('').sort(() => 0.5 - Math.random()).join('');
  }
}

使用しているモジュールにサービスを追加することを忘れないでください

@NgModule({
  imports: [
    CommonModule,
    SharedModule,
    CommonModule,
    RouterModule.forChild(routes),
    FormsModule,
    ReactiveFormsModule,
    FlexLayoutModule,
    TranslateModule,
    ExistingUserDialogModule,
    UserDocumentsUploadDialogModule
  ],
  declarations: [
    UserListComponent,
    EditUserDialogComponent,
    UserEditorComponent
  ],
  entryComponents: [
    EditUserDialogComponent
  ],
  providers: [
    AuthService,
    PasswordGeneratorService
  ]
})
export class UsersModule {
}

コントローラ上で、サービス内でパスワード生成メソッドを呼び出すメソッドを追加し、結果をパスワードフィールドに設定します

  constructor(
     private passwordGenerator: PasswordGeneratorService,
    )
  get newPassword() {
    return this.password.get('newPassword');
  }
  generatePassword() {
    this.newPassword.setValue(this.passwordGenerator.generatePassword(8,true,true,true));
  }

私は関数generatePasswordを削除して使用しましたが、クラス全体を必要としません。thnx
Biskrem Muhammad

0

長さが選択されたランダムなパスワード文字列ジェネレータがあります

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>


0

ええと、いつでも最新バージョンのブラウザで利用できるwindow.cryptoオブジェクトを使用できます。

乱数を取得するには、1行のコードが必要です。

let n = window.crypto.getRandomValues(new Uint32Array(1))[0];

また、データの暗号化と復号化にも役立ちます。MDN Web docs-window.cryptoで詳細をご覧ください。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.