私がプレイしているオンラインゲームで話題になったので、乱数の解析行為とその対策について、簡単にまとめます。
【コンピューターにおける乱数とは】
「乱数」とは、その名の通り、ランダムな数値のことを指します。
しかし、コンピューター上で乱数を生成する場合、特定のアルゴリズムにより疑似的に生成しており、正確に言うと完全にランダムではないため、専門的には「疑似乱数」と呼ばれます。
例えば、平易なアルゴリズムの例として「線形合同法」が挙げられます。
このアルゴリズムでは、「初期値(シード)」と呼ばれるXn(n=0)の値を与え、Xn(n=1)の値をXn(n=0)を元に算出し、Xn(n=2)の値をXn(n=1)を元に算出し…といった形で、前回の乱数の生成値から今回の乱数の生成値を求めています。
他にも疑似乱数を生成するアルゴリズムの種類はいくつか存在しますが、前回の乱数の生成値から今回の乱数の生成値を求めている所は変わりありません。
【疑似乱数の解析行為】
疑似乱数では、アルゴリズムを知っている状態で実際に出力される生成値を観察することで、初期値を解析できる場合があります。
そして、この解析に成功した場合、初期値から順番に計算を行うことで、Xnの値を知ることができます。
例えば、先ほどの「線形合同法」がアルゴリズムとして適用されている場合において、Xn(n=1)から順番に
2, 5, 1, 4, 0, 3...
といった値が観察される場合、初期値は6であると解析することができます。
(M = 7, A = 1, B = 3)
通常、実際に使用される乱数のアルゴリズムはより複雑なものですが、同じ要領で、複数の生成値から初期値を解析することができる場合があります。
【解析行為への対策】
疑似乱数は、暗号鍵の生成のようなセキュリティ分野や、オンラインカジノのようなギャンブル等の分野でも用いられます。
これらの分野で疑似乱数を解析され、乱数の生成値が推測された場合、何かしらの犯罪行為が行われて不利益を受ける可能性あるため、そのような分野で疑似乱数を用いる場合は解析対策を行う必要があります。
対策を行う上では、「暗号論的疑似乱数」と呼ばれる、学術的に解析が困難なアルゴリズムを用いて乱数を生成することが有効です。
(ただし、「暗号論的疑似乱数」は計算量が多いため、シミュレーションや一人向けゲームのような解析対策を行う必要がない分野においては、通常の疑似乱数の方が適しています)
【疑似乱数の実装方法】
各言語で、疑似乱数や暗号論的疑似乱数を生成するためのライブラリが用意されています。
例えば、Javaの場合は以下のようにライブラリを使用して実装することができます。
・疑似乱数
public class Main {
public static void main(String[] args) throws Exception {
double randomNumber = Math.random();
System.out.println(randomNumber);
}
}
・暗号論的疑似乱数
import java.security.SecureRandom;
import java.security.NoSuchAlgorithmException;
public class Main {
public static void main(String[] args) throws Exception {
try {
SecureRandom randomNumber = SecureRandom.getInstance("SHA1PRNG");
System.out.println(randomNumber.nextDouble());
} catch (NoSuchAlgorithmException e) {
// 例外処理
}
}
}