14

大きなファイルで 1 つの MD5 チェックサムを計算する場合、さまざまな MD5 値を 1 つの値に結合するために一般的に使用される手法は何ですか? それらを一緒に追加するだけですか?これを行う特定の言語、ライブラリ、または API にはあまり興味がありません。むしろ、その背後にある技術に興味があります。誰かがそれがどのように行われるか説明できますか?

疑似コードで次のアルゴリズムがあるとします。

MD5Digest X
for each file segment F
   MD5Digest Y = CalculateMD5(F)
   Combine(X,Y)

しかし、正確には何をCombineしますか?2 つの MD5 ダイジェストを一緒に追加しますか、それとも何ですか?

4

7 に答える 7

16

大きすぎてメモリに収まらないファイルの MD5 値を計算するには

そのことを念頭に置いて、2 つの MD5 ハッシュを「結合」したくはありません。どのMD5 実装でも、現在のチェックサム状態を保持するオブジェクトがあります。したがって、いつでも MD5 チェックサムを抽出できます。これは、同じ始まりを共有する 2 つのファイルをハッシュする場合に非常に便利です。大きなファイルの場合、データをフィードし続けるだけです。状態が記憶されているため、ファイルを一度にハッシュしてもブロック単位でも違いはありません。どちらの場合も、同じハッシュが得られます。

于 2010-02-06T18:55:52.777 に答える
6

MD5 は反復アルゴリズムです。大量の小さな MD5 を計算してから、それらを何らかの方法で組み合わせる必要はありません。ファイルの小さなチャンクを読み取り、ダイジェストに追加するだけなので、一度にファイル全体をメモリに保持する必要はありません。これがJavaの実装です。

FileInputStream f = new FileInputStream(new File("bigFile.txt"));
MessageDigest digest = MessageDigest.getInstance("md5");
byte[] buffer = new byte[8192];
int len = 0;
while (-1 != (len = f.read(buffer))) {
   digest.update(buffer,0,len);
}
byte[] md5hash = digest.digest();

出来上がり。一度にファイル全体をメモリに保持することなく、ファイル全体の MD5 を取得できます。

何らかの理由で、ファイルのサブセクションの MD5 ハッシュが必要な場合 (これは、低帯域幅接続を介して転送される大きなファイルの中間チェックを行うのに役立つ場合があります)、複製することでそれらを取得できることに注意してください。そのように、いつでもダイジェスト オブジェクト

byte[] interimHash = ((MessageDigest)digest.clone()).digest();

これは実際のダイジェスト オブジェクトには影響しないため、引き続き MD5 ハッシュ全体を操作できます。

また、MD5 は暗号化目的 (信頼できないソースからのファイルの信頼性の検証など) では古いハッシュであり、ほとんどの状況では SHA-1 などのより適切なものに置き換える必要があることにも注意してください。2 つの信頼できるソース間のファイルの整合性を検証するなど、暗号化以外の目的では、MD5 で十分です。

于 2010-02-06T18:56:32.790 に答える
2

MD5 アルゴリズムは任意の長さの入力を受け取るため、この質問はあまり意味がありません。まともなライブラリには関数が必要なので、メッセージはブロックに分割され、順次ハッシュされ、処理されるブロックは前の結果のハッシュのみに依存するため、一度にメッセージ全体を追加する必要はありません。ループ。

ウィキペディアの記事の疑似コードは、アルゴリズムがどのように機能するかの概要を示しているはずです。

于 2010-02-06T18:53:29.220 に答える
2

openSSL ライブラリを使用すると、進行中のハッシュ (sha1/md5) にデータのブロックを追加できます。すべてのデータの追加が完了したら、Finalメソッドを呼び出すと、最終的なハッシュが出力されます。

個々のブロックごとに md5 を計算して追加するのではなく、openssl ライブラリから進行中のハッシュ メソッドにデータを追加します。これにより、入力データ サイズに制限のない、すべての個々のデータ ブロックの md5 ハッシュが得られます。

http://www.openssl.org/docs/crypto/md5.html#

于 2010-02-06T18:50:23.397 に答える
2

AndiDog の回答の Python 2.7 の例。ファイル 123.txt には複数の行があります。

>>> import hashlib
>>> md5_A, md5_B, md5_C = hashlib.md5(), hashlib.md5(), hashlib.md5()
>>> with open('123.txt', 'r') as f_r:
...     md5_A.update(f_r.read()) # read whole contents
... 
>>> with open('123.txt', 'r') as f_r:
...     for line in f_r: # read file line by line
...         md5_B.update(line)
... 
>>> with open('123.txt', 'r') as f_r:
...     while True: # read file chunk by chunk
...         chunk = f_r.read(10)
...         if not chunk: break
...         md5_C.update(chunk)
... 
>>> md5_A.hexdigest()
'5976ddfa19bc2e1669ac3bd836101f58'
>>> md5_B.hexdigest()
'5976ddfa19bc2e1669ac3bd836101f58'
>>> md5_C.hexdigest()
'5976ddfa19bc2e1669ac3bd836101f58'

メモリに収まらない大きなファイルの場合、行単位またはチャンク単位で読み取ることができます。この MD5 の 1 つの使用法は、diff コマンドが失敗したときに 2 つの大きなファイルを比較することです。

于 2014-11-05T22:34:57.947 に答える
1

ハッシュを結合する C# の方法を次に示します。ユーザーコードを簡素化するために拡張メソッドを作成しましょう。

public static class MD5Append
{
    public static int Append(this MD5 md5, byte[] data)
    {
        return md5.TransformBlock(data, 0, data.Length, data, 0);
    }

    public static void AppendFinal(this MD5 md5, byte[] data)
    {
        md5.TransformFinalBlock(data, 0, data.Length);
    }
}

使用法:

   using (var md5 = MD5CryptoServiceProvider.Create("MD5"))
        {
            md5.Initialize();

            var abcBytes = Encoding.Unicode.GetBytes("abc");
            md5.Append(abcBytes);
            md5.AppendFinal(abcBytes);

            var h1 = md5.Hash;

            md5.Initialize(); // mandatory
            var h2= md5.ComputeHash(Encoding.Unicode.GetBytes("abcabc"));

            Console.WriteLine(Convert.ToBase64String(h1));
            Console.WriteLine(Convert.ToBase64String(h2));
        }

h1 と h2 は同じです。それでおしまい。

于 2013-11-01T18:47:56.357 に答える
1

ほとんどのダイジェスト計算の実装では、データを小さなブロックでフィードできます。結果が入力全体の MD5 と等しくなるように、複数の MD5 ダイジェストを結合することはできません。MD5 はパディングを行い、最終段階で処理されたバイト数を使用するため、最終ダイジェスト値から元のエンジン状態を回復できなくなります。

于 2010-02-06T18:55:56.910 に答える