パスワードを生成して返すメソッドを作った。

データベースの学習をしたこともあり、独自に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コンソールにて、)

password関数(メソッド)の動作確認

二行目では、パスワードの長さが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生成メソッドの紹介でも触れると思います。そかさ。