Security

Idea

【初心者向け】乱数と暗号技術について解説(JavaScript も使うよ!)

2025年9月23日

2025年9月23日

【初心者向け】乱数と暗号技術について解説(JavaScript も使うよ!)

こんにちは、けいこんぐらです!

今回は、以下で紹介している書籍を読んで、乱数について学び、奥が深くて面白いなと感じたので、その内容を簡単にまとめてみます 👏

【書籍】暗号化についてよく理解していなかったので「暗号技術入門」を読んでみた!

セキュリティ(暗号化)について素人レベルの知識しかなかったので、「暗号技術入門」という書籍で暗号化の基礎を学んでみました!

https://kotukotu-stack-log.com

【書籍】暗号化についてよく理解していなかったので「暗号技術入門」を読んでみた!

ざっくり今回紹介する内容

  • 乱数と擬似乱数
  • 暗号技術における乱数
  • JavaScript で乱数を予測してみる

私は文系で、難しい計算とか無理なので、専門的な内容は省いて、できるだけわかりやすく解説できればと思います 😵‍💫

暗号技術における乱数の仕組み・重要性について、簡単に理解したい方は、ぜひ最後まで読んでみてください!

乱数って何に使われる?

まずは、日常的に乱数がどのように使われているか、また暗号技術においてなぜ乱数が必要なのかを見ていきます。

日常での使用例 🎲

  • サイコロ
  • ゲームの確率系
  • パスワード生成
  • 音楽アプリのシャッフル再生

暗号技術での使用例 🔐

  • 鍵の生成
  • 初期化ベクトル(IV)の生成
    • ブロック暗号の安全性を高めるために使用されるランダムな値
  • ソルトの生成
    • パスワードのハッシュ化において、同じパスワードでも異なるハッシュ値を生成するためにパスワードの前後に追加されるランダムな値

乱数は、日常生活の中でもよく登場しますが、特に「暗号技術」においては、セキュリティを確保するために非常に重要な役割を果たしています。

世の中には悪いことを考える人(以下、攻撃者と呼びます)がいるので、生成した鍵などを見破られないようにするために、乱数が必要になります 🦹‍♀️

乱数の性質

乱数には 3 つの性質があり、下に行けばいくほど、より見破られにくい乱数になります。

性質説明特徴
無作為性統計的な偏りがない「でたらめ」だが、何度も試行すれば予測可能
ゲームなどであれば十分だが、暗号技術には向かない
予測不可能性過去の数列から次を予測できない過去の結果から次の数列を予測できないため、暗号技術で使える
「一方向ハッシュ」などと組み合わせることで実現可能
再現不可能性同じ数列を再現できない真の乱数
物理現象から情報を得る必要があるため、ソフトウェアでは実現できない

以上の性質を踏まえると、セキュリティが無視できない暗号技術にとって、攻撃者から見破られないために、少なくとも「予測不可能性」が必要であることがわかります。

疑似乱数生成器

ソフトウェアでは、「再現不可能性」を持った乱数を生成することはできませんが、「無作為性」「予測不可能性」を持った乱数を生成することは可能です。

そのために使われるのが 疑似乱数生成器(PRNG: Pseudo-Random Number Generator) です。

真の乱数ではないので、「疑似」なんですね 💡

特徴

  • 外部から与えられたシード値(初期値)を元に乱数を生成する
    • マイクラなんかでもよくシード値って言いますよね 🎮
    • つまり、同じシード値を与えれば、同じ乱数列が生成される

擬似乱数生成器の種類

  • 一般的生成法
    • 方式と過去の出力が既知であれば、未来の出力を予測可能
      • 線形合同法
      • メルセンヌ・ツイスタ
  • 暗号学的に安全な生成法
    • 方式と過去の出力から未来の出力が予測困難で、現在の状態から過去の出力が予測不可能
      • BBS(Blum-Blum-Shub)
      • Fortuna

一般的生成法は未来の出力を予測可能なので、暗号技術には向きません 🙅‍♂️

反対に、暗号学的に安全な生成法は未来の出力を予測できないで、暗号技術に向いています。

JavaScript で体験

JavaScript でも手軽に疑似乱数を生成することができます。

sample.js
// シード値は実装側によって決定される(ブラウザ, OS などに左右される)
// 内部的に Xorshift というアルゴリズムを使用しているらしい
Math.random();

だたこれは、暗号技術には向いていません。ここに記載があります。

