md5sumに基づいて複数のファイルをマージする

md5sumに基づいて複数のファイルをマージする

複数の部分に分割されたdata.txtファイルがあります。元のファイルdata.txtを作成するには、ファイルの断片を正しく結合する必要があります。フラグメント名に階層がないため、どのプログラムがこれを行うのかわかりません。ただし、md5sumdata.txtファイル(フラグメントリストがリストされています)があります。このmd5sumファイルを使用してフラグメントからファイル全体を回復するにはどうすればよいですか?

答え1

perl -MAlgorithm::Combinatorics=permutations \
  -le '$i=permutations(\@ARGV); while ($p=$i->next) { $n++; print "combo$n @$p" }' frag1 frag2 frag3 frag4 \
| while read out a b c d; do cat $a $b $c $d > $out; md5 $out; done

あるいは、GNUツールがあれば、代わりmd5sumにそれを行うことができます。md5

答え2

一部はありますか?フラグメントのすべての順列を試す必要があるように聞こえるので(または正しいフラグメントが見つかるまで)、比較的少数のフラグメントで問題を解決すると、多くのタスクが発生します。

答え3

一部のチェックサムを知ることはチェックサム全体を計算するのに役立ちません。正しい順列が見つかるまで、可能なすべての順列のチェックサムを計算する必要があります。お持ちの場合N部分があります。N! (継承N)順列、可能性が同じなら処理しなければなりません。N正しいものが見つかるまで平均!/2です。

プレフィックスが同じ複数の文字列のチェックサムを計算する必要がある場合は、MD5関数の内部状態を保存して時間を節約できます。たとえば、3つの部分(X、Y、Z)に対してMD5(X + Y + Z)、MD5(X + Z + Y)、MD5(Y + X + Z)、MD5(Y + Z + X)、 MD5(Z+X+Y) および MD5(Z+Y+X)。 MD5(X,…) 計算を開始すると、状態をコピーしてサフィックス Y+Z および Z+Y 計算を完了します。ただし、出力ではなく内部状態が必要であり、ほとんどのツールは内部状態へのアクセスを許可しません。

Pythonハッシュライブラリcopyハッシュ関数の内部状態をコピーする方法を提供します。それも列挙順列のための反復子標準ライブラリにあります。

#!/usr/bin/env python2
import hashlib, itertools, sys

def look_for_permutation(goal, filenames):
    n = len(filenames)
    files = map(open, filenames)
    previous = map(lambda _: None, filenames)
    states = [hashlib.md5()] + [None] * (n-2)
    for current in itertools.permutations(files):
        i = 0
        while current[i] == previous[i]:
            i += 1
        state = states[i].copy()
        for f in current[i:n-2]:
            state.update(f.read())
            i += 1
            states[i] = state.copy()
            f.seek(0)
        state.update(current[n-2].read())
        current[n-2].seek(0)
        state.update(current[n-1].read())
        if state.hexdigest() == goal:
            return current
        current[n-1].seek(0)
        previous = current
    return None

if __name__ == '__main__':
    result = look_for_permutation(sys.argv[1], sys.argv[2:])
    if result:
        for f in result: print f.name
        sys.exit(0)
    else:
        sys.exit(1)

スクリプトはハッシュ計算を最適化しますが、ファイルの内容を繰り返し読み込みます。ファイルの内容がメモリに収まる場合は、ファイルを一度にロードして作業を高速化できます。

関連情報