JavaScript Tips | 文字列ユーティリティ:生成 - ランダム文字列

JavaScript JavaScript
スポンサーリンク

ランダム文字列ユーティリティで何をしたいか決める

「ランダム文字列」と一口に言っても、目的で“正解の実装”が変わります。

短い一時トークン(画面遷移の一時キー)
テストデータ用の適当なID
ユーザーに見せる仮パスワードや招待コード

業務で一番大事なのは、「セキュリティが必要かどうか」を最初に決めることです。
セキュリティがいらない用途(テストデータ、見た目だけのランダムID)なら Math.random で十分。
パスワード・トークン・認証系なら、必ず crypto.getRandomValues を使うべきです。

ここを曖昧にしたまま書き始めると、「なんとなく動くけど危ないコード」が量産されます。


まずは「非セキュア用途」向けの基本ランダム文字列

文字セットと長さを決める

一番よくある要件はこんな感じです。

「英大文字・英小文字・数字からなる、長さ N のランダム文字列がほしい」

このときは、まず「使う文字の集合(文字セット)」を決めます。

const DEFAULT_CHARS =
  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
JavaScript

そして、「この文字セットからランダムに1文字ずつ選んで、指定の長さだけ連結する」という発想で作ります。

Math.random を使ったシンプル実装

function randomString(length, chars = DEFAULT_CHARS) {
  if (length <= 0) return "";

  let result = "";

  for (let i = 0; i < length; i++) {
    const index = Math.floor(Math.random() * chars.length);
    result += chars[index];
  }

  return result;
}
JavaScript

ポイントを噛み砕きます。

length が 0 以下なら空文字を返す(ガード)。
chars は「使ってよい文字の集合」。
Math.random() は 0 以上 1 未満の乱数を返すので、それに chars.length を掛けてインデックスを決める。
Math.floor で小数点以下を切り捨てて、0〜chars.length - 1 の整数にする。

実際に動かしてみるとこうなります。

randomString(8);                 // 例: "aZ3kP0xQ"
randomString(16);                // 例: "f9Gh2LmN0pQrStUv"
randomString(6, "0123456789");   // 例: "493027"(数字だけ)
JavaScript

テストデータや一時的なIDなど、「バレても困らない用途」なら、このレベルで十分です。


セキュリティが絡むなら crypto.getRandomValues を使う

なぜ Math.random ではダメなのか

Math.random() は「擬似乱数」です。
“それっぽくランダム”に見えるだけで、暗号的には安全ではありません
アルゴリズムや内部状態が分かると、出てくる値をある程度予測できてしまいます。

だから、次のような用途には使ってはいけません。

パスワード生成
ログイン用トークン
パスワードリセット用URLのトークン
APIキー

こういうときは、OS が提供する安全な乱数を使う必要があります。
ブラウザや Node.js では、それをラップした crypto.getRandomValues が使えます。

crypto.getRandomValues を使った安全なランダム文字列

function secureRandomString(length, chars = DEFAULT_CHARS) {
  if (length <= 0) return "";

  const array = new Uint32Array(length);
  crypto.getRandomValues(array);

  let result = "";

  for (let i = 0; i < length; i++) {
    const index = array[i] % chars.length;
    result += chars[index];
  }

  return result;
}
JavaScript

重要ポイントを丁寧に説明します。

Uint32Array(length) で「長さ N の整数配列」を用意する。
crypto.getRandomValues(array) で、配列の各要素に“安全な乱数”を詰めてもらう。
各要素は 0〜2³²-1 の範囲の整数なので、それを chars.length で割った余り(%)をインデックスとして使う。

これで、「各文字の選択に暗号論的に安全な乱数」を使えるようになります。

使い方は Math.random 版と同じです。

secureRandomString(32); // セキュアな32文字のランダム文字列
JavaScript

パスワードやトークンなど、「推測されたら困るもの」は必ずこちらを使う、というルールにしておくと安全です。


実務での使いどころと設計のコツ

用途ごとに関数を分ける

おすすめは、用途ごとに関数を分けておくことです。

export function randomString(length, chars) {
  // 非セキュア用途(テストデータなど)
}

export function secureRandomString(length, chars) {
  // セキュア用途(トークンなど)
}
JavaScript

呼び出し側のコードを読むだけで、「これはセキュアな乱数を使っている」「これはテスト用だ」と分かるようにしておくと、後から見ても迷いません。

文字セットを一箇所にまとめる

よく使う文字セットは、定数としてまとめておくと便利です。

export const CHARS_ALNUM =
  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";

export const CHARS_HEX = "0123456789abcdef";
JavaScript

こうしておくと、

secureRandomString(32, CHARS_HEX); // 16進文字だけのトークン
JavaScript

のように、用途に応じて簡単に切り替えられます。


ちょっとだけ手を動かしてみる

ブラウザのコンソールで、次の順番で試してみてください。

randomString(8);
randomString(8);
randomString(8);

secureRandomString(32);
secureRandomString(32);
JavaScript

「毎回違う値が出る感覚」と、
「長さや文字セットを変えるとどう変わるか」を体で掴んでみてください。

そのうえで、自分のプロジェクトに

export const CHARS_ALNUM = "...";
export function randomString(...) { ... }
export function secureRandomString(...) { ... }
JavaScript

の3点セットを置いて、
「ランダム文字列が欲しくなったら必ずここを通す」というルールにしてみてください。

それができた瞬間、あなたのコードは
「その場しのぎの Math.random 連打」から、
目的に応じてきちんと設計されたランダム文字列ユーティリティに、一段レベルアップします。

タイトルとURLをコピーしました