web-dev-qa-db-ja.com

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

フラグメントに分割されたファイルdata.txtがあります。元のファイルがdata.txtで作成されるように、ファイルのフラグメントを適切に組み合わせる必要があります。フラグメントの名前には階層がないため、これを行う手順がわかりません。しかし、私はmd5sumファイルdata.txt(フラグメントをリストしています)を持っています。 md5sumファイルを使用して、ファイル全体をフラグメントから復元するにはどうすればよいですか?

1
lukassz
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

またはmd5sum の代わりに md5 GNUツールがある場合。

1
thrig

一部のチェックサムを知っていても全体のチェックサムを計算するのに役立たないため、正しい順列が見つかるまで、考えられるすべての順列のチェックサムを計算する必要があります。 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の hashlib は、ハッシュ関数の内部状態をコピーするための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)

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

フラグメントはいくつありますか?フラグメントのすべての順列を(または正しいフラグメントにヒットするまで)試行する必要があるように思われるため、比較的少量のフラグメントの問題を解決しても、大量の作業が発生します。

0
StackUnderflow