web-dev-qa-db-ja.com

標準のJava 6で使用するパスワードベースの暗号化は何ですか?

Java 6?で使用するパスワードベースの暗号化方法はどれですか?可能な限り強力である必要がありますが、デフォルトのセキュリティポリシーファイルで動作します(ダウンロードする必要があるエクスポート制限付きのファイルではありません)別にインストールします)?

5
user12889

私の推奨:パスワードベースの暗号化の使用を避けるようにしてください (できる限り回避できる場合)。特に、パスワードベースの暗号化は実際には安全ではない傾向があります。問題は、ユーザーのパスワードが抵抗するのに十分なエントロピーを持つことはまれであることです辞書攻撃。したがって、 暗号化が必要な場合、おそらくパスワードベースの暗号化を使用したくないでしょう (代替手段がある場合)。

より良い解決策は、ユーザーにキーを与え、そのキーを使用して暗号化または復号化することです。

私の推奨に従わない場合:パスワードベースの暗号化を絶対に使用する必要がある場合、リスクをいくらか減らすためのいくつかの提案を次に示します。

  • PBKDF2 を使用して、パスワードからキーを取得します。鍵の導出プロセスに、たとえばユーザーのマシンで100ミリ秒かかるように、適切に多数の反復を選択します。これにより、ユーザーのパスフレーズで辞書検索を実行するのが少し難しくなります。ただし、リスクが排除されるわけではないため、ユーザーは非常に長いパスフレーズを選択するために余分な労力を費やす必要があります。

  • ユーザーが非常に長いパスフレーズを使用する可能性を高めるためにできる限りのことをしてください。最善の方法は、パスワードを自動的に生成することです。 80ビットのエントロピーを持つものを選択することをお勧めします。これをA-Za-z0-9(0または1との混同を避けるためにOまたはlではない)を使用するパスワードに変更すると、結果のパスフレーズは14文字になります。ユーザーは、このような長いパスフレーズに対処する必要がない場合がありますが、安全を確保するには、それを吸い取って対処する必要があります。

    ユーザーが独自のパスフレーズを選択できるようにすると、ほとんどの場合、品質の低いパスフレーズが選択されます。リスクに関する悲惨な警告を含めることをお勧めします。少なくとも20文字で、ランダムに作成できるパスフレーズを選択することをお勧めします。カットアンドペーストして使用できるサンプルパスフレーズを生成する小さなアプリを提供することもできます。

    どんなに努力しても、ユーザーが自分のパスフレーズを選択した場合、多くのユーザーはおそらく十分に安全でないものを選択するでしょう。問題は、暗号化には、Webアカウントのパスワードに使用するパスワードよりもかなり長く強力なパスフレーズが必要なことです。ほとんどのユーザーはおそらくこれを知らないでしょうし、とにかく長くて十分に強いパスフレーズを選択することの煩わしさは、多くのユーザーがそうすることを妨げ、彼らが安全に動作しない原因となるでしょう。

パスワードベースの暗号化が安全に使用するための頭痛の種であるという感覚を得ているなら、あなたの感覚は完全に正確です。

5
D.W.

最初に@ D.W。の回答を読んでください。それは良いアドバイスでいっぱいです。次に、パスワードベースの暗号化を引き続き行う場合は、次のことを考慮してください。

  • パスワードベースの暗号化とは、パスワードをキーに変換し、そのキーを対称暗号化に使用することです。
  • Javacanは、パスワードベースの暗号化を行うことができます。つまり、次に示すように、合理化されたAPIで2つのステップを実行します here 。ただし、パスワードハッシュメカニズムと暗号化アルゴリズムのsomeの組み合わせのみを許可し、特に、AESでは問題となることを許可しないと報告されています。
  • パスワードからキーへの変換を行ってから、コードの2つの別々のステップで暗号化を行うことを妨げるものはありません。

パスワードハッシュメカニズムはデータを「隠す」ことがないため、通常、暗号法や輸出規制の対象にはなりません。次に、コードに bcrypt の実装のみを含めることをお勧めします。 jBCrypt これはJavaで記述されており、簡単なライセンスでオープンソースであり、かなりコンパクトです(oneソースファイル)。その実装ではstringsを使用する必要があるため、コードを少し変更する必要がありますが、生のビットが必要です。したがって、次のようにします。

  • crypt_raw()メソッドを使用して、パスワードとソルトを192ビットのbcrypt出力に変換します。
  • これらの192ビットをSHA-512でハッシュします(Java 6にはSHA-512実装が含まれています)。これにより、512ビットが生成されます。
  • データのAES暗号化にこれらの512ビットを使用し、結果に [〜#〜] mac [〜#〜] を使用します(例:HMAC/SHA-256を使用し、Java 6)。詳細については、以下を参照してください。

(私は通常、説明されている理由でPBKDF2よりもbcryptを好みます there ですが、PBKDF2も悪くないので、本当にPBKDF2が必要な場合(またはコンプライアンス上の理由で必要な場合)、それを選択してください。)

重要:暗号化を適切に行い、MACを追加することは、驚くほど多くの方法で失敗する可能性があります。あなたは自分でそれをしないように暖かく励まされています。ただし、次のメソッドは安全である必要があります

  • 512ビットの「パスワード派生データ」があります。 4つの128ビットブロックに分割します。
  • CBCモードでAES-128を使用してデータを暗号化します。 CBCには 初期化ベクトル が必要です。これはランダムな16バイトの配列です。最初の128ビットブロック(SHA-512出力から)をキーとして使用し、2番目の128ビットブロックをIVとして使用します。また、PKCS#5パディングを使用します(入力データの長さが16の倍数ではない可能性があるため)。
  • 暗号化が完了したら、IVで構成される入力に対してHMAC/SHA-256を計算し、次に暗号化結果をこの順序で計算します。 HMACのキーは、SHA-512出力からの3番目の128ビットブロックです。
  • 「暗号化ファイル」には、bcryptのソルト(128ビット、別名16バイト)、AES/CBC暗号化の出力、およびHMAC出力(256ビット、別名32バイト)が含まれている必要があります。
  • 復号化の場合、ソルト(暗号化ファイルから)とパスワードを使用してbcryptを再計算し、SHA-512を適用して暗号化キー、IV、およびHMACのキーを取得します。 HMAC値を確認し、適切な場合はデータを復号化します。

そして、覚えておいてください:決して、決して[〜#〜]決して[〜#〜]再利用しない2つの暗号化インスタンスのソルト値(同じパスワードを使用するかどうか)。ファイルを暗号化するたびに、常にJava.security.SecureRandomを使用して新しいランダムソルトを生成します。

3
Thomas Pornin