web-dev-qa-db-ja.com

PBKDF2で、最適なハッシュサイズ(バイト単位)はいくつですか?塩のサイズはどうですか?

PBKDF2でハッシュを作成する場合、開発者はハッシュのサイズを選択できます。常に長い方が良いですか?また、ランダムな塩のサイズはどうですか?ハッシュと同じサイズにする必要がありますか?

編集:特にパスワードのハッシュで。

27
blesh

ハッシュ関数については、最も効率的なプラットフォームタイプ(1秒あたりおよび1ドルあたりでより多くのハッシュ計算を生成するプラットフォーム)が使用するマシン(つまり、PC)である関数を使用します。これは、あなたが攻撃者との武器競争にあり、攻撃者が他の種類のハードウェアを購入してEdge(GPUなど)を手に入れることができるためです。 GPUは32ビット演算では非常に優れていますが、64ビット演算では得意ではありませんが、PC(64ビットモード)は後者で非常に高速です。

したがって、64ビット算術演算で実行されるハッシュ関数を使用します。これはSHA-512を指しています。

PBKDF2は キー導出関数 です:構成可能なサイズの出力を生成します。パスワードハッシュの場合、一般的なプリイメージ攻撃を阻止する(つまり、一致するものが見つかるまでランダムなパスワードを試す)のに十分な大きさのサイズにする必要があるため、たとえば、少なくとも80ビットの出力が必要になります。セキュリティを不注意に対してより説得力のあるものにするためだけに、そして美学のためにも、次の2のべき乗に進んでください:a128ビット出力。それを超えることは役に立ちません。

ソルトはunique-可能な限り一意である必要があります。一意のソルト値を達成する簡単な方法は、 暗号学的に強いPRNG でソルトを生成することです。ソルト値を再利用する確率は、これらのランダムソルトが十分に大きく、「十分に大きい」場合、無視できるほど低くなります。 "は" 128ビット "を意味します。したがって、ランダム128ビットソルトを使用します。

個人的には、パスワードハッシュにはPBKDF2よりも bcryptを推奨 を使用します。

24
Thomas Pornin

PBKDF2規格によると、ソルトの最小推奨サイズは64ビットですが、安全マージンを確保するために個人的には128ビット以上をお勧めします。ソルトのサイズは、選択したハッシュに依存しません。

セキュリティに関する限り、派生キーの長さ少なくともを256ビット以上のソルトの出力と同じサイズに選択することをお勧めします。とにかく、256ビット未満のハッシュサイズは、最新のハッシュ関数のセキュリティ境界を下回っています。

そのサイズのキーを処理できないブロック暗号のキーを使用している場合を除き、ハッシュ関数の出力長よりも短い派生キーの長さを選択しても意味がありません。

最適なセキュリティの観点から、PRFとしてSHA-512、512ビットの派生キー、128ビットのソルト、および状況に応じて可能な限りの反復を推奨します。

11
Polynomial

選択したプラットフォームが.NETの場合、その Rfc2898DeriveBytes クラスに特化したOWASP記事があります。特に注意(鉱山を強調):

Rfc2898DeriveBytesの組み込み.NET実装により、ユーザーは1つの擬似ランダム関数-HMAC with SHA-1に制限されます。これは今日のほとんどのシナリオで許容可能ですが、将来的には、より複雑なハッシュ関数が必要になる可能性があります。

パスワードの保存にPBKDF2を使用すると、基本ハッシュ関数のサイズより多くのビットを出力することはできません。 PBKDF2-SHA1の場合、これは160ビットまたは20バイトです。より多くのビットを出力してもハッシュの安全性は向上しませんが、攻撃者にはコストをかけずに、ディフェンダーに多くの時間を費やします。攻撃者は、最初のハッシュ関数サイズの出力を比較するだけで、PBKDF2出力のリセットを生成する時間を節約できます。

また、他の回答のガイダンスに従って調整したコードサンプルもあります。

public static string Hash(string str)
{
    // Generate the hash, with an automatic 16 byte salt
    using (var rfc2898DeriveBytes = new Rfc2898DeriveBytes(str, 16))
    {
        rfc2898DeriveBytes .IterationCount = 10000 // or whatever you can afford
        byte[] hash = rfc2898DeriveBytes.GetBytes(20);
        byte[] salt = rfc2898DeriveBytes.Salt;
        return Convert.ToBase64String(salt) + "|" + Convert.ToBase64String(hash);
    }
}
4
Ohad Schneider