データベースの学習をしたこともあり、独自にULID(Universally Unique Identifier)を作れないものかと調査を開始して、なんとか、それらしきものを開発しました。
その中でランダムなパスワードが必要になったので、標題にあるメソッドも作りました。(独自ULID生成メソッドは後日紹介できると思います。)
自らの備忘も兼ねて紹介します。
password = function(lng, scl=36) {
if(lng<1) return '';
scl = scl>=2&&scl<=89?scl:36;
const chars = `0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!#$%&()*+,-./:;<=>?@[]^_{}~`;
const a32 = crypto.getRandomValues(new Uint32Array(lng));
return Array.from(a32).map((vc, id, ar)=>chars[vc%scl]).join('');
}
コードの一行目は、password関数(メソッド)の宣言になります。
引数「lng」はパスワードの長さです。
引数「scl」は文字列に利用する文字の範囲です。初期値を36としてます。
「password(36)」と、第二引数は省略(初期値になる)して、動作確認してみます。(Google ChromeのJavascriptコンソールにて、)

二行目では、パスワードの長さが1より小さいと処理を行わずに、空文字を返します。
三行目では、文字の範囲が2から89に収まっていなければ、初期値の36に強制指定します。
四行目は、定数「cahrs」を宣言して、パスワードに利用する文字群を代入してます。
ここで、記号の採用不採用が少々厄介でした。いろいろと参考にしましたが、安定動作を心がけるために結局は勝手に決めました。
採用していない記号は、ダブルクォート「”」とシングルクウォート「’」、バッククウォート「`」、バックスラッシュ「\」、バーティカルバー「|」です。
三種類のクウォートは、どれか一つを不採用にすれば大丈夫そうでした。この場合バックスラッシュを不採用にすれば良いのですが、思い切って全て不採用としました。
バックスラッシュはJavascriptの処理系でエスケープ文字に使われます。何かトラブルの元になる可能性も考えて不採用としました。
バーティカルバーは、不採用にしているケースが多かったので、おまじないのつもりで不採用にしました。
「パスワードに使ってはいけない記号」(感謝。)を読むと、もっと不採用にしても良さそうです。
とりあえず現在は、最大89文字の中からパスワードを生成できます。
数字だけのパスワードであれば、引数「scl」を10に、小文字アルファベットを混ぜるのであれば36に、大文字も混ぜるのであれば62に、採用記号を混ぜるのであれば89にとなります。
記号の採用を変更した場合は、三行目の数値も変更しなくてなりませんので、ご注意ください。
五行目は、定数「a32」を宣言して、後ろの括弧内で生成した型付き配列オブジェクト「Uint32Array」をインターフェイス「Crypto」のメソッド「getRandomValues()」に渡して暗号強度の強い乱数値を仕込んで返ってきたUint32Arrayオブジェクトが代入されます。どこだったかで「Math.random()」ではなくこっちを使えとありました。(感謝。)
コンソールで、バラして動作させてみると何が起こっているのかよく判ります。パスワード桁数は36です。

> a32 = new Uint32Array(36);
<- ▼
> a32 = crypto.getRandomValues(a32);
<- ▼
「crypto」と小文字で始まっているのは「window.crypto」の略でCryptoオブジェクトを参照しているからです。(老婆心まで、)
六行目は、Uint32Arrayオブジェクトを一気に処理してパスワードを返しているのですが、これもコンソールでバラして動作させてみると良いです。
まずは、パスワード用の文字列と、引数「scl」をマックスの89で準備しておきます。

> chars = `0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!#$%&()*+,-./:;<=>?@[]^_{}~`;
<- '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!#$%&()*+,-./:;<=>?@[]^_{}~'
> scl = 89;
<- 89

> a = Array.from(a32);
<- ▼
> a = a.map((vc, id, ar)=>chars[vc%scl]);
<- ▼
> a.join('');
<- ',oqL<(doW,e2:LFu;@26)Bfg>$yD-<6a7g<x'
最初に、配列オブジェクトのfromメソッドでUint32Arrayオブジェクトから普通の配列を生成します。
つぎに、配列オブジェクトのコールバックタイプメソッド「map」を使って、剰余演算結果から一文字ずつ取得して配列を生成します。
最後に、配列オブジェクトのjoinメソッドで配列の内容を連結すればパスワードの完成です。
インターフェイス「Crypto」には、「randomUUID()」というメソッドもあります。
独自ULID生成メソッドなんか作ってないで「これでUUID(Universally Unique Identifier)を生成してもらってもいいんでない?」とも思います。
でも、最初にID生成の開発を考えたときに、タイムスタンプを使おうと思っていたのでULIDの開発になりました。
まあ、それは独自ULID生成メソッドの紹介でも触れると思います。そかさ。