用于动态增长/流数据的哈希算法?

est*_*est 7 python hash md5 data-stream

是否有任何算法可以从已知的哈希摘要中继续哈希?例如,客户端将一大块文件上传到ServerA,我可以得到md5上传内容的总和,然后客户端将剩余的文件块上传到ServerB,我可以将md5内部状态转移到ServerB并完成散列吗?

基于我多年前在comp.lang.python上发现的md5 有一个很酷的黑魔法黑客,但是它ctypes用于特定版本的md5.so或者_md5.dll,所以它不是用于不同python解释器版本或其他编程语言的可移植代码,除了md5模块自2.5以来在python标准库中已弃用,因此我需要找到更通用的解决方案.

更重要的是,散列的状态是否可以存储在十六进制摘要本身中?(因此,我可以继续使用现有的哈希摘要散列数据流,而不是内部黑客攻击.

任何想法都表示赞赏.提前致谢 :)

abb*_*bot 2

不是来自已知的摘要,而是来自已知的状态。您可以使用纯 python MD5 实现并保存其状态。这是使用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()
Run Code Online (Sandbox Code Playgroud)

正如 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()
Run Code Online (Sandbox Code Playgroud)

它与 Python 3 不兼容,因为它没有 _md5/md5 模块。

不幸的是,hashlib 的 openssl_md5 实现不适合此类黑客攻击,因为 OpenSSL EVP API 不提供任何调用/方法来可靠地序列化 EVP_MD_CTX 对象。