web-dev-qa-db-ja.com

暗号鍵の生成に使用されるPBKDF2:長い共有秘密(パスワード)と反復回数

AS/400と別のコンピューター(おそらくWindowsを実行している)の間のプライベートデータを保護するために使用される対称暗号化(DES、3DES、AESの場合もあります)アルゴリズムのキーを生成するためにpbkdf2を使用したいと思います。

FreeBSDリポジトリからAS/400(iSeriesまたはPowerシステムとして別名)にpbkdf2 cソースコードを「移植」してきましたが、これは大したことではありません。

Windowsシステム(Visual Studio 2012を使用)でも同じコードをコンパイルしました(興味がある人のために、PBKDF2を実装するAPIがWindows 7およびWin2008R2に存在します:BCryptDeriveKeyPBKDF2())

Windowsでのパフォーマンスは十分に良いようです(Windowsマシンが執筆時点では「遅いマシン」ではないことは認めます:Asus R751L、Intel Core i7-4500U、16GB ram):パスワード= "abcd"、salt = "someソルト」(実際のアプリケーションで必要なランダム値の場合は64ビット以上を使用します)、ここで数回の反復カウント(c)の場合があります。

  • c = 1000 => 31ms(最適化されていません)、15ms(速度のために最適化されています)
  • c = 10000 => 320ms(最適化されていません)、94ms(速度のために最適化されています)
  • c = 100000 => 3280ms(最適化されていません)、880ms(速度のために最適化されています)

(参考までに、BCryptDeriveKeyPBKDF2()APIは、コンパイルしたバージョンよりも少し良い結果が得られますが、これは私の問題ではありません)

ここで問題となるのは、AS/400システムで得られる実行速度です。

  • c = 1000 => 12590ミリ秒(最適化されていません)、2946ミリ秒(最適化されていません)
  • c = 10000 => 125889ms(最適化されていません)、29452ms(最適化されています)
  • c = 100000 =>(試していない...)

私のAS/400はそれほど強力なシステムではありませんが、最適化されたバージョンでも本当に遅いです...

これまで、「c」(反復回数)パラメータはできるだけ高くする必要があることを読みました。2000年代の「c」の推奨最小値は1000でした。関係するシステムによると、許容可能なパフォーマンスとセキュリティの間でオフ。私の場合、c = 1000は、いくつかの理由で、私の意見ではすでに計算に時間がかかりすぎています。

  • アプリケーションの応答性、
  • 可能なDOS攻撃、
  • ...

今私は疑問に思っています:長くて複雑な共有秘密は、 "c"をできるだけ小さく保つための解決策になるでしょうかwithout "失う"あまりに "セキュリティ"しますか? (「c」の1000はすでに非常に遅いので、c = 100を使用したいと思います...)

「パスワードにn文字を追加することは、xの反復(c)の数を増やすことといくらか同等です。

ソルトのサイズを大きくすると(たとえば、64ビットではなく128ビット以上)、クラッカーの元のデータに戻るのが難しくなりますか?

2
ggo

AS/4 マシンの行には長​​い歴史があります。彼らは通常、PowerPC/POWERファミリーのCPUを使用しますが、最初のモデルは55 MHzでクロックされるCPUで始まりましたが、高速であるとは期待できません...これは、得られるひどいパフォーマンスを説明するかもしれません。あるいは、移植プロセスに微妙な問題があったのかもしれません。たとえば、アグレッシブなループのアンロールにより、関数コードがL1キャッシュを超える可能性があり、パフォーマンスが大幅に低下する可能性があります(このような場合、すでに50倍の速度低下が見られます)。

とにかく、PBKDF2の反復は、入力パスワードの比較的低いエントロピーを補償することを目的としています(パスワードはpasswordであるため、人間の脳に適合します) )。エントロピーが高くなるようにパスワードを調整できる場合は、反復回数が少ないセキュリティが得られます。

(エントロピーは長さではないことに注意してください。エントロピーはrandomnessです。)

1
Tom Leek

名前が示すように、パスワードベースのキー導出関数(PBKDF)を使用して、暗号化キーパスワードからを取得します。通常、パスワードは短く(エントロピーは低く)、ブルートフォースは妥当な時間内に実行できます。 PBKDFは、推測ごとに多くの時間を使用して、総当たり攻撃を阻止します。

キーを制御しているようです(ユーザーがパスワードを選択しているのではありません)。この場合、PBKDFなしで秘密キーを直接使用しても安全です。あなたのアルゴリズムが32バイトのキーが必要です。このキーはエントロピーが高く、妥当な時間内にブルートフォースすることはできません。これらの32バイトは英数字のテキストではなく、ランダムな32バイトの配列のようなものであることに注意してください。

編集:

あなたのコメントから、私はそれが確かにパスワードであることを理解しています。そのため、PBKDFが正しい方法です。実際には、長いパスワード(エントロピーの高いパスワード)を使用すると、コスト要因を減らすことができますが、ユーザーがそのような強力なパスワードを確実に選択できるようにするのは困難です。 Password2014既知のことわざのようなパスワードはほとんどのルールを満たしているため、通常のルールは適切な指標ではありませんが、強力なパスワードではありません。 1つの方法は、アプリケーションが独自に強力なパスワードを生成し、この形式のパスワードのみを受け入れることです。

0
martinstoeckli

「パスワードにn文字を追加することは、xの反復(c)の数を増やすことと多少等価です。

パスワードの強度と反復回数のトレードオフはid:logです。ここで、idはIDで、logは対数です。したがって、1000回の反復は、約10ビットの追加のパスワード強度を意味します。 100万回の反復は、20ビットの追加を意味します。ただし、真にランダムなパスワードの場合のみ、パスワードの文字数とビット単位の強度の間に強い1対1の関係はありません。

PBKDFは、さもなければさらに悪化する問題に対する非常に悪い解決策です。強度に対数的に追加するだけです。通常、PBDKFはこれほどの全体的な負荷は発生しません。大規模なサービスであっても、特定の瞬間にログインするユーザーの数は、総ユーザー数に比べて少ないためです。しかし、あなたの場合、負荷の問題PBDKFが明らかに当てはまります。

0
user10008