認証の基本とパスワードの安全な管理:なぜbcryptを使うべきか?
Bcryptなどのハッシュ化アルゴリズムと、ソルトの役割。
Goの標準ライブラリ(crypto/sha256とか)だけだと すぐ割られる
でも bcrypt は 世界中のセキュリティのプロが「これなら安全!」って認めてる
1.ゴールデンルール:パスワードは「絶対に」平文で保存しない。
ユーザーのパスワードは、万が一データベースが流出しても、攻撃者にすぐ知られてしまわないように、ハッシュ化して保存するのが鉄則です。
・ハッシュ化とは? 一方向の不可逆な変換のこと。元のデータ(パスワード)からは常に同じハッシュ値が作れますが、ハッシュ値から元のパスワードを復元することはできません。
・危険な例:Goの標準ライブラリ(crypto/sha256など)だけを使うと... 高速で汎用性の高いSHA-256などのハッシュ関数は、パスワードのハッシュ化には不向きです。高性能な現代のPCを使えば、ハッシュ化された値から、元のパスワードを**総当たり攻撃(ブルートフォースアタック)**で容易に推測されてしまいます。
2.世界中のセキュリティ専門家が「これなら安全!」と認めているのがbcryptです。
bcryptが優れている理由は、**「遅さ」と「ソルト」**という2つの特徴にあります。
2-1.コストファクターによる「遅さ」の実現
bcryptは意図的にハッシュ化の処理に時間がかかるように設計されています。この「遅延」は..コストファクター(Cost Factor)で調整可能です。
・攻撃者にとって、攻撃者が総当たり攻撃で数億個のパスワードを試そうとすると、その「遅さ」が積み重なり、解読にかかる時間が現実的ではないほど長くなります。
Goのbcryptでは、bcrypt.DefaultCost(現在の推奨値は12)を指定することで、2025年時点でも世界最強クラスのセキュリティを簡単に実現できます。
2-2.ハッシュ値を変える「ソルト(Salt)」の役割
ソルトとは、パスワードをハッシュ化する際、パスワードに付与するランダムな文字列のことです。
ソルトが防ぐ2つの攻撃
レインボーテーブル攻撃の防止
・もしソルトがないと、「password123」というパスワードは誰が使っても常に同じハッシュ値になります。
・攻撃者は事前に大量のパスワードとそのハッシュ値のリスト(レインボーテーブル)を用意し、DBから流出したハッシュ値と照合するだけで、簡単にパスワードを特定できてしまいます。
太郎:password123 → + 自動ソルト「abc123」 → ハッシュ「xxxxxx」
花子:password123 → + 自動ソルト「xyz999」 → ハッシュ「yyyyyy」(全然違う!)
同じパスワードでも、ソルトが違うためハッシュ値が全く異なり、レインボーテーブルは無効化されます。
同じパスワードを隠蔽
・データベースが流出しても、同じパスワードを使っているユーザー(例:全員がpassword123)がいたとしても、ソルトが異なるため、ハッシュ値はすべてバラバラになります。攻撃者は、一つ一つ総当たり攻撃を試すしかなくなり、効率的な攻撃を防げます。
Goでの安全なbcrypt実装方法
Goのgolang.org/x/crypto/bcryptを使えば、ソルトの生成も、ハッシュ値への埋め込みも、比較時のソルト抽出もすべて自動で行われます。開発者が手動でソルトを管理する必要はありません。
ターミナルで以下を打ちます。
Bashgo get golang.org/x/crypto/bcrypt
import "golang.org/x/crypto/bcrypt"
// 1. ユーザー登録時(パスワードを保存するとき)
hashedPassword, _ := bcrypt.GenerateFromPassword(
[]byte(ユーザーが入力したパスワード),
bcrypt.DefaultCost, // ← 2025年でもこれで世界最強クラス
)
// DBに保存(これがDBに入る)
db.SaveUser(hashedPassword) // 例: "$2a$12$Kix...こんな感じの長い文字列"
// 2. ログイン時(パスワードチェック)
func CheckPassword(password string, hashed string) bool {
err := bcrypt.CompareHashAndPassword([]byte(hashed), []byte(password))
return err == nil // 正しい → true
}
// 使い方
if CheckPassword("入力されたパスワード", dbから取ったハッシュ) {
ログイン成功
}
| タイミング | 何が起こってる? |
|---|---|
| ユーザー登録時 | パスワード + 自動で作られたソルト → bcryptが全部混ぜてハッシュ → DBに保存 |
| ログイン時 | 入力されたパスワード + DBに保存されてるハッシュの中に入ってるソルト → 再度計算 → 一致するか比較! |
セキュリティ実装のチェックリスト
あなたのアプリケーションは安全ですか?今すぐチェックしましょう。
・パスワードは bcrypt か argon2id でハッシュ化してる?
(平文・MD5・SHA系は絶対使ってないか?)
・bcrypt.DefaultCost(12)以上にしてる?
(古いアプリケーションでコストが低いままになっていないか確認)
・ハッシュ化した値をそのままDBに保存してる?
(ソルトを別のカラムに保存するなど、余計な手間をかけていないか確認しましょう。また、bcryptはハッシュ値の中にソルトとコスト情報を含む)