需要存储哪些状态才能允许可恢复的哈希计算?

时间:2014-01-03 01:28:30

标签: algorithm hash cryptography

这个问题只与现实问题间接相关,更令人感兴趣。我并不了解当前的真实哈希算法如何在内部工作。

我知道典型的哈希计算(和CRC计算等)会逐步工作,依次为每个字节/字更新一些状态 [事实证明算法一次只能运行一个块,虽然接口经常自动处理]。因此,稍后可以恢复部分完成的哈希计算 - 存储该状态,然后重新加载并继续您离开的位置。关于SO的问题已经存在,但它们似乎都与特定的图书馆有关。

从CRC-16的古老知识(是的,真的 - 由于过时的文件格式),我的印象是CRC值本身就是你需要存储以恢复计算的所有状态。显然,实现可以用奇怪的方式编写,但原则上到目前为止看到的文件部分内容的CRC-16是从该点恢复计算所需的完整状态。

现在使用的所有常见哈希计算都是如此吗?特别是MD5,SHA-1和SHA-256。或者是否必须存储其他(附加或替代)状态才能恢复计算?

显然需要从文件中恢复的位置,但除此之外,您需要存储什么样的精确状态才能使用公共散列函数恢复散列计算。

对于额外的奖励积分 - 如何在C ++中使用Crypto ++访问该状态? (链接或对文档正确部分的引用可能非常有用)。

我将此标记为“算法”,因为这是此处的重点 - 来自现实世界算法的要求,而不是任何特定语言或库的实现。

2 个答案:

答案 0 :(得分:7)

今天的大多数加密哈希,包括MD5SHA-1SHA-2系列都基于Merkle–Damgård construction

在这种结构中,通过将输入分成固定长度的块来处理输入,固定长度的块一次一个地馈送到“混合函数”中,该“混合函数”将算法的内部状态不可逆地混合在一起(这也是一个固定长度的bitstring)。在输入结束时,产生的内部状态进一步被不可逆转地转换以防止某些类型的攻击:

Diagram of the Merkle–Damgård hashing process

(即将发布的SHA-3哈希标准基于较新的cryptographic sponge construction,它在某些细节上有所不同,但在此处讨论的一般级别上并不显着。)

如果不是长度填充和完成步骤,您可以只获取任何消息的散列并使用它来计算该消息的散列,并附加一些额外的数据,就像您可以使用CRC一样。唉,从加密的角度来看,这被认为是一件坏事,并且最终确定步骤被特别包含在使其无法实现的过程中。

因此,如果要在消息中间中断散列过程并稍后恢复,则需要在之前获取内部状态字符串,然后才能通过填充和终结阶段。< / p>

(您可能还需要存储少量附加数据,例如到目前为止处理的块数,以获得正确的长度填充,如果散列在块中间被中断,则任何部分输入块都不会然后进入混合功能。)


大多数加密库使用存储内部状态的哈希对象实现哈希算法,并允许以任意段提供输入,如下所示(伪代码):

HashFunction hash = new SomeHashFunction();
hash.addInput( data );
// ...
hash.addInput( moreData );
BitString output = hash.finalize();

通常,即使散列对象可能无法直接访问其内部状态,它们通常也会提供克隆和/或序列化自身的方法。我并不特别熟悉Crypto++,但一目了然,seems提供Clone()方法。


聚苯乙烯。如果您对使用加密哈希值进行文件完整性验证感兴趣,可能需要查看universal hashing,特别是基于多项式评估的通用哈希函数,如GHASHPoly1305 。这些是非常快速且可并行化的哈希函数,通常用作authenticated encryption方案的一部分,但也可以单独用作message authentication codes。关于它们的好处是它们不仅可以逐步计算,而且,通过一些聪明的数学,如果对数据的中间进行了更改,它们甚至可以逐步更新。它们的主要缺点是,为了防止伪造加密(例如,创建具有相同散列的两个文件),它们需要与密钥一起使用。

答案 1 :(得分:0)

@Mitch-我知道这是一个老话题,但是您的请求并不令人感兴趣。现在,在汽车世界中,这项新的FOTA功能(空中固件)可通过4G,WiFi等更新车辆固件(几个车载电子控制单元中的几个固件)。车辆可能会接收到固件中断(无网络区域,车辆关闭...)。因此,我们分几部分接收该软件,并且我们需要能够停止/恢复哈希计算(用于签名验证)。但是当前的汽车加密软件SW标准(Autosar)与例如PKCS#11标准。