CryptGenRandomは、 Microsoft CryptoAPIに含まれる、暗号的に安全な疑似乱数生成関数です。Win32プログラムでは、乱数生成が必要なあらゆる場所でMicrosoftはこの関数の使用を推奨していました(その後、 BCryptGenRandomに置き換えられました。下記参照)。Kernel32での同等の関数はRtlGenRandomです
ヘブライ大学が2007年に発表した論文では、Windows 2000におけるCryptGenRandomの実装にセキュリティ上の問題があることが示唆されています(攻撃者がマシンを制御下に置いていると仮定した場合)。マイクロソフトは後に、同じ問題がWindows XPにも存在するものの、Vistaには存在しないことを認めました。マイクロソフトは2008年半ばにWindows XP Service Pack 3でこのバグの修正プログラムをリリースしました。[ 1 ]
CryptGenRandomは、非推奨のWindows CryptoAPIに属しているため、非推奨となりました。最新のCryptography API: Next Generation (CNG) の代替は、BCryptGenRandom(および基盤となるProcessPrngとSystemPrng)です。[ 2 ]
背景
Win32 APIには、 Windowsアプリケーションで使用するためにMicrosoftが提供する暗号化プリミティブのセットであるMicrosoft CryptoAPIによる包括的な暗号化サポートが含まれています。TLSサポート( Schannel API経由)やコード署名などのWindowsテクノロジはこれらのプリミティブに依存しており、これらのプリミティブは暗号的に安全な擬似乱数生成器(CSPRNG)に依存しています。CSPRNGは、Microsoft CryptoAPIに付属する標準のCSPRNGです CryptGenRandom
動作方法
Windows Vista以前
Microsoftが提供する暗号化プロバイダーは、現在と呼ばれる内部関数CryptGenRandomに基づく、同じ実装を共有しています。[ 3 ] 2007年時点では、アルゴリズムの概要のみが公開されていました RtlGenRandom
[ RtlGenRandom ] は、 FIPS 186-2 付録 3.1の規定に従い、 SHA-1をG 関数として用いてランダムランダムを生成します。エントロピーは以下のとおりです。
- 現在のプロセス ID (GetCurrentProcessID)。
- 現在のスレッド ID (GetCurrentThreadID)。
- 起動時からのティックカウント (GetTickCount)。
- 現在の時刻 (GetLocalTime)。
- さまざまな高精度パフォーマンス カウンター (QueryPerformanceCounter)。
- ユーザー名、コンピューター名、検索パスを含む、ユーザーの環境ブロックのMD4ハッシュ。 [...]
- RDTSC、RDMSR、RDPMCなどの高精度内部CPUカウンタ
[省略: 低レベルのシステム情報フィールドとパフォーマンスカウンターの長いリスト] [ 4 ]
Windows Vista以降
マイクロソフトは、2019年に公開されたホワイトペーパーで、Windows 10の乱数ジェネレータの実装について詳しく説明しています。[ 5 ] Windows 10では、
- 乱数生成器には階層構造が存在します。カーネルには「ルート」PRNGがあり、そこから最終的にすべての乱数が導出されます。カーネルはルートPRNGを用いて、論理プロセッサごとに1つのPRNGをシードします(したがって、PRNGの状態はスレッドローカルであり、ロックは不要です)。プロセスが起動すると、カーネルのプロセッサごとのPRNGにランダムバイトを要求し、自身のプロセスPRNGをシードします。そして、プロセスPRNGを用いて、論理プロセッサごとに1つのバッファ付きPRNGもシードします。[ 5 ]
- 乱数を取得するためのすべてのユーザー空間呼び出し( または
CryptGenRandom)はRtlGenRandom、最終的には に帰着しProcessPrng、これはプロセスのプロセッサごとのPRNGからバイト列を返します。PRNGは常に、FIPS SP800-90で規定されているAES-CTR-DRBGアルゴリズムを使用します。 は下位互換性BCryptGenRandomのために古いアルゴリズムの要求も受け入れますが、プロセッサごとのPRNGから乱数のみを返します。[ 5 ] : 8- Windows VistaおよびWindows Server 2008以降では、FIPS 186の代わりにAES-CTR-DRBGがデフォルトになっています。[ 6 ]
- 他のアルゴリズムの削除はWindows 10で行われました。[ 6 ]
- ルートRNGは定期的にエントロピープールから再シードされる。[ 5 ]:9 起動時に利用できるエントロピーが非常に少ない場合、特別な「初期シード」手順により、シードファイル、外部エントロピー、TPMのランダム性、RDRAND /RDSEED命令、ACPI-OEM0テーブル、UEFIエントロピー、および現在の時刻からシードが提供される。[ 5 ]:11
- カーネルは複数のエントロピープールを維持しています。複数のエントロピー源がプールに追加されますが、主なものは割り込みタイミングです。[ 5 ]:12 プールが使用されると、その内容のSHA-512ハッシュが出力として使用されます。[ 5 ]:10 Windowsはエントロピーを推定しません。[ 5 ]:16
安全
暗号システムのCSPRNGのセキュリティは、動的な鍵マテリアルの源となるため、極めて重要です。HTTPS接続を保護するTLSセッションキーなど、「オンザフライ」で必要な鍵は、CSPRNGから生成されます。これらの擬似乱数が予測可能であれば、セッションキーも予測可能になります。CSPRNGはWin32環境における事実上の標準であるため、Windowsユーザーにとってそのセキュリティは非常に重要です。 CryptGenRandom
暗号解読
2007年11月にレオ・ドレンドルフ氏らがエルサレム・ヘブライ大学とハイファ大学で発表したCryptGenRandomの暗号解読では、 Windows 2000におけるこのアルゴリズムの実装に重大な脆弱性が発見されました。[ 7 ]
この脆弱性を悪用するには、攻撃者はまず乱数生成器を実行しているプログラムを侵害する必要があります。論文で指摘されている弱点はすべて、攻撃者が生成器から状態ビットを盗み出すことに依存しています。この攻撃を実行できる立場にある攻撃者は、通常、あらゆる乱数生成器を無効化できる立場にあります(例えば、生成器の出力を盗聴したり、メモリ内で既知の値に固定したりするなど)。しかし、ヘブライ大学のチームは、攻撃者がCryptGenRandomインスタンスのセキュリティを永続的に侵害するには、状態ビットを一度盗むだけで十分だと指摘しています。また、収集した情報を使用して過去に生成された乱数を特定し、既に送信済みのクレジットカード番号などの情報を侵害する可能性もあります。
この論文の攻撃は、CryptGenRandom がストリーム暗号RC4 を使用しており、状態が分かれば逆方向に実行できるという事実に基づいています。また、CryptGenRandom がユーザー モードで実行されるという事実も利用しており、たとえばバッファー オーバーフローを悪用してオペレーティング システムへのユーザー レベルでのアクセス権を持つ人は誰でも、そのプロセスの CryptGenRandom の状態情報を取得できます。最後に、CryptGenRandom はエントロピーからシードを頻繁に更新しません。この問題は、各 Win32 プロセスが独自の CryptGenRandom 状態のインスタンスを持っているという事実によって悪化します。つまり、1 つのプロセスが侵害されても他のすべてのプロセスが推移的に侵害されるわけではありませんが、侵入に成功した場合の存続期間が長くなる可能性があります。
CryptGenRandomアルゴリズムの詳細は当時公開されていなかったため、Dorrendorf氏のチームはリバースエンジニアリングツールを用いてその動作を解明しました。彼らの論文は、Windowsの暗号用乱数生成器の動作を記録した初めての公開記録です。
共通基準
Windows 2000、XP、2003はすべて、CryptGenRandom()およびFIPSGenRandom()の実装を含め、EAL4+の評価に合格しています。セキュリティターゲットに関するドキュメントはCommon Criteria Portalで公開されており、EAL4要件への準拠を示しています。結果として、アルゴリズムのセキュリティについて結論を導くことはほとんどできません。EAL4は、ベストプラクティスと明示されたセキュリティ目標に照らして製品を評価しますが、詳細な暗号解析を行うことはほとんどありません。
FIPS検証
このセクションは、ウィキペディアの品質基準を満たすためにクリーンアップする必要があるかもしれません。具体的な問題は次のとおりです。リストが不完全です。rngvalページにアクセスしてCtrl+Fで「Microsoft Corp」を検索する方が簡単です。本当にリストを完成させたいのでしょうか?退屈で繰り返しが多く、FIPS 186-2への準拠を示すだけです。( 2024年3月) |
Microsoft は、次の環境での RNG 実装の検証を取得しています。
- Windows VistaおよびServer 2008 RNG実装(証明書435)[ 8 ]
- Windows Vista RNG実装(証明書321)[ 8 ]
- Windows 2003 拡張暗号化プロバイダ (rsaenh.dll) (証明書 316) [ 8 ]
- Windows 2003 拡張DSSおよびDiffie-Hellman暗号化プロバイダ(dssenh.dll)(証明書314)[ 8 ]
- Windows 2003 カーネルモード暗号化モジュール (fips.sys) (証明書 313) [ 8 ]
- Windows CEおよびWindows Mobile拡張暗号化プロバイダー(rsaenh.dll)(証明書292)[ 8 ]
- Windows CEおよびWindows Mobile拡張暗号化プロバイダー(rsaenh.dll)(証明書286)[ 8 ]
- Windows CE 拡張暗号化プロバイダー (rsaenh.dll) (証明書 66) [ 8 ]
これらのテストは、「製品のセキュリティを測るものではなく、承認された様々なRNG仕様への適合性をテストするために設計されています。[...] したがって、検証は製品全体のセキュリティの評価または承認として解釈されるべきではありません。」結果として、アルゴリズムのセキュリティについて結論を導き出すことはほとんどできません。FIPS評価は必ずしもソースコードを検査したり、RNGシードの生成方法を評価したりするわけではありません。[ 9 ]
RNG検証リストには、次のような通知が記載されている。「2016年1月1日現在、SP800-131A改訂1版『移行:暗号アルゴリズムと鍵長の使用の移行に関する勧告』に従い、FIPS 186-2、[X9.31]、および1998年版[X9.62]で規定されているRNGの使用は承認されなくなりました。このリストは歴史的目的のみに提供されています。」[ 10 ]
代替手段
APIレベル
Windows開発者には、CryptGenRandom機能にアクセスするための代替手段がいくつかあります。これらの代替手段は同じアルゴリズムを呼び出し、同じセキュリティ特性を共有しますが、他の利点がある場合があります
RtlGenRandomの使用
プログラムにWindows XPまでの下位互換性が必要な場合は、Windows API関数( [ 3 ]RtlGenRandomにあります)を呼び出して、以下に示すように安全なランダムデータを生成できます。これが問題にならない場合は、プログラムは代わりに新しい呼び出し を使用する必要がありますadvapi32.dllBCryptGenRandom
これまで私たちは開発者に対し、鍵、ノンス、パスワードを生成するためにrandなどの関数ではなく、暗号的に安全な乱数を生成するCryptGenRandomなどの関数を使用するよう常に指示してきました。CryptGenRandomの問題は、CryptoAPI(CryptAcquireContextなど)を読み込む必要があることですが、他の暗号関数を使用している場合は問題ありません。
Windows XP以降のデフォルトのインストールでは、CryptGenRandomはADVAPI32!RtlGenRandomという関数を呼び出します。この関数では、CryptAPIの要素をすべてロードする必要はありません。実際、Whidbeyの新しいCRT関数であるrand_sはRtlGenRandomを呼び出します。[ 11 ]
RNGCryptoServiceProviderの使用
.NETを使用するプログラマーは、RNGCryptoServiceProviderクラスを使用する必要があります。[ 12 ]
暗号化 API: 次世代 (CNG) の使用
CNG [ 13 ]は、廃止されたCrypto APIの長期的な代替手段です。CNGは、同等の関数であるBCryptGenRandom [ 14 ]と、鍵生成専用の関数を提供します。
プログラミング言語
- Microsoft Cライブラリ関数は、暗号的に安全な乱数を生成するために
rand_s使用します。 [ 11 ]RtlGenRandom - Unix系システムでは/dev/urandomを使用するosモジュールのPython関数urandomは、 WindowsシステムではCryptGenRandomを呼び出します。[ 15 ]
SunMSCAPIWindows版JREのOpenJDKおよびOracleディストリビューションで利用可能なJCAプロバイダは、Windows - PRNGというアルゴリズム名を持つSecureRandom実装を提供しています。このクラスは、ランダムバイトまたはシードバイトの問い合わせをすべてCryptGenRandomに転送し、追加のシードバイトを設定します。[ 16 ]
参照
- エントロピー供給システムコール- OpenBSDおよびLinuxカーネルのCryptGenRandomとほぼ同等
- /dev/random – ほとんどのUnix系カーネルの乱数ソース
- 乱数ジェネレータ攻撃
参考文献
- ^ 「マイクロソフト、XPに乱数生成器のバグがあることを確認」 。 2008年6月22日時点のオリジナルよりアーカイブ
- ^ CryptGenRandom 関数 (Windows)「重要: この API は非推奨です。新規および既存のソフトウェアでは、Cryptography Next Generation API の使用を開始する必要があります。Microsoft は将来のリリースでこの API を削除する可能性があります。」(この通知は CryptoAPI 全体に適用されます。)
- ^ a b "RtlGenRandom 関数 (ntsecapi.h)" . Microsoft Learn . Microsoft. 2024年2月22日. 2024年11月7日閲覧。
- ^ハワード、マイケル、ルブラン、デイヴィッド (2003). 『Writing Secure Code, Second Edition』. ピアソン・エデュケーション. ISBN 0-7356-1722-8。
- ^ a b c d e f g h Ferguson, Niels (2019年10月). 「Windows 10の乱数生成インフラストラクチャ」(PDF) . download.microsoft.com
- ^ a b "CNGアルゴリズム識別子(Bcrypt.h) - Win32アプリ" . learn.microsoft.com . 2023年4月13日.
注:Windows Vista SP1およびWindows Server 2008以降、乱数ジェネレーターはNIST SP 800-90標準で規定されているAESカウンターモードに基づいています。[...] Windows 10:Windows 10以降、デュアル楕円曲線乱数ジェネレーターアルゴリズムは削除されました。このアルゴリズムの既存の使用は引き続き機能しますが、乱数ジェネレーターはNIST SP 800-90標準で規定されているAESカウンターモードに基づいています。
- ^ Dorrendorf, Leo; Zvi Gutterman; Benny Pinkas. 「Windowsオペレーティングシステムの乱数ジェネレータの暗号解析」(PDF) 。 2012年5月18日時点のオリジナル(PDF)からアーカイブ。 2007年11月12日閲覧。
- ^ a b c d e f g h「RNG検証リスト」。NISTコンピュータセキュリティ部門。 2024年3月20日閲覧。
- ^ 「乱数生成器検証システム(RNGVS)」(PDF)。米国国立標準技術研究所コンピュータセキュリティ部門。2005年1月31日。2013年2月24日時点のオリジナル(PDF)からアーカイブ。 2013年6月18日閲覧。
- ^ 「暗号アルゴリズム検証プログラム: rng検証リスト」。
- ^ a b "rand_s" . Microsoft Learn . Microsoft. 2022年12月2日. 2024年11月7日閲覧。
- ^ 「アーカイブコピー」 2006年9月8日時点のオリジナルよりアーカイブ。 2007年8月27日閲覧。
{{cite web}}: CS1 maint: アーカイブされたコピーをタイトルとして (リンク) - ^ Crypto API 次世代 (Windows)
- ^ BCryptGenRandom (Windows)
- ^ https://docs.python.org/2/library/os.html#os.urandom Python ライブラリリファレンス、OS モジュール
- ^ http://docs.oracle.com/javase/8/docs/technotes/guides/security/SunProviders.html#SunMSCAPI Oracle Java SE 8 技術ドキュメント、Sun Providers