Skip to main content

CSPRNG:ランダムアルゴリズムにもセキュリティが必要!

feature snyk platform

2023年2月9日

0 分で読めます

コインを高く放り投げると、結果は表か裏のどちらかだとわかります。しかし、どちらになるかは予測できません。50%の確率で当てることはできますが、確実に当てることはできません。サイコロを振れば、当たる確率はさらに下がります(6分の1)。それでも、出る可能性のある目はわかっています。

コンピューターはさまざまなことを得意としていますが、特に優れているのが予測可能性です。コンピューターは決定論的であり、真にランダムな数を生成することはできません。しかし、関数を使えば、ランダムに近い値を生成できます。こうした関数は疑似乱数生成器と呼ばれます。

簡単なコードを見てみましょう。

import random

# Generate a random integer between 0 and 10
random_number = random.randint(0, 10)

print(random_number)

このコードは、0から10までのランダムな数を生成します(0と10も結果に含まれます)。先ほどのコイン投げやサイコロを振ることに似ています。どんな結果が出る可能性があるかはわかっていますが、正確に予測することはできません。

暗号技術を扱う場合、予測可能性はゼロでなければなりません。つまり、結果を決して予測できないようにする必要があります。たとえば、パスワードリセット用の「ランダムな」トークンを生成するとします。現在時刻を使ってハッシュ値を生成できます。パスワードリセット用URLに表示すると、ランダムに見えるでしょう。しかし、実際には予測可能です。コードがオープンソースとして公開され、誰でも閲覧できる場合、ハッカーに悪用される可能性があります。

import hashlib
import time

t = time.localtime()
current_time = time.strftime("%H:%M:%S", t)

MD5_hash = hashlib.md5(current_time.encode())

print(MD5_hash.hexdigest())

ランダム性の捉え方は分野によって異なります。たとえばカジノでは、ルーレットを回すことはランダムです。統計上、結果を「予測」できる確率が2.6%あったとしてもです。しかし、暗号技術ではそれでは不十分です!

疑似乱数は安全ではない

先ほど疑似乱数生成器(PRNG)を紹介しましたが、暗号技術にはさらに優れたものが必要です。暗号用途で乱数を安全に使うには、予測できず、繰り返しがなく、パターンもあってはなりません。そこで、暗号学的に安全な疑似乱数生成器(CSPRNG)を使用します。

CSPRNGは、暗号アプリケーションで安全に使えるよう、特別に設計された乱数生成器です。アルゴリズムと生成器の初期化に使ったシード値が知られていても、予測や再現が難しい乱数列を生成するように設計されています。つまり、予測できないことが必要です。それだけでなく、CSPRNGは大量の乱数を生成しても、数列に繰り返しや識別可能なパターンが現れないようにする必要があります。

CSPRNGは、鍵生成、パスワードのハッシュ化、暗号化など、さまざまな暗号アプリケーションで使われています。また、一意のID、トークン、セッションキーの生成など、暗号以外の用途にも使われます。

CSPRNGとエントロピー

CSPRNGの「CS」はどこから来るのでしょうか?その鍵となるのがエントロピーです。

エントロピーとは、データソースに含まれるランダム性や不確実性の尺度です。CSPRNGに欠かせない要素です。エントロピープールは、CSPRNGのシードとして使われるランダムデータの供給源です。また、生成される数値の予測不可能性を保つため、定期的にシードを再設定する際にも使われます。

CSPRNGが利用できるエントロピープールにはさまざまな種類があり、CSPRNGの具体的な実装によって使用するプールが異なります。ハードウェア乱数生成器(HRNG)は、電子ノイズ、放射性崩壊、大気ノイズなど、さまざまなランダム性の源を利用して乱数を生成する物理デバイスです。数値の生成に使われる物理プロセスは予測や再現が難しいため、優れたエントロピー源と考えられています。

一部のオペレーティングシステムは、CSPRNGのシードとして使えるエントロピー源を提供しています。たとえば、LinuxやUNIX系システムの/dev/randomまたは/dev/urandomファイル、WindowsのBCryptGenRandom()などです。Pythonを使っている場合は、os.urandom()を使うと、OS固有の乱数ソースからランダムなバイト列を取得できます。

CSPRNGは、ネットワークトラフィック、マウスの動き、キーボード入力など、さまざまな環境要因からエントロピーを収集することもできます。こうした要因は予測が難しく、優れたエントロピー源となります。さらに一歩進んで、CloudFlareのように溶岩ランプを使うこともできます!

CSPRNGの例

引き続きPythonを使って、URLで安全に使えるトークンを生成する例を見てみましょう。

import secrets

print (secrets.token_urlsafe(16))

このコードは、暗号学的に安全な疑似乱数を生成します。たとえば、パスワードリセット用トークンの生成など、さまざまな用途に使えます。このトークンはURLに含まれ、次のような形式になります:https://supersecurereset.io/forgot-password?token=3PDhWtzkTo9QGAq6mvLxYA

ランダム性とセキュリティについてさらに学ぶ

安全でない乱数やパスワードリカバリーは、コンピューターセキュリティのごく一部にすぎません。安全な環境やアプリケーションを作るには、多くの要素が関わります。すべてを知っている必要はありません。そんなときに役立つのがSnyk Learnです。

Snyk Learnは、セキュリティ専門家が提供するコンテンツで学べる優れたツールです。しかも、完全に無料です。デモではなく、本当に無料で、受講できるレッスン数にも制限はありません。

ランダム性やパスワードリカバリーの方法について詳しく知りたい方は、次の2つのレッスンをご覧ください。

セキュアコーディングのスキルを向上

いつでもどこでも学べる、無料で質の高い開発者向けセキュリティ教育。

続きを読む

Blog

フロンティアモデルは脆弱性を発見した。攻撃者だけがエクスプロイトチェーンを見つけた。

静的解析で欠陥は見つかりましたが、ライブ攻撃テストで侵害につながる連鎖を実証できたのは唯一でした。Evo COS、Claude Security、Claude Code Securityを比較します。

feature insights context
Blog

自律型攻撃はすでに始まっている。防御もそのスピードに追いつかなければならない。

自律型攻撃者によって、防御に使える時間は短くなっています。継続的な検出、修復、検証、予防で、セキュリティチームが攻撃に歩調を合わせる方法をご紹介します。

Blog

AIコーディングエージェントが不適切なアクセス制御を繰り返し実装する理由

AIコーディングエージェントは、コンパイルが通りレビューも通過する一方で、あるテナントのデータを別のテナントに公開してしまう認可ロジックを生成することがあります。不適切なアクセス制御が検出しにくい理由と、その防止策をご紹介します。