動かざることバグの如し

近づきたいよ 君の理想に

JavaScriptでパスワード生成するときはMath.random()を使うな

パスワード生成するメソッド

指定した桁数のパスワードを生成するメソッドをTypeScriptで実装した。

別にjsでも動くと思う

export const generatePassword = (length: number): string => {
  const characters = 'abcdefghijklmnopqrstuvwxyz0123456789';
  let password = '';
  for (let i = 0; i < length; i++) {
    const randomIndex = Math.floor(Math.random() * characters.length);
    password += characters[randomIndex];
  }
  return password;
};

console.log(generatePassword(8));

動作としては問題ないのだが、何回か実行しているとどうも同じ文字が連続して生成される気がする。

❯ bun index.ts
2xdd87lv
❯ bun index.ts
qeezy2ew

でChatGPTに聞いたら案の定 Math.random()を使うのは良くないらしい

代わりにCrypto.getRandomValues()使えと言われたので書き直してもらった

export const generatePassword = (length: number): string => {
  const characters = 'abcdefghijklmnopqrstuvwxyz0123456789';
  let password = '';
  const randomValues = new Uint32Array(length);
  crypto.getRandomValues(randomValues);
  for (let i = 0; i < length; i++) {
    const randomIndex = randomValues[i] % characters.length;
    password += characters[randomIndex];
  }
  return password;
};
  • const randomValues = new Uint32Array(length);
    • Uint32Arrayは、符号なし32ビット整数の配列を作成します。
    • lengthは配列の長さで、ここではパスワードの長さに相当します。
    • この行は、ランダムな値を格納するための空の配列を作成します。
  • crypto.getRandomValues(randomValues);
    • cryptoは、暗号化操作のためのグローバルオブジェクトです。
    • getRandomValuesメソッドは、引数として渡された配列を、暗号学的に安全なランダムな値で埋めます。
    • この行は、randomValues配列をランダムな数値で満たすために使用されます。

よさそう

❯ bun index.ts
n4je65la

てかググってたらもっとスマートに実装してる人いたわ

export const generatePassword = (length: number): string => {
  const characters = 'abcdefghijklmnopqrstuvwxyz0123456789';
  return Array.from(crypto.getRandomValues(new Uint32Array(length)))
    .map(value => characters[value % characters.length])
    .join('');
};

参考リンク