c# - 为什么 SHA1.ComputeHash 在多线程的高负载下会失败?

标签 c# sha stress-testing finalizer

我发现我维护的一些代码存在问题。下面的代码有一个 private static SHA1 成员(它是一个 IDisposable 但因为它是 static,所以它永远不会被最终确定)。然而,在压力下,这段代码会抛出一个异常,表明它已被关闭:

Caught exception.  Safe handle has been closed" 
Stack trace: Call stack where exception was thrown
at System.Runtime.InteropServices.SafeHandle.DangerousAddRef(Boolean& success)
at System.Security.Cryptography.Utils.HashData(SafeHashHandle hHash, Byte[] data, Int32 cbData, Int32 ibStart, Int32 cbSize)
at System.Security.Cryptography.Utils.HashData(SafeHashHandle hHash, Byte[] data, Int32 ibStart, Int32 cbSize)
at System.Security.Cryptography.HashAlgorithm.ComputeHash(Byte[] buffer)

有问题的代码是:

internal class TokenCache
{
    private static SHA1 _sha1 = SHA1.Create();

    private string ComputeHash(string password)
    {
        byte[] passwordBytes = UTF8Encoding.UTF8.GetBytes(password);
        return UTF8Encoding.UTF8.GetString(_sha1.ComputeHash(passwordBytes));
    }

我的问题显然是什么会导致这个问题。对 SHA1.Create 的调用是否会静默失败(有多少加密资源可用)?这可能是由应用程序域关闭引起的吗?

还有其他理论吗?

最佳答案

根据 the documentation对于 HashAlgorithm 基类

Any public static (Shared in Visual Basic) members of this type are thread safe. Any instance members are not guaranteed to be thread safe.

您不应在不同线程尝试同时在同一实例上调用 ComputeHash 的线程之间共享这些类。

编辑 这就是导致您的错误的原因。由于多个线程在同一个哈希算法实例上调用 ComputeHash,下面的压力测试会产生各种错误。您的错误就是其中之一。

具体来说,我在这个压力测试中看到了以下错误:

  • System.Security.Cryptography.CryptographicException:哈希在指定状态下使用无效。
  • System.ObjectDisposedException: 安全句柄已关闭

压力测试代码示例:

const int threadCount = 2;
var sha1 = SHA1.Create();
var b = new Barrier(threadCount);
Action start = () => {
                    b.SignalAndWait();
                    for (int i = 0; i < 10000; i++)
                    {
                        var pwd = Guid.NewGuid().ToString();
                        var bytes = Encoding.UTF8.GetBytes(pwd);
                        sha1.ComputeHash(bytes);
                    }
                };
var threads = Enumerable.Range(0, threadCount)
                        .Select(_ => new ThreadStart(start))
                        .Select(x => new Thread(x))
                        .ToList();
foreach (var t in threads) t.Start();
foreach (var t in threads) t.Join();

关于c# - 为什么 SHA1.ComputeHash 在多线程的高负载下会失败?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26592596/

相关文章:

c# - WPF MeasureOverride 不适用于我的自定义控件

c# - 无法从文件连接到数据库

java - 如何减小 SHA1 的大小?

mysql - 通过MySQL生成密码的pbkdf2_sha256 hash

使用 100 台设备进行测试

php - 测试网站的负载、压力、可扩展性

c# - 使用 XPath 从 XML 文件中提取 XML 元素

C# 数据 GridView : Long Text Truncated with "..." on the Left Side When the Column is Right-Aligned

尝试获取 SHA 证书指纹时发生 firebase 错误?

JMeter 和 JavaScript