メインコンテンツへスキップ

VillageSQL is a drop-in replacement for MySQL with extensions.

All examples on this page work on VillageSQL. Install Now →
MySQL には MD5() と SHA2() があります。開発者はパスワードをハッシュするときにこれらに手を伸ばします。それは間違いです。これらの関数は高速になるように設計されていますが、それはパスワードの保存にとってはまさに誤った性質です。

高速なハッシュがパスワードに不向きな理由

MD5 や SHA-256 のような暗号学的ハッシュ関数は速度に最適化されています。現代の GPU は毎秒数十億の SHA-256 ハッシュを計算できます。チェックサムやデータ整合性にはそれが役立ちます。パスワードにとっては、ハッシュ化されたパスワードのテーブルを入手した攻撃者が数時間でブルートフォースできることを意味します。 パスワードハッシュのアルゴリズム (bcrypt、Argon2、PBKDF2) は意図的に遅く作られています。1 つのパスワードの検証に数十ミリ秒かかるように設計されており、ログインには問題ありませんが、ブルートフォース攻撃は現実的でなくなります。

標準的な答え: アプリケーションコードでハッシュする

ほとんどの MySQL アプリケーションは、アプリケーション層でハッシュすることでこれを正しく処理しています。PHP、Python、Node.js、あるいはアプリを動かしている言語が何であれ、その bcrypt を使います。データベースはハッシュ化された値しか見ません。 これは機能しますが、分断を生みます。ハッシュのロジックはアプリケーションコードにあり、データはデータベースにあります。マイグレーション、一括操作、データのインポートは、正しくハッシュするためにアプリケーションを経由しなければならないか、複数のコードベースにハッシュのロジックを複製しなければなりません。

VillageSQL の場合: SQL で直接 PBKDF2

VillageSQL の vsql_crypto 拡張機能は crypt() と gen_salt() を追加します。PostgreSQL の pgcrypto をモデルにした、PBKDF2 ベースのパスワードハッシュ API です。アプリケーションコードを経由せずに、SQL でパスワードをハッシュし検証できます。

パスワードの保存

gen_salt は PBKDF2 ファミリーのみを扱います。pbkdf2-sha256 と pbkdf2-sha512、および短いエイリアスの pbkdf2、sha256、sha512 です。pgcrypto の bf (bcrypt)、md5、des の型はサポートされていません。gen_salt はそれらの名前に対して NULL を返します。

パスワードの検証

crypt() は保存されたハッシュからソルトとパラメータを自動的に取り出します。保存されたハッシュを 2 番目の引数として渡します。

反復回数の選択

反復回数は、ハッシュの計算にかかる時間を制御します。反復が多いほど遅くなり、ブルートフォースが難しくなりますが、ログインも遅くなります。 10,000 から始め、ハードウェアが許す限り増やしてください。ログインエンドポイントは 100ms を許容できます。数十億回の推測を試みる攻撃者には許容できません。

SQL でハッシュすべきときとアプリケーションコードでハッシュすべきとき

SQL でのハッシュが常に正しい選択とは限りません。次の場合に使ってください。
  • アプリを経由するのが現実的でない一括挿入やマイグレーションを行っている
  • ハッシュのロジックをデータベース層に集中させたい
  • SQL 駆動の管理ツールやシードスクリプトを構築している
次の場合はアプリケーションコードでハッシュしてください。
  • アプリケーションフレームワークに、十分にテストされた bcrypt/Argon2 ライブラリがすでにある
  • 暗号のエコシステムが成熟した言語を使っている (ほとんどはそうです)
  • スキーママイグレーションなしでハッシュアルゴリズムを入れ替えたい
どちらのアプローチも安全なハッシュを生成します。重要なのは、素の SHA2 ではなく、遅いアルゴリズム (PBKDF2、bcrypt、または Argon2) を使うことです。

よくある質問

PBKDF2 は bcrypt と同じくらい強力ですか?

同等の反復回数では、bcrypt がメモリハードである (GPU で並列化しにくい) ため、わずかに優位です。高い反復回数 (100,000 以上) の PBKDF2 は今も強力で、広く導入されています。この差は敵対的なシナリオでは重要ですが、どちらも SHA2 よりはるかに優れています。

既存の SHA2 ハッシュを移行できますか?

はい。needs_rehash フラグを追加してください。ログインに成功したときに、ハッシュが古い SHA2 形式かどうかを確認し、crypt() で再ハッシュします。すべてのアクティブユーザーがログインしたら、古いハッシュを削除してください。

PostgreSQL の既存の bcrypt ハッシュを移行できますか?

直接はできません。crypt() は PBKDF2 形式ではないソルトやハッシュに対して NULL を返すため、pgcrypto の bcrypt ハッシュはここでは検証できません。既存の列にそのまま保持し、上の SHA2 ハッシュと同じ方法で、各ユーザーの次回のログイン成功時に再ハッシュしてください。PostgreSQL から MySQL への移行ガイドに拡張機能の完全な対応表があります。

保存されたハッシュにはソルトが含まれていますか?

はい。crypt() の出力は、アルゴリズム、反復回数、ソルト、ハッシュを 1 つの文字列にエンコードしています。ソルトを別途管理する必要はありません。

トラブルシューティング

関連項目