我正在查看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;
}
答案 0 :(得分:3)
您应该检查的第一件事是您是IO绑定还是CPU限制。如果你受CPU限制,那么我怀疑是 Bouncy Castle。如果你受IO限制,可能是.NET对IO更加智能。首先,您可能希望将缓冲区大小从4K增加到(比方说)64K。试一试吧。这是一个非常容易的改变。更难的改变是使用异步IO,以便在您散列已经获得的数据时读取下一个缓冲区的未散列数据。
答案 1 :(得分:1)
虽然这两种算法可能差异很大,您可能会遇到3-6倍的差异,但问题很可能是由于I / O差异造成的。通过将FileStream传递给.NET实现,它有可能在内部做一些聪明的事情来实现更好的I / O性能(例如并发哈希和读取),而你在Bouncy Castle示例中没有这样做。
要对此进行测试,您可以:
让你的两个例子尽可能相似(这就是我要做的)。您可以在.NET HashAlgorithm中使用TransformBlock和TransformFinalBlock,它将更类似于您的Bouncy Castle测试。
尝试对Bouncy Castle代码进行I / O优化,看看是否可以实现.NET实现的性能。
但这可能没有实际意义。如果.NET实现满足您的需求,它可能最适合您的应用程序。看起来它可能已经内置了一些性能特征,你必须手动添加到Bouncy Castles实现。
答案 2 :(得分:1)
似乎您正在正确使用它。
您对两个实现之间的性能差异也很正确。 我的最新测试表明,在c#nuget上的Bouncy Castle MD5哈希比.NET哈希慢约X2。
答案 3 :(得分: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;
(我很清楚,将完整的文件内容存储在内存中可能不是很方便)。