4

我有一个散列算法对象(在本例中为 SHA1),我向其提供数据,以便在调用 Result 属性时最终获得散列结果。

问题是一旦调用了 m_HashAlgorithm.Hash 属性,该对象就不能再用于喂食。如果我尝试输入它,我会得到: System.Security.Cryptography.CryptographicUnexpectedOperationException: Hash must be finalized before the hash value is retrieved.

我需要能够获得中间散列结果,但继续喂食并稍后获得另一个结果。有没有办法实现它?

private readonly HashAlgorithm m_HashAlgorithm;

public DigitalSignatureCreator(HashAlgorithm hashAlgorithm)
{
    m_HashAlgorithm = hashAlgorithm;

    m_MemoryStreamEncrypt = new MemoryStream();
    m_CryptoStreamEncrypt = new CryptoStream(m_MemoryStreamEncrypt, m_HashAlgorithm, CryptoStreamMode.Write);
}

public void Feed(byte[] data, int offset, int count)
{
    m_CryptoStreamEncrypt.Write(data, offset, count);
}

public byte[] Result
{
    get
    {
          return m_HashAlgorithm.Hash;
    }
}
4

2 回答 2

4

您需要HashFinal在获得结果之前调用:

http://msdn.microsoft.com/en-us/library/system.security.cryptography.hashalgorithm.hashfinal.aspx

根据哈希算法的工作方式(块密码),您无法获得准确的中间结果,因为它不会正确计算中间数据块。这是因为它必须填充最终数据块以确保正确的值并保持加密“强”。换句话说,由于数据块依赖于先前的块,因此您需要所有数据来生成正确的结果。.NET 试图通过在最终确定之前拒绝访问密码结果来帮助您解决这个问题。您提供哈希所有数据,然后完成以获得正确计算的结果。

我会向你提出这个问题:你为什么需要中间结果?有什么理由可以从不同的角度接近或解决吗?告诉我们原因,我们或许可以提供替代方案。

您还应该注意在使用后正确关闭/处理您的流。

于 2013-08-26T15:48:01.890 回答
2

我猜你不能使用HashAlgorithm. 因此,如果您想这样做,您可能必须依赖可以更改的哈希实现,例如 Bouncy Castle 库中的那个(非常宽松的库,因此您可以从代码中获取状态)。

请注意,对哈希扩展的攻击是众所周知的,因此您可能需要重新查看您的协议。

如果您想使用标准算法实现,我建议您查看哈希树实现,这在文件共享协议中很常见。

于 2013-08-26T17:29:45.707 回答