7

既知のハッシュダイジェストからハッシュを続行できるアルゴリズムはありますか?たとえば、クライアントがファイルのチャンクをServerAにmd5アップロードし、アップロードされたコンテンツの合計を取得してから、クライアントが残りのファイルチャンクをServerBにアップロードし、md5内部の状態をServerBに転送して、ハッシュを終了できますか?

何年も前にcomp.lang.pythonで見つけたmd5に基づくクールなブラックマジックハックがありましたが、それはまたctypesはの特定のバージョンに使用されているため、さまざまなPythonインタープリターバージョンmd5.so_md5.dll他のプログラミング言語用の移植性の高いコードではありません。さらに、このmd5モジュールは2.5以降Python標準ライブラリで非推奨になっているため、より一般的な解決策を見つける必要があります。

さらに、ハッシュの状態を16進ダイジェスト自体に格納できますか?(したがって、ダーティな内部ハックではなく、既存のハッシュダイジェストを使用してデータのストリームをハッシュし続けることができます。)

4

3 に答える 3

2

これは理論的には可能ですが(これまでのところ、md5には続行するために必要なすべての状態が含まれているはずです)、通常のAPIでは必要なものが提供されていないようです。代わりにCRCで十分な場合は、必要な「ストリーミング」の場合にCRCがより一般的に使用されるため、これはおそらくはるかに簡単です。ここを参照してください:

binascii.crc32(data [、crc])

crc32()続行するチェックサムであるオプションのcrc入力を受け入れます。

お役に立てば幸いです。

于 2011-05-03T06:43:00.240 に答える
2

既知のダイジェストからではなく、既知の状態から。純粋なPythonMD5実装を使用して、その状態を保存できます。PyPyの_md5.pyを使用した例を次に示します。

import _md5

def md5_getstate(md):
    return (md.A, md.B, md.C, md.D, md.count + [], md.input + [], md.length)

def md5_continue(state):
    md = _md5.new()
    (md.A, md.B, md.C, md.D, md.count, md.input, md.length) = state
    return md

m1 = _md5.new()
m1.update("hello, ")
state = md5_getstate(m1)
m2 = md5_continue(state)
m2.update("world!")
print m2.hexdigest()

m = _md5.new()
m.update("hello, world!")
print m.hexdigest()

e.danが指摘したように、ほとんどすべてのチェックサムアルゴリズム(CRC、Adler、Fletcher)を使用することもできますが、意図的なデータ変更からは保護されず、ランダムエラーからのみ保護されます。

編集:もちろん、参照したスレッドのctypesを使用して、より移植性の高い方法で(マジック定数なしで)シリアル化メソッドを再実装することもできます。これはバージョン/アーキテクチャに依存しないはずだと思います(Python 2.4-2.7、i386とx86_64の両方でテスト済み):

# based on idea from http://groups.google.com/group/comp.lang.python/msg/b1c5bb87a3ff5e34

try:
    import _md5 as md5
except ImportError:
    # python 2.4
    import md5
import ctypes

def md5_getstate(md):
    if type(md) is not md5.MD5Type:
        raise TypeError, 'not an MD5Type instance'
    return ctypes.string_at(id(md) + object.__basicsize__,
                            md5.MD5Type.__basicsize__ - object.__basicsize__)

def md5_continue(state):
    md = md5.new()
    assert len(state) == md5.MD5Type.__basicsize__ - object.__basicsize__, \
           'invalid state'    
    ctypes.memmove(id(md) + object.__basicsize__,
                   ctypes.c_char_p(state),
                   len(state))
    return md

m1 = md5.new()
m1.update("hello, ")
state = md5_getstate(m1)
m2 = md5_continue(state)
m2.update("world!")
print m2.hexdigest()

m = md5.new()
m.update("hello, world!")
print m.hexdigest()

_md5 / md5モジュールがないため、Python3とは互換性がありません。

残念ながら、hashlibのopenssl_md5実装は、OpenSSL EVP APIがEVP_MD_CTXオブジェクトを確実にシリアル化するための呼び出し/メソッドを提供しないため、このようなハッキングには適していません。

于 2011-05-03T07:14:32.233 に答える
1

私もこの問題に直面していて、既存の解決策が見つからなかったので、ctypesを使用してハッシャー状態を保持するOpenSSLデータ構造を分解するライブラリを作成しました:https ://github.com/kislyuk/rehash 。例:

import pickle, rehash
hasher = rehash.sha256(b"foo")
state = pickle.dumps(hasher)

hasher2 = pickle.loads(state)
hasher2.update(b"bar")

assert hasher2.hexdigest() == rehash.sha256(b"foobar").hexdigest()
于 2017-07-12T18:37:14.017 に答える