テレビゲームやギャンブル、暗号は一見すると全く関係ないように思えますが、実はすべて「乱数」を利用しており、現代人の生活は乱数なくして成立しません。そんな乱数をコンピューターでどうやって生成させているのかを、プログラミング関連のブログ・BetterProgrammingが解説しています。

Generating Random Numbers Is a Lot Harder Than You Think | by Sunny Beatteay | Sep, 2021 | Better Programming

https://betterprogramming.pub/generating-random-numbers-is-a-lot-harder-than-you-think-b121c3e75d08

プログラミングで乱数を使いたい場合、例えばRubyの場合は「rand」、Pythonの場合は「random()」などのメソッドを使います。この時に生み出されるのはあくまでも計算によって求められる擬似乱数であり、完全にランダムな数ではありません。

そもそもコンピュータは「データを入力して、データを出力する」という論理的な機械であり、コンピュータが乱数を生成するには、乱数の源となるデータが必要。この乱数の源となるデータがどんなものなのかは乱数ジェネレーターによって異なり、BetterProgrammingによれば、乱数ジェネレーターには主に2種類あるとのこと。

1つは「擬似乱数ジェネレーター(PRNG)」と呼ばれるもの。このPRNGで数を生成するには、特定の数値である「シード値」と「乱数生成アルゴリズム」の2つが必要となります。PRNGに使われる乱数生成アルゴリズムには「平方採中法」「線形合同法」「線形帰還シフトレジスタ」「メルセンヌ・ツイスタ」などがあります。

PRNGは完全な乱数を生成できませんが、見た目にはランダムな数を高速かつ安価で生成可能。さらに特定のシード値を用意すれば再現性が得られるので、テスト運用が可能というのも大きなポイントです。そのため、PRNGはゲームやプログラミング言語のランダムメソッドによく用いられています。

ただし、PRNGの生成する数のランダム性はシード値に依存するため、シード値が漏れてしまうと数の生成を予測できてしまうという脆弱性もあります。実際、セキュリティソフトであるカスペルスキーのパスワードマネージャーで、シード値の取得に問題があり、ランダムに生成されるパスワードが予測可能になってしまったという例があります。

カスペルスキーのパスワードマネージャーが生成したパスワードは総当たり攻撃で爆速突破が可能と判明、一体なぜか? - GIGAZINE



そこで、乱数の源となるデータをランダムに生み出すのが「真性乱数ジェネレーター(TRNG)」です。TRNGは、特定の数値であるシード値ではなく、エントロピーを利用するというのが特徴で、より完全に近い乱数を生み出すことができます。そのため、TRNGはサイコロやカードのシャッフル、ルーレットなど、デジタルギャンブルの現場で用いられているとのこと。

どうやってエントロピーを乱数の源のデータにしているのかという点ですが、これはコンピューターを構成する部品にランダム性を求めています。例えばメモリの揮発性や光電効果などの量子現象を使って、物理的なノイズをデジタルの1と0に変換することで、TRNGはランダム性の高い数字を生成します。



一方で、TRNGは数の生成に時間がかかってしまうという欠点があります。さらに乱数の源となるデータにエントロピーが求められるため、アイドル状態のサーバーや新しいサーバーではアクティブなサーバーほどランダム性の高いデータを作成することができません。

PRNGとTRNGにはそれぞれ弱点があるので、テレビゲームやギャンブルでは問題なく使うことができても、高いセキュリティ性が求められる暗号の分野では使うことができません。そこで考案されたのが、PRNGの速さとTRNGのセキュリティ性を両立する「暗号論的擬似乱数ジェネレーター(CSPRNG)」です。

CSPRNGは「高品質のエントロピー源からシード値を作り、それをアルゴリズムに入力して安全性の高い乱数を生成する」というジェネレーター。要するにCSPRNGは「TRNGでPRNGのシード値を生成する」という仕組みです。Unix系OSやLinuxで採用されている/dev/randomは、このCSPRNGを用いています。BetterProgrammingは「これからテレビゲームを遊ぶとき、音楽をシャッフル再生するとき、あるいはプログラミングで乱数を呼びたいとき、コンピューターの中でどんな不思議なことが起こっているのかをよりよく知っておいてほしいと思います」と述べました。