[golang] crypto/rand で疑似乱数生成器を初期化する
Go 言語で疑似乱数 math/rand を使うとき、実行ごとに別の乱数列を選択するための方法として、rand.Seed(time.Now().UnixNano()) とするのが人気があるようなのですが、より予測困難さを追加するためには以下のコードのようにすると良いです。
今日では、Perl, Ruby, Python などで、明示的な seed をせずに rand を使った場合に、内部的に行われる自動的な seed では、OS の乱数生成器由来の値が使われるようになっているので、Go でも同じ感じで良いと思います。
LittleEndian は BigEndian でも良いです。crypto/rand には big.Int のインターフェースもありますが、こちらの方式の方が簡潔に書けると思います。
蛇足ですが、暗号化用の鍵や、何とかトークンのような、長さ分のエントロピーを持つ乱雑な文字列を作りたい場合は、math/rand ではなく、crypto/rand をそのまま使う必要があります。
リンク
math/rand: Deterministic random by default is dangerous #11871
今日では、Perl, Ruby, Python などで、明示的な seed をせずに rand を使った場合に、内部的に行われる自動的な seed では、OS の乱数生成器由来の値が使われるようになっているので、Go でも同じ感じで良いと思います。
package main
import (
cryptorand "crypto/rand"
"encoding/binary"
"math/rand"
)
func main() {
randSeed()
println("rand int:", rand.Int())
}
func randSeed() {
var seed int64
err := binary.Read(cryptorand.Reader, binary.LittleEndian, &seed)
if err != nil {
panic(err)
}
rand.Seed(seed)
}
LittleEndian は BigEndian でも良いです。crypto/rand には big.Int のインターフェースもありますが、こちらの方式の方が簡潔に書けると思います。
蛇足ですが、暗号化用の鍵や、何とかトークンのような、長さ分のエントロピーを持つ乱雑な文字列を作りたい場合は、math/rand ではなく、crypto/rand をそのまま使う必要があります。
リンク
math/rand: Deterministic random by default is dangerous #11871
コメント
コメントを投稿