2

我正在查看 Bouncy Castle 以了解其哈希算法的性能与 .NET Framework 的性能相比如何,而且它看起来不太好;MD5 实现比 .NET 慢约 6 倍,SHA256 实现比 .NET 慢约 3 倍。

所以我想确保我正确使用了 Bouncy Castle,因为文档几乎不存在。这就是我正在做的事情:

using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Digests;

public byte[] Hash(string filename)
{
  IDigest hash = new Sha256Digest();

  byte[] result = new byte[hash.GetDigestSize()];

  using (var fs = new FileStream(filename, FileMode.Open, FileAccess.Read, 
    FileShare.Delete | FileShare.ReadWrite))
  {
    byte[] buffer = new byte[4092];
    int bytesRead;

    while ((bytesRead = fs.Read(buffer, 0, buffer.Length)) > 0)
    {
      hash.BlockUpdate(buffer, 0, bytesRead);
    }

    hash.DoFinal(result, 0);
  }

  return result;
}

编辑

为了比较,这是我使用 .NET 的方式:

public byte[] Hash(string filename)
{
  byte[] hashBytes;
  HashAlgorithm hash = new SHA256CryptoServiceProvider();

  using (var fs = new FileStream(filename, FileMode.Open, FileAccess.Read, 
    FileShare.Delete | FileShare.ReadWrite))
  {
    try
    {
      hashBytes = hash.ComputeHash(fs);
    }
    finally
    {
      hash.Clear();
    }
  }

  return hashBytes;
}
4

4 回答 4

3

您应该检查的第一件事是您是受 IO 限制还是受 CPU 限制。如果您受 CPU 限制,那么我怀疑那Bouncy Castle。如果您受 IO 限制,则可能是 .NET 对 IO 更加智能。首先,您可能希望将缓冲区大小从 4K 增加到(例如)64K。试一试。这是一个非常容易的改变。一个更难的改变是使用异步 IO,以便您在对已经获得的数据进行哈希处理时读取下一个缓冲区的未哈希数据。

于 2012-08-21T17:57:50.307 回答
1

虽然这两种算法可能存在很大差异,以至于您会遇到 3-6 倍的差异,但问题也很可能是 I/O 差异的结果。通过将 FileStream 传递给 .NET 实现,它可能会在内部做一些聪明的事情来获得更好的 I/O 性能(例如散列和同时读取),而您在 Bouncy Castle 示例中没有这样做。

要对此进行测试,您可以:

  1. 使您的两个示例尽可能相似(这就是我要做的)。您可以在 .NET HashAlgorithm 中使用 TransformBlock 和 TransformFinalBlock,这将更类似于您的 Bouncy Castle 测试。

  2. 尝试对您的 Bouncy Castle 代码进行 I/O 优化,看看您是否可以接近 .NET 实现的性能。

不过,这可能没有实际意义。如果 .NET 实现满足您的需求,它可能最适合您的应用程序。似乎它可能已经内置了一些性能特征,您必须手动添加到 Bouncy Castles 实现中。

于 2012-08-21T18:09:07.140 回答
1
  1. 似乎您使用正确。

    • 如果您不确定,请通过将哈希值与 .NET 哈希值进行比较来测试您的代码。
    • 您还可以测试不同的块大小,看看它们是否能提高代码的性能。4092 可能不是较大流的最佳大小。另外,尝试采用 2 的倍数的块大小。
  2. 您对两种实现之间的性能差异也是正确的。我的最新测试表明,c# nuget 上的 Bouncy Castle MD5 散列比 .NET 散列慢 ~X2。

MD5 哈希时间(毫秒)

于 2019-08-12T10:52:43.117 回答
0

我知道这个问题已经很老了,但目前我能够为 .NET 和 Bouncy Castle 的 MD5 算法实现获得相同的速度。

但是,我不是在读取文件时计算哈希值,而是在上一步中读取完整的文件内容,然后对其进行哈希处理:

    var md5Digest = new MD5Digest();
    var hash = new byte[md5Digest.GetDigestSize()];

    md5Digest.BlockUpdate(buffer, 0, buffer.Length);
    md5Digest.DoFinal(hash, 0);

    // Once used, mark buffer content to be garbage collected.
    buffer = null;

(我很清楚将完整的文件内容存储在内存中可能不是很方便)。

于 2019-07-27T23:28:27.963 回答