我有以下用例:
增量散列文件不是问题,just call TransformBlock
and TransformFinalBlock
。
问题是我需要多个数据散列来共享其起始字节,但在我调用TransformFinalBlock
来读取第一个Hash
字节的n
后,我无法继续使用相同的对象进行哈希并需要一个新对象。
在搜索问题时,我发现Python和OpenSSL都可以选择复制散列对象,以实现此目的:
hash.copy()
返回哈希对象的副本(“clone”)。此可用于有效计算共享共同初始子字符串的字符串摘要。
EVP_MD_CTX_copy_ex()可用于从中复制消息摘要状态 进去如果要散列大量数据,这非常有用 只在最后几个字节中有所不同。 out必须初始化 在调用此函数之前。
尽可能搜索,我找不到任何包含C#HashAlgorithm的库存,这样我就可以在调用它之前有效地Clone()
==复制这样的对象 TransformFinalBlock
方法 - 然后继续使用克隆散列其余数据。
我发现C# reference implementation for MD5可能很容易适应克隆(*),但我更倾向于使用那些而不是将这样的东西引入代码库。
(*)实际上,据我所知,任何哈希算法(与加密/解密相反)我讨厌检查是可以轻易复制的,因为这样的算法所具有的所有状态都是一种形式的摘要。
所以我在这里遗漏了一些东西,或者标准的C#/ .NET接口实际上是不是提供了复制哈希对象的方法?
另一个数据点:
Microsoft为crypto services提供的自己的原生API有一个函数CryptDuplicateHash
,其状态为doc,引用文档:
CryptDuplicateHash函数可用于创建单独的哈希值 以相同内容开头的两个不同内容。
自Windows XP以来一直存在。 : - |
请注意。 MD5:用例不具有加密敏感性。只是可靠的文件校验和。
答案 0 :(得分:4)
我意识到这并不是你所要求的,但是如果这与你解决的问题相符,那么另一种方法就是给你相同的保证&类似的流性能特征。我过去曾将此用于服务器到服务器文件传输协议,其中发送方/接收方始终不可用/可靠。当然,我控制了电线两侧的代码,我意识到你可能没有。在这种情况下,请忽略; - )
我的方法是设置1个处理整个文件的HashAlgorithm,另一个用于散列文件的固定大小的块 - 不是滚动哈希(避免你的问题),而是独立的哈希。因此,想象一下1034MB(1 GB + 10 MB)文件在逻辑上分为32MB块。发送方加载了文件,同时在文件级和块级HashAlgorithm上调用TransformBlock。当它到达32MB的末尾时,它在块级别1上调用TransformFinalBlock,记录该块的散列,并为下一个块重置/创建新的HashAlgorithm。当它到达文件的末尾时,它在文件块和块级别的哈希上调用TransformFinalBlock。现在发件人有一个计划'包含文件名,文件大小,文件哈希以及每个块的偏移量,长度和哈希值的传输。
它将计划发送给接收方,接收方为新文件分配空间(文件长度%块大小告诉它最后一个块小于32MB)或打开现有文件。如果文件已经存在,则它运行相同的算法来计算相同大小的块的哈希值。与计划的任何不匹配导致它仅向发送方询问这些块(这将考虑尚未转移的块/所有0和损坏的块)。它做了这个(验证,请求块)在一个循环中工作,直到没有任何东西要求。然后它检查了计划的文件级哈希。如果文件级哈希是无效的,但块级哈希都是有效的,那么它可能意味着哈希委托或坏RAM(两者都非常罕见......我使用的是SHA-512)。这允许接收器从不完整的块或损坏的块中恢复,最坏情况下必须再次下载1个坏块,这可以通过调整块大小来抵消。
答案 1 :(得分:3)
SIGH
库存.NET库不允许这样做。伤心。无论如何,有几种选择:
MD5Managed
pure .NET(“默认”MD5 RSA许可证)ClonableHash
通过PInvoke包装MS Crypto API(可能需要从Org.Mentalis
命名空间中提取一些工作,但许可证是允许的)也可以将C++ implementation包装在C ++ / CLI包装器中 - 初步测试表明这似乎比普通的.NET库更快,但是不要接受我的话它
因为,我自己也编写/改编了一个基于C ++的解决方案:https://github.com/bilbothebaggins/md5cpp
它还没有投入生产,因为要求发生了变化,但这是一个很好的练习,我觉得它很有效。 (除了它不是纯粹的C#实现。)