是否有任何算法可以继续从已知的哈希摘要中进行哈希处理?例如,客户端将一大块文件上传到ServerA,我可以获得上传内容的md5
总和,然后客户端将剩余的文件块上传到ServerB,我可以转移{{1内部到ServerB并完成散列?
我在几年前在comp.lang.python上找到了基于md5的cool black magic hack,但它使用md5
来表示特定版本的ctypes
或md5.so
,所以它不是用于不同python解释器版本或其他编程语言的可移植代码。此外,自{2.5}以来,_md5.dll
模块在python标准库中已弃用,因此我需要找到更通用的解决方案。
此外,散列的状态是否可以存储在十六进制摘要本身中? (所以我可以继续使用现有的哈希摘要散列数据流,而不是内部黑客攻击。)
答案 0 :(得分:2)
这在理论上是可行的(到目前为止md5 应该包含你需要继续的所有状态),但看起来普通的API不能提供你需要的东西。如果你可以使用CRC就足够了,这可能会容易得多,因为那些更常用于你需要的“流媒体”情况。见这里:
crc32()
接受一个可选的crc
输入,这是要继续的校验和。
希望有所帮助。
答案 1 :(得分:2)
不是来自已知摘要,而是来自已知状态。您可以使用纯python MD5实现并保存其状态。以下是使用_md5.py from from PyPy的示例:
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()
它不兼容Python 3,因为它没有_md5 / md5模块。
不幸的是,hashlib的openssl_md5实现不适用于此类黑客,因为OpenSSL EVP API不提供任何调用/方法来可靠地序列化EVP_MD_CTX对象。
答案 2 :(得分:1)
我也遇到了这个问题,并且没有找到现有的解决方案,因此我编写了一个库,该库使用ctypes来解构持有hasher状态的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()