ネクロマンシング。
さて、これは簡単に解決できます。
crypto-random のない範囲の乱数を検討してください:
// Returns a random number between min (inclusive) and max (exclusive)
function getRandomArbitrary(min, max) {
return Math.random() * (max - min) + min;
}
/**
* Returns a random integer between min (inclusive) and max (inclusive).
* The value is no lower than min (or the next integer greater than min
* if min isn't an integer) and no greater than max (or the next integer
* lower than max if max isn't an integer).
* Using Math.round() will give you a non-uniform distribution!
*/
function getRandomInt(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min;
}
したがって、必要なことは Math.random を crypt からのランダムに置き換えることだけです。
では、Math.random は何をするのでしょうか? MDN
に
よると、 Math.random() 関数は、0 から 1 未満 (0 を含むが 1 は含まない) の範囲の浮動小数点の疑似乱数を返します。
したがって、暗号乱数 >= 0 かつ< 1 ( <= ではない) が必要です。
したがって、 getRandomValues からの負でない(別名、UNSIGNED) 整数が必要です。
どうやってこれを行うのですか?
シンプル: 整数を取得してから Math.abs を実行する代わりに、UInt を取得するだけです。
var randomBuffer = new Int8Array(4); // Int8Array = byte, 1 int = 4 byte = 32 bit
window.crypto.getRandomValues(randomBuffer);
var dataView = new DataView(array.buffer);
var uint = dataView.getUint32();
その簡略版は
var randomBuffer = new Uint32Array(1);
(window.crypto || window.msCrypto).getRandomValues(randomBuffer);
var uint = randomBuffer[0];
あとは、uint を uint32.MaxValue (別名 0xFFFFFFFF) で割って浮動小数点数を取得するだけです。また、結果セットに 1 を含めることはできないため、(uint32.MaxValue+1) で割って結果が < 1 になるようにする必要があります
。JavaScript 整数は 64-ビット浮動小数点数を内部で使用するため、32 ビットに制限されません。
function cryptoRand()
{
var array = new Int8Array(4);
(window.crypto || window.msCrypto).getRandomValues(array);
var dataView = new DataView(array.buffer);
var uint = dataView.getUint32();
var f = uint / (0xffffffff + 1); // 0xFFFFFFFF = uint32.MaxValue (+1 because Math.random is inclusive of 0, but not 1)
return f;
}
その省略形は
function cryptoRand()
{
const randomBuffer = new Uint32Array(1);
(window.crypto || window.msCrypto).getRandomValues(randomBuffer);
return ( randomBuffer[0] / (0xffffffff + 1) );
}
あとは、上記の関数で Math.random() を cryptoRand() に置き換えるだけです。
crypto.getRandomValues が Windows で Windows-CryptoAPI を使用してランダム バイトを取得する場合、これらの値を真に暗号学的に安全なエントロピーのソースと見なすべきではないことに注意してください。