36

Java、特にMD5およびSHA-2 512(SHA512)または256のハッシュアルゴリズムの最良かつ最速の実装を知りたい。引数として文字列を取得し、結果としてハッシュを返す関数が必要です。ありがとう。

編集:これは、各URLを一意のハッシュにマッピングするためのものです。MD5はこの分野ではそれほど信頼性が高くないため、SHA-2アルゴリズムの最適で最速の実装を見つけることに関心があります。SHA-2でさえいくつかのURLに対して同じハッシュを生成する可能性があることは知っていますが、私はそれで生きることができます。

4

6 に答える 6

53

まず最初に、速度は過大評価されています。特定のアルゴリズムが「遅すぎる」と宣言する前に、対策を講じる必要があります。ほとんどの場合、ハッシュ関数の速度に大きな違いはありません。セキュリティに不安がある場合は、まず十分に安全なハッシュ関数を選択してから、パフォーマンスのみを気にしてください。

さらに、「文字列」をハッシュしたい。JavaStringは、内部的には、charUnicode コード ポイント (実際には、UTF-16 を使用してコード ポイントをエンコードする Unicode 16 ビット コード ユニット) を表す値の配列からのチャンクです。ハッシュ関数は、一連のビットまたはバイトを入力として受け取ります。str.getBytes("UTF-8")したがって、文字列をバイトの集まりとして取得するなど、変換手順を実行する必要があります。ハッシュ自体と比較すると、変換ステップには無視できないコストがかかる可能性があります。

注: URL エンコーディングに注意してください。%URL では、一部のバイトを「 」記号で始まるシーケンスに置き換えることができます。これは印刷できない文字をサポートするためのものですが、「標準」文字にも使用できます (たとえば、' a' を ' 'に置き換え%61ます)。これは、(あるString.equals()意味で) 異なる 2 つの文字列が、実際には同じ URL を表している可能性があることを意味します (URL 処理に関する限り)。状況によっては、これが問題になる場合とそうでない場合があります。

最初に、Java のMessageDigestAPI を標準の (インストール済みの) JCE プロバイダー (つまりMessageDigest.getInstance("SHA-256")、 を呼び出します) で使用してみて、結果を評価してください。理論的には、JCE は「ネイティブ」コード (C またはアセンブリで記述) を使用して呼び出しを実装にマップすることができます。これは、Java で得られるものよりも高速です。

そうは言っても…

sphlibは、C および Java による、多くの暗号化ハッシュ関数のオープンソース実装です。コードは速度のために最適化されており、実際には、Java バージョンは Sun/Oracle の標準 JRE が提供するものよりも高速であることが判明しました。前のリンクが失敗した場合に備えて、このリンクを使用してください(現在のように、メインのホスト サーバーがメンテナンスのためにダウンしている場合があります) (警告: 10 MB のダウンロード)。アーカイブには、SHA-2 および今後の SHA-3 の 14 の「第 2 ラウンド」候補について、いくつかのプラットフォームで測定されたパフォーマンス数値を示すレポート (2010 年の第 2 回 SHA-3 候補会議で発表されたもの) も含まれています。

しかし、実際には現場でのベンチマークを作成する必要があります。たとえば、L1 キャッシュへの影響はパフォーマンスに劇的な影響を与える可能性があり、関数コードを取得して分離して実行するだけでは正確に予測できません。

于 2011-03-28T12:33:40.660 に答える
21

編集:私は当初、「最速のハッシュアルゴリズム」とは何かという質問を読みましたが、「各アルゴリズムの最速の実装」であることが明確になりました。これは有効な質問であり、他の人はより高速な実装を指摘しています。ただし、大量のデータを短時間でハッシュしない限り、それほど重要ではありません。通常、標準の JCE で提供されているもの以外のものを使用するのに、時間と複雑さを費やす価値があるとは思えません。

URLアドレスの場合、最新のハードウェアで1秒あたり100万回以上のSHA-256でハッシュする必要があり、より高速なものが必要になります。ほとんどのアプリケーションが 1 秒あたり 1,000 を超える (1 日あたり 8,600 万を超える) 必要があるとは想像できません。つまり、ハッシュに費やされる全体の CPU 時間は 1% をはるかに下回ることになります。したがって、無限に高速なハッシュ アルゴリズムを使用したとしても、全体的なパフォーマンスを最大で 1% しか改善できません。

元の回答:最高と最速の両方を得ることは、互いに矛盾しています。より良いハッシュは一般的に遅くなります。本当に速度が必要で、セキュリティがそれほど重要でない場合は、MD5 を使用してください。最高のセキュリティが必要な場合は、SHA-256 または SHA-512 を使用してください。あなたはそれを何に使用しているかについて言及していないので、どちらかをお勧めするのは難しいです. とにかく、最新のハードウェアでのほとんどのユースケースで十分に高速であるため、SHA-256 を使用するのがおそらく最も安全です。方法は次のとおりです。

String input = "your string";
MessageDigest digest = MessageDigest.getInstance("SHA-256");
digest.update(input.getBytes("UTF-8"));
byte[] hash = digest.digest();

パスワードのハッシュ化など、セキュリティ目的でこれを使用している場合は、ダイジェストにもソルトを追加する必要があります。ハッシュから印刷可能な文字列が必要な場合は、それを 16 進数として文字列にエンコードできます。

static char[] HEX_CHARS = "0123456789ABCDEF".toCharArray();

StringBuilder sb = new StringBuilder(hash.length * 2);
for (byte b : hash) {
    sb.append(HEX_CHARS[(b & 0xF0) >> 4]);
    sb.append(HEX_CHARS[b & 0x0F]);
}
String hex = sb.toString();
于 2011-03-26T23:28:47.090 に答える
2

これらをチェックしてください:SHA/MD5の例がたくさん

また: 同じスレッドから:高速MD5

文字列ハッシュ=MD5.asHex(MD5.getHash(new File(filename)));

于 2011-03-26T23:24:45.403 に答える
2

考慮すべきもう 1 つのことは、MD4 の使用です。MD5 ほど安全ではありませんが、さらに高速に計算されます。XP までの Windows では、MD4 でパスワードを保存および交換していました。このプラットフォームに認証サービスを提供できるため、このハッシュを使用します。

于 2011-03-27T00:43:59.000 に答える