web-dev-qa-db-ja.com

ログイン:パスワードハッシュと正常な復号化

パスワードベースのログインでのパスワード処理に一方向関数(BCryptなど)を使用することは、一般的なアプローチです。

アプリケーションがユーザーのパスワードから導出されたキーを使用して秘密キーを暗号化する場合、ログイン時に成功した復号化に依存しても安全ですか?

例:

  • 登録(クライアント側で実行されるすべての手順):

    1. ユーザーのパスワードからキー(A)を取得します(例:PBKDF2を10万回の反復で使用)。
    2. キーAを使用して、ユーザーの秘密キーを暗号化します(GCMモードのAESなど、認証された暗号化を使用)。
    3. 必要な情報をユーザーのデータベースレコードに保存します(暗号文、ソルトなど)。
  • ログイン(クライアント側で実行されるすべての手順):

    1. ユーザー名でユーザーのデータベースレコードをロードします。
    2. ユーザーのパスワードからキー(B)を取得します(登録時に使用したのと同じ方法を使用)。
    3. キーBを使用してユーザーの秘密キーを復号化してみます。
2
Ratlos

はい、これは実行可能なアプローチですwhen指定したように、認証された暗号化を使用します。暗号化されたデータの認証タグは、保存されたパスワードハッシュに似ており、GCMはメッセージの偽造を防ぐように特別に設計されています(つまり、秘密鍵にアクセスせずに構築された有効なタグ)。

実際、GMACはGCMモードのバリアントであり、データを暗号化しないように設計されていますが、一部のデータに対して共有キーで署名を提供するためにjustを使用しています。

これは、認証されていない暗号では行わないでください。「正しい」復号化を検出するためにパディングが使用されている場合でも、これにより、(不正なキーであるにもかかわらず、正しいパディング。

これはすべて言われていますが、これはgoodの考えではないと思います。これは、標準のパスワードストレージスキームよりも実装エラーが発生しやすいためです。このスキームを攻撃することは、十分に研究された認証メカニズムであるユーザーパスワードの別のPBKDF2ハッシュを攻撃することと同じくらい簡単/困難です。 2つのPBKDF2ハッシュの計算でCPU時間を心配している場合は、以下を実行できます。

  1. 対称キーを導出するためにkey = PBKDF2(Password, Salt, N)を計算します。
  2. pwhash = PBKDF2(Password, Salt, N+1)を計算して、保存されているパスワードハッシュを導出します。 (これは、上記の元のハッシュで1つの余分なラウンドのみで実行できます。)

PBKDF2(Password, Salt, N+1)PBKDF2(Password, Salt, N)に反転することは、使用するハッシュ関数でHMACを反転することと同じです。

上記のスキームは、Lastpassが認証とパスワードボールトの復号化に使用するスキームです。 (pwhashのみがサーバーに送信されるため、パスワードボールトのキーをそこから回復することはできません。)

4
David