暗号化技術を支える重要な技術の一つとして擬似乱数生成機があげられます。やっていることはただ乱数を生成しているだけなのですが、実際ここが脆かったために脆弱なシステムができてしまったという例もあります。
実際に信頼性の高い擬似乱数生成機は優秀なのか調べてみました。
実験の条件
まずは実験する前に条件を整えておきたいと思います。
128MBの乱数を生成するスレッドを同時に8個動かして合計1GBの乱数を生成します。これを1セットとし、合計4セットやって4GBのデータで判定します。
かかった時間はそれぞれのスレッドで時間を測定してそれを合計しています。なのであくまでのべ時間です。実際1本のスレッドで動かした方が速いのかもしれない。
あと進行状況を更新するために2MBごとに画面の更新を行なっています。512回画面の更新のためにスレッドをロックしてるので時間についてはガバガバだと思ってください。調べた感じ誤差は±5秒ぐらいなんでよしとしました。
普通のRandomクラス
C#で標準で使えるSystem.Randomクラスを基準に調べてみたいと思います。
All Count : 4GB Zero Count : 17179822560 One Count : 17179915808 Time : 00:17:41.5735718
調査の結果はビットが1だったの 17,179,915,808個、0だったのは 17,179,822,560個でした。1の方が0.00054277627%多いそうです。(ちなみにもう一回テストを行なっても1の方が0.00542%多かったです。どうしても1の方が多くなる傾向があるっぽい)
値の散布は以下の通りです。ところどころ偏ったところはあるけど問題はないかな。
正直これだけでも十分な気はするんですけどね。ちなみに1MBの乱数の生成に259.03msかかっています。
RNGCryptoServiceProviderクラス
暗号関係のクラスのために用意されている擬似乱数生成機です。スピードが遅い代わりに信頼性の高いもので、状況に応じて使い分けるようにとのことだそうです。しかし実際に調べてみた結果Randomクラスとかかってる時間変わらないんだけどどういうことなんだか
All Count : 4GB Zero Count : 17179850790 One Count : 17179887578 Time : 00:17:04.5266975
こちらの方はビットの1が17,179,887,578個、0が17,179,850,790個で1の方が0.0002141346%多かったです。これを見るとRandomクラスよりも2倍きちんとした乱数が出ているのかなと思いました。てか時間こっちの方が短いんかい
値のばらけ方はRandomと大差ないと思います。
こちらの方は1MBの乱数を生成するのに250msかかっています。条件整えてるはずなのにこちらの方がかかってる時間短いってどういうことなんですかね。
まとめ
コートの描きやすさ的にRandomクラスでいいじゃん(いいじゃん)というオチに。うーん…0.0002%差なら妥協の範囲だと思うんですけどどうなんですかね。
暗号化で危険なのといえば乱数の結果が0とか255とか、ビットが同じので埋まることなのでその辺除外していけばまあ問題ないんじゃないかと思いました。