GoでBcryptを使用するときのメモ
パスワード保存にargon2が推奨1されている現在でもBcryptを使うときようのメモ。
- 使用しているパッケージ->golang.org/x/crypto/bcrypt
Bcryptは72バイト文字より長い入力を切り捨てる2ため、それ以上の入力を考慮するのであればハッシュ関数(例えば出力長が64バイトのSHA-512)を用いるなどして入力長が72バイト以下に収まるように処理しなくてはならない。一部の実装ではヌルバイト文字を終端文字として認識してしまう問題があるが、golang.org/x/cryptoの実装ではそのような問題がない3ので、HMACを使ってBcryptの入力にすればよい。
※単にSHA-512を使うと脆弱なので❌
var secretKey []byte
func init() {
key := os.Getenv("SECRET_KEY")
if key == "" {
log.Fatal("SECRET_KEY is not set")
}
secretKey = []byte(key)
}
func computeHMACSHA512(data []byte) []byte {
h := hmac.New(sha512.New, secretKey)
h.Write(data)
return h.Sum(nil)
}
func GeneratePasswordHash(password []byte) ([]byte, error) {
p := computeHMACSHA512(password)
return bcrypt.GenerateFromPassword(p, bcrypt.DefaultCost)
}
func VerifyPassword(hashedPassword, password []byte) bool {
p := computeHMACSHA512(password)
return bcrypt.CompareHashAndPassword(hashedPassword, p) == nil
}
-
https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html ↩
-
golang.org/x/cryptoではエラーになる ↩
-
最終的にコミットには含まれていないが、過去にこの動作についてドキュメント化されようとしていたようである->https://go.dev/cl/516916。 ↩