0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【技術メモ】Go言語でbcryptパスワードハッシュ化の実装方法 | セキュアな認証システム構築

Posted at

👉 セキュアなWeb/APIサーバー実装、ユーザー認証システム、パスワード管理に必須のbcryptハッシュ化メモ。Golang、bcrypt、パスワードハッシュ、認証、セキュリティ対策のまとめ。

bcrypt主要関数メモ

⚡ GenerateFromPassword

func GenerateFromPassword(password []byte, cost int) ([]byte, error)
  • 入力:
    • password []byte → 平文パスワード
    • cost int → 計算コスト (4-31)
  • 出力:
    • ハッシュ値 + エラー
  • メモ:
    • パスワード長は最大72バイト
    • 低コスト指定時は自動的に10に引き上げ

⚡ CompareHashAndPassword

func CompareHashAndPassword(hashedPassword, password []byte) error
  • 入力:
    • hashedPassword []byte → 保存済みハッシュ
    • password []byte → 検証したいパスワード
  • 出力:
    • 一致時 → nil
    • 不一致時 → エラー

⚡ コスト定数

const (
    MinCost     int = 4  // 最小(非推奨)
    MaxCost     int = 31 // 最大(重い)
    DefaultCost int = 10 // 標準
)

サンプルコード集

✅ 最小限のハッシュ化実装

// パスワードハッシュ化(最小実装)
password := []byte("super-secret")
hash, err := bcrypt.GenerateFromPassword(password, bcrypt.DefaultCost)
// → "$2a$10$..."

✅ パスワード検証(ログイン処理など)

// 検証処理(最小実装)
err := bcrypt.CompareHashAndPassword(hash, []byte("super-secret")) 
if err == nil {
    // 認証成功
} else {
    // 認証失敗
}

✅ ハイセキュリティ設定

// セキュリティ重視(処理は遅くなる)
hash, err := bcrypt.GenerateFromPassword(password, 14)

✅ 便利ユーティリティ関数

// 文字列 → ハッシュ文字列 変換
func HashPassword(password string) (string, error) {
    bytes, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
    return string(bytes), err
}

// パスワード検証(true/false形式)
func CheckPasswordHash(password, hash string) bool {
    err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password))
    return err == nil
}

実装例(認証システム)

👤 ユーザー登録処理

func RegisterUser(email, password string) error {
    // ハッシュ生成
    hashedPW, err := HashPassword(password)
    if err != nil {
        return fmt.Errorf("パスワードハッシュ化エラー: %w", err)
    }
    
    // DBに保存
    _, err = db.Exec(
        "INSERT INTO users (email, password_hash, created_at) VALUES (?, ?, NOW())", 
        email, hashedPW
    )
    return err
}

🔐 ログイン認証処理

func LoginUser(email, password string) (bool, error) {
    var hashedPW string
    
    // ハッシュ取得
    err := db.QueryRow(
        "SELECT password_hash FROM users WHERE email = ?", 
        email
    ).Scan(&hashedPW)
    
    if err != nil {
        return false, err // ユーザーなし or DBエラー
    }
    
    // パスワード検証
    return CheckPasswordHash(password, hashedPW), nil
}

bcryptハッシュ構造

$2a$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy
\__/\__/\____________________/\_____________________________/
 |   |           |                          |
 |   |           |                          +-- 実際のハッシュ値
 |   |           |
 |   |           +-- ソルト (16バイト)
 |   |
 |   +-- コスト (10)
 |
 +-- ハッシュ種別 ($2a$ = bcrypt)

重要メモ

  • DB設計: VARCHAR(60)以上で保存すること
  • 同一パスワード: 毎回異なるハッシュ生成(自動ソルト)
  • コスト増加: +1ごとにハッシュ時間約2倍に増加
  • セキュリティ: 最低コスト10以上を推奨(OWASP基準)
  • メモリ使用: 他ハッシュ関数より多め(考慮すべき)
  • 特徴: GPUによる総当たり攻撃に強い設計
  • 注意: Webサーバーではレスポンス時間への影響を考慮

よくあるコード例

JWT認証と組み合わせ

// ユーザー認証後にJWTトークン発行
func GenerateJWT(userID int) (string, error) {
    // ここにJWT生成コード
}

func LoginHandler(w http.ResponseWriter, r *http.Request) {
    // 認証処理
    success, _ := LoginUser(email, password)
    if success {
        token, _ := GenerateJWT(userID)
        // tokenをクライアントに返す
    }
}

パスワードリセット

func ResetPassword(userID int, newPassword string) error {
    hashedPW, _ := HashPassword(newPassword)
    _, err := db.Exec("UPDATE users SET password_hash = ? WHERE id = ?", 
        hashedPW, userID)
    return err
}

エラーハンドリング

// よくあるエラーパターン
switch {
case errors.Is(err, bcrypt.ErrMismatchedHashAndPassword):
    // パスワード不一致
case errors.Is(err, bcrypt.ErrHashTooShort):
    // ハッシュ形式不正
default:
    // その他エラー
}

参考情報

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?