Go 1.22 の math/rand
パッケージと追加された math/rand/v2
パッケージを眺めている。
おそらく Go 1.22 における疑似乱数関連の最大のトピックは ChaCha8 がランタイムに組み込まれ,疑似乱数生成器の既定アルゴリズムになったことだろう。
ChaCha はストリーム暗号の一種で,簡単に言うと,疑似乱数を生成してそれを平文と XOR するというものらしい。
このうちの疑似乱数を生成する部分を切り出しているようだ。
ストリーム暗号に使うものなので,暗号技術的にセキュアでかつ速いというのが特徴になるだろうか。
ちなみに ChaCha の後ろについている 20 とか 8 とかはラウンド数を示しているそうな。
ChaCha は OpenSSL だか OpenSSH だかでも見かけたような(うろ覚え)。
もし結城浩さんが『暗号技術入門』の第4版を出される機会があれば,付録でいいので是非 ChaCha にも言及して欲しい。
ランタイムに ChaCha8 疑似乱数生成器を組み込む
ChaCha8 疑似乱数生成器のアルゴリズムは internal/chacha8rand
パッケージに実装されている。
中身については割愛させてもらう。
Internal パッケージなので,サードパーティのパッケージからは直接参照できない。
まずは runtime
パッケージに組み込んでいる部分を見てみる。
ちょっと長いけどご容赦。
これは疑似乱数生成器の状態(主に seed)を管理してる部分かな。
最初の seed は乱数デバイスから取ってるんだね。
これに失敗すると時刻から生成する,と。
ユーザ側は明示的に seed を指定する必要がなくなるということやね。
mrandinit()
関数でランタイムを初期化して,それを使って実際に乱数を取得してるのが rand()
関数だね。
ふむふむ。
math/rand パッケージのトップレベル関数群にランタイムの ChaCha8 を組み込む
それじゃあ math/rand
パッケージの方を見てみよう。
go:linkname
ディレクティブの説明は割愛する。
こうやってリンクしてるということで飲み込んでいただければ(笑) そうそう。
go:linkname
ディレクティブは unsafe
パッケージを要求するので,真似するときは要注意だよ。
ともかく,この runtime_rand()
関数を使って rand
.Source
インタフェース互換の構造体 runtimeSource
を定義している。
Seed()
メソッドを呼び出したら panic 吐くとか容赦ないな(笑) runtimeSource
はこんな風に使う。
つまり,環境変数 GODEBUG
で明示的に指定(randautoseed=0
)するか最初に rand
.Seed()
関数を呼び出すかしない限りランタイムに組み込んだ ChaCha8 疑似乱数生成器が有効になるっちうわけだ。
ちなみに lockedSource
は math/rand
パッケージに従来からある疑似乱数生成器で,名前の通り,ちゃんと mutex で排他処理している。
math/rand/v2 パッケージにおける Source インタフェースの定義
では,いよいよ Go 1.22 で追加された math/rand/v2
パッケージを見てみよう。
math/rand
パッケージと math/rand/v2
パッケージとの大きな違いは rand.Source
インタフェースが非互換になっていることだろう。
math/rand
パッケージの Source
インタフェースの定義は以下の通り。
これに対して math/rand/v2
ではこう定義されている。
どえらシンプル! Seed()
メソッドがなくなったのは大きいね。
これによって runtimeSource
やトップレベル関数群が参照する globalRand
の定義もめっさシンプルになった。
うんうん。
シンプルが一番だね。
ChaCha8 を rand.Source にする
ChaCha8 疑似乱数生成器を疑似乱数の Source
として明示的に組み込む場合は, rand
.NewChaCha8()
関数を使って生成する。
ランタイムに組み込まれているものと違って,こちらは排他処理を行っていない。
並行的に安全(concurrency safe)ではないわけだ。
なので平行処理下で math/rand/v2
の ChaCha8 を扱う場合は要注意である。
つか,平行処理下で ChaCha8 疑似乱数生成器を使うならトップレベル関数群を使うべきだろう。
PCG を rand.Source にする
math/rand/v2
にはもうひとつ疑似乱数生成器が用意されている。
PCG (Permuted Congruential Generator) というそうな。
PCG は線形合同法(LCG)のバリエーションなんだそうで, LCG の統計学上の欠点を改善したものらしい。
2014年に発表された比較的新しいアルゴリズムのようだが,今のところは欠点のようなものは特に指摘されてないとか。
当然ながら暗号技術分野では使えない。
こちらも並行的に安全ではないのでご注意を。
これから math/rand を使う理由はないかな
今までは math/rand
で用意されている疑似乱数生成器は暗号技術的にセキュアではない(要件である「予測困難性」を満たさない)ため使いどころを考えなければならなかったが Go 1.22 から math/rand
, math/rand/v2
ともに ChaCha8 が既定の疑似乱数生成器なったため用途を選ばずカジュアルに使えるようになるだろう。
そうなると,これから疑似乱数生成器を使おうというとききに,わざわざ math/rand
を使う理由はないかな。
math/rand
って無駄に複雑になってる感じだもんなぁ。
ちなみに math/rand/v2
では Read()
関数もなくなっているが, math/rand
でも rand
.Read()
関数は Deprecated になってるし,リリースノートを見ると, Read()
関数が使いたきゃ crypto/rand
パッケージを使え,みたいなことが書いてあるので,まぁそういうことなんだろう。
ブックマーク
参考図書
- Go言語による並行処理
- Katherine Cox-Buday (著), 山口 能迪 (翻訳)
- オライリージャパン 2018-10-26
- 単行本(ソフトカバー)
- 4873118468 (ASIN), 9784873118468 (EAN), 4873118468 (ISBN)
- 評価
Eブック版もある。感想はこちら。 Go 言語で並行処理を書くならこの本は必読書になるだろう。
reviewed by Spiegel on 2020-01-13 (powered by PA-APIv5)
- 効率的なGo ―データ指向によるGoアプリケーションの性能最適化
- Bartłomiej Płotka (著), 山口 能迪 (翻訳)
- オライリー・ジャパン 2024-02-24
- 単行本(ソフトカバー)
- 4814400535 (ASIN), 9784814400539 (EAN), 4814400535 (ISBN)
- 評価
版元で Ebook を買える。Go言語のリファレンス本ではない。フトウェア工学,プログラミング(の考え方)を学ぶ教科書的な位置づけかなぁ。
reviewed by Spiegel on 2024-04-21 (powered by PA-APIv5)
- 暗号技術入門 第3版 秘密の国のアリス
- 結城 浩 (著)
- SBクリエイティブ 2015-08-25 (Release 2015-09-17)
- Kindle版
- B015643CPE (ASIN)
- 評価
SHA-3 や Bitcoin/Blockchain など新しい知見や技術要素を大幅追加。暗号技術を使うだけならこれ1冊でとりあえず無問題。
reviewed by Spiegel on 2015-09-20 (powered by PA-APIv5)