Math.random() - JavaScript | MDN

Math.random() は静的メソッドで、 0 以上 1 未満の範囲で浮動小数点の擬似乱数を返します。その範囲ではほぼ均一な分布で、ユーザーは必要なだけ範囲の拡大をすることができます。実装側で乱数

https://developer.mozilla.org

Math.random() - JavaScript | MDN

Math.random() の提供する乱数は、暗号に使用可能な安全性を備えていません。セキュリティに関連する目的では使用しないでください。代わりにウェブ暗号 API (より具体的には Crypto.getRandomValues() メソッド) を使用してください。

実際に予測してみる 🧑‍💻

※ 実行には Node.js が必要です

Chrome の DevTools で以下のコードを実行してみてください。

Chrome DevTools
console.log(
  `${Math.random()} ${Math.random()} ${Math.random()} ${Math.random()}`
);

今回は js-randomness-predictor という NPM パッケージを使って、4 つの疑似乱数から今後出力される疑似乱数を予測してみます!

Terminal
# パッケージインストール
npm i js-randomness-predictor
 
# 予測する!
npx js-randomness-predictor --environment chrome --sequence { 先ほどChromeで取得した疑似乱数たちをコピー } --predictions 10
# example) npx js-randomness-predictor --environment chrome --sequence 0.8718005396476145 0.26303525384344595 0.3715591148468824 0.44276922059614887 --predictions 10
 
# output
{
  "sequence": [
    0.8718005396476145,
    0.26303525384344595,
    0.3715591148468824,
    0.44276922059614887
  ],
  "predictions": [
    0.8105094289543446,
    0.8860500291642275,
    0.25891941035157573,
    0.9230800032711288,
    0.6285448143870935,
    0.19971853472507917,
    0.8994670461609209,
    0.4106324596739902,
    0.236143314832427,
    0.6046395076652631
  ],
  "actual": "You'll need to get this yourself via the same way you generated the sequence"
}

そして、Chrome DevTools で先程の続きから、以下のコードを実行して、予測した乱数(predictions)と出力された乱数が一致するか確認してみてください。

Chrome DevTools
Array.from({ length: 10 }, Math.random);
 
// => (10)[..., ..., ...]

10 個の乱数が予測通りに出力されるはず?です!(おもろい 🧐)

つまり、過去の出力(4 個)から未来の出力(10 個)を予測できてしまったというわけです!

そこで公式にも記載がある通り、セキュリティに関する乱数の生成や鍵の生成には暗号強度の強い専用のメソッドを使用するようにしましょう!

気をつけること

シード値

ここまで、乱数・擬似乱数、暗号技術に適した乱数の性質について解説してきましたが、実際に疑似乱数を使う際、真に気をつけるべきことがあります。

それは、「シード値」の存在です。

暗号化の鍵などを生成するために乱数を使用するわけですが、シード値が攻撃者に知られてしまうと、生成される乱数も予測可能になってしまいます。

結局、疑似乱数を使っても守るべきものは、存在するというわけですね、、

ただ、このシード値を「再現不可能性」を持つ乱数にするなど、工夫することで、より安全に疑似乱数を使用することができます 🍃

擬似乱数生成器は実装しない

疑似乱数生成器の実装は、複雑な計算が必要です。

特にセキュリティに関わる乱数生成器には、単にでたらめな数列を作るだけでなく、攻撃者によるあらゆる予測を阻止するための数学的な厳密さが求められます。

もし、独自実装した場合、一見ランダムに見える数列でも、実はパターンや偏りがあるといった致命的な欠陥が隠れている可能性が大いにあります。

そのため、先人たちの知恵と長年の研究によって開発され、世界中の専門家によって徹底的に検証された信頼性の高いライブラリを使用することが、最も賢明な選択です 🙆‍♂️

まとめ

今回は、乱数と擬似乱数について、また暗号技術における乱数の重要性について解説してみました。

私自身、乱数ってランダムな数字でしょ?ぐらいの感覚でしたが、これを気にちょっぴり理解が深まった気がします。

セキュリティを考える上で、乱数は非常に重要な要素となるので、頭の片隅にでもおいておきましょう 🧠

プロフィール

Profile Icon

けいこんぐら

ITエンジニア

大阪在住のサラリーマン。👨‍💻

新卒未経験でエンジニアとして働き、システムの開発等を行っている。

いつか、つよつよエンジニアになれるように日々頑張っています!

タグ