LoginSignup
4
4

More than 5 years have passed since last update.

Node.jsでセキュアな乱数を生成したい!(0.0 ~ 1.0)

Last updated at Posted at 2018-09-09

やりたいこと

0.0~1.0の間で小数の乱数をセキュアに生成したいです

以下のMDNによるとMath.random()はセキュアじゃないです。

Math.random() の提供する乱数は、暗号に使用可能な安全性を備えていません。セキュリティに関連する目的では使用しないで下さい。代わりにWeb Crypto API(より正確にはwindow.crypto.getRandomValues()メソッド)を使用して下さい。

なので、Math.random()のセキュア版を作りたいです。

セキュアな乱数生成

以下のsecureRandom()がセキュアなMath.random()のつもりです。

// cryptoをインポート
const crypto = require('crypto');

// crypto.randomBytes()で生成するときのバイト数
const nBytes   = 4;
// nBytesの整数の最大値
const maxValue = 4294967295

// [0.0, 1.0]区間でセキュアな乱数を生成する
function secureRandom() {
  // nBytesバイトのランダムなバッファを生成する
  const randomBytes = crypto.randomBytes(nBytes);
  // ランダムなバッファを整数値に変換する
  const r = randomBytes.readUIntBE(0, nBytes);
  // 最大値で割ることで、[0.0, 1.0]にする
  return r / maxValue;
}

動かしてみる

以下で動作確認できます([run▶]を押してください)
https://repl.it/@nwtgck/secure-random-number

maxValueの算出について

maxValuenBytesを使えば生成できるはずなのです。JavaScriptでmaxValue == (1 << 8*nBytes) - 1なはずなので、ビット演算をしてみたのですが、うまく行かなかったので、ハードコーディングしています。長くなりますが、以下のように書くと、うまくnBytesからmaxValueを算出できました(なにかいい案があったら教えてもらえると嬉しいです)。

// (計算できるけど、ちょっと長い)
const maxValue = new Buffer(Array(nBytes).fill(0xff)).readUIntBE(0, nBytes); 

Math.random()との違い

Math.random()は「[0, 1)(0以上、1未満)」らしいですが、secureRandom()は[0, 1]なので、そこが違うところだと思います。

参考

4
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4