🔑

Goで暗号論的擬似乱数を生成する

2023/12/23に公開

はじめに

この記事は「Qiita Advent Calendar 2023 Go言語」の23日目の記事です。

ゴール

Go言語で署名に利用する鍵を生成したいケースがあったので、その方法をまとめます。

Goの乱数生成

Goの乱数生成に関する標準パッケージには次の2つがあります

math/rand

擬似乱数生成器。
math/rand は、初期化のためのSeedによって、生成される乱数が決まります。(https://golang.org/src/math/rand/rng.go)
Seed値に対応した値を返すため、乱数を再現することが可能です。そのため、生成されるランダム値が予測されやすく暗号系技術での使用には適しません。
https://pkg.go.dev/math/rand

crypto/rand

暗号論的擬似乱数生成器。
io.Readerインターフェイスを利用してランダムなバイト列を取り出すことができます。生成されるランダム値を予測するのが困難なので、秘密鍵の生成などに用いることができます。
https://pkg.go.dev/crypto/rand

今回のケースでは予測困難性が求められるので、crypto/rand を利用して乱数を生成してみます。

64バイトの key を生成する

crypto/rand を利用して64バイトの key を生成するサンプルコードです。

func main() string {
	randBytes := make([]byte, 64)
	_, err := io.ReadFull(rand.Reader, randBytes)
	if err != nil {
		panic(err)
	}

	// バイト列のデータをBase64でエンコーディングし、文字列を生成
	return base64.RawURLEncoding.WithPadding(base64.NoPadding).EncodeToString(randBytes)
}
  • io.ReadFull(rand.Reader, randBytes)でランダムなバイト配列を取得できます。
  • エンコーディングは encoding/base64 を利用できます。
    サンプルでは、RawURLEncoding を使用してURL Safeなエンコーディングを行うようしています。

まとめ

「パスワード・セッションIDの生成」や「暗号化に必要なランダムなバイト列の生成」など、ランダムかつ予測困難性が求められる場合はcrypto/randを利用して生成することができます。

Discussion