記事一覧へ戻る

乱数生成の「偽物」に騙されるな!Math.random()をセキュリティに使ってはいけない致命的理由

#security

あなたの「ランダム」は、ハッカーに予測されている

男の子
男の子
「博士!パスワードリセット用のトークンを作るのに、JavaScriptの Math.random() を使ったぜ!これで誰にも予測できないランダムな文字列の完成だぜ!」
博士
博士
「な、なんじゃとー!それはシステムに巨大な穴を開けているのと同じじゃぞい! Math.random() はセキュリティに使ってはいけない致命的な弱点があるんじゃ。」
女の子
女の子
「もう、アンタはいつも表面的な便利さに騙されるんだから。擬似乱数は数式で作られてるから、パターンを解析されたら100%予測されちゃうのよ。博士、本物の『安全な乱数』について教えてあげて!」

1. 擬似乱数の限界:なぜ Math.random() は「武器」にならないのか

博士
博士
Math.random() はシミュレーション用じゃ。過去に出た値から次の値を予測できてしまうんじゃよ。実際、オンラインカジノがこれで破られた事件もあるんじゃぞ。」
男の子
男の子
「ええっ!カジノが破られる!?そんなにヤバいやつだったのか…。見た目はバラバラなのに、裏ではバレバレなんだな…。」
女の子
女の子
「『一見バラバラ』と『予測不可能』は別物なの。セキュリティに必要なのは、後者の予測不可能性!デジタルの鍵を作るには、もっと頑丈な素材が必要なのよ。」
実務チェックポイント
  • セッションIDやトークンの生成に標準の乱数関数を使っていないか?
  • その乱数生成器は「暗号学的に安全(CSPRNG)」と明記されているか?
  • 生成された文字列に、特定の文字が出やすい「偏り」はないか?

2. プロの選択:暗号学的に安全な乱数生成(CSPRNG)の実装

博士
博士
「セキュリティには **CSPRNG** を使うのが鉄則じゃ。マウスの動きやCPUの温度変化などの『予測不能なノイズ』を元にしておるから、予測は不可能じゃ。」
男の子
男の子
「マウスの動き!?なんだかスパイ映画みたいだぜ!ブラウザなら window.crypto.getRandomValues() を使えばいいんだな?」
女の子
女の子
「そうよ。当サイトのツールも、そういう安全なAPIを使ってるわ。あと、範囲を絞る時の『偏り(モジュロ・バイアス)』にも注意してね。わずかな偏りもハッカーにはヒントになるんだから。」

🚨 開発現場の注意点:モジュロ・バイアスの罠

安全な乱数を使っても、random % 10 のように範囲を絞る際に、特定の数字が出やすくなる「偏り(モジュロ・バイアス)」が生じることがあります。範囲指定を行う際は、偏りを排除するアルゴリズム(Fisher-Yatesシャッフルなど)を正しく適用する必要があります。

3. 実務シナリオ:安全なランダム文字列の活用例

博士
博士
「パスワードリセットURLや二要素認証のコード、APIキーの発行など、システムの入り口を守る頑丈な鍵として機能させるのじゃ。」
男の子
男の子
「『たかが乱数』なんて思っててごめんだぜ!これからは本物の安全な乱数を味方につけるぜ!」
女の子
女の子
「エンジニアとしての命を守る作法ね。アンタも少しは城壁を高くする努力をしなさいよ!」
「たかが乱数」という油断が、システムの城壁を崩す

まとめ:確かな「無秩序」を味方につけよう

男の子
男の子
「博士、僕、もう Math.random() で鍵は作らないぜ!Crypto最高だぜ!」
女の子
女の子
「正しい知識に基づいた乱数生成は、アプリを一段上の安全なレベルへ引き上げるわ。みんなも無秩序を味方にしましょう!」
博士
博士
「フォッフォッフォ、乱数は運ではなく科学じゃ。当サイトのツールで、本物の安全な乱数の手触りを確かめてみるのじゃぞい!」
パソコン博士
パソコン博士

「0.1234...」といった小数の乱数を作るのと、安全なパスワードを作るのとでは、裏側の仕組みが全く違うのじゃ。テスト用のデータなら Math.random() で十分じゃが、セキュリティが絡むときは必ず「Crypto」という言葉がついた関数を探すのじゃぞ。これはエンジニアとしての「命を守る作法」のようなものじゃな!