为什么SHA1.ComputeHash高负荷下失败,多个线程? [英] Why does SHA1.ComputeHash fail under high load with many threads?

查看:418
本文介绍了为什么SHA1.ComputeHash高负荷下失败,多个线程?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我看到有一些代码,我保持一个问题。下面的代码有一个私有静态SHA1 成员(这是一个的IDisposable 但因为它是,它应该永远不会敲定)。然而,在压力下的代码抛出表明它已关闭了异常:



<预类=郎无prettyprint-覆盖> 捕捉到异常。安全句柄已关闭
堆栈跟踪:调用堆栈,其中的例外是在System.Runtime.InteropServices.SafeHandle.DangerousAddRef抛出
(布尔&安培;成功)
在System.Security.Cryptography.Utils .HashData(SafeHashHandle hHash,字节[]数据的Int32 cbData,的Int32 ibStart,的Int32 CBSIZE)
在System.Security.Cryptography.Utils.HashData(SafeHashHandle hHash,字节[]数据的Int32 ibStart,的Int32 CBSIZE)$在System.Security.Cryptography.HashAlgorithm.ComputeHash b $ b(字节[]缓冲区)

代码问题是:

 内部类TokenCache 
{
私有静态SHA1 _sha1 = SHA1.Create() ;

私人字符串ComputeHash(字符串密码)
{
字节[] = passwordBytes UTF8Encoding.UTF8.GetBytes(密码);
返回UTF8Encoding.UTF8.GetString( _sha1.ComputeHash(passwordBytes));
}

我的问题是很明显这是什么原因问题,调用 SHA1.Create 可能失败默默(多少加密资源可用)?难道这是由AppDomain的下降引起的?



任何其他理论?


解决方案

按照文档的HashAlgorithm 基类




任何公共静态(共享在Visual Basic中)这种类型的成员是线程安全的。任何实例成员不能保证是线程安全的。




您不应线程,不同的线程试图调用<$之间共享这些类C $ C> ComputeHash 在同一时间同一个实例。



修改
这是是什么原因造成的错误。下面的压力测试产生的各种错误,由于多个线程调用ComputeHash在同一个哈希算法的实例。你的错误就是其中之一。



具体来说,我已经看到了这种压力测试以下错误:




  • System.Security.Cryptography.CryptographicException:哈希不适于在指定状态下使用

  • System.ObjectDisposedException:安全句柄已关闭



压力测试的代码示例:

  const int的THREADCOUNT = 2; 
VAR SHA1 = SHA1.Create();
变种B =新的屏障(经纬);
行动开始=()=> {
b.SignalAndWait();
的for(int i = 0; I< 10000;我++)
{
VAR PWD = Guid.NewGuid()的ToString();
VAR字节= Encoding.UTF8.GetBytes(PWD);
sha1.ComputeHash(字节);
}
};
VAR线程= Enumerable.Range(0,经纬)
。选择(_ =>新建的ThreadStart(开始))
。选择(X =>新建线程(X))
.ToList();
的foreach(在线程变种T)t.Start();
的foreach(在线程变种T)t.Join();


I'm seeing an issue with some code I maintain. The code below has a private static SHA1 member (which is an IDisposable but since it's static, it should never get finalized). However, under stress this code throws an exception that suggests it has been closed:

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)

The code in question is:

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));
    }

My question is obviously what could cause this issue. Can the call to SHA1.Create fail silently (how many cryptographic resources are available)? Could this be caused by the appdomain going down?

Any other theories?

解决方案

As per the documentation for the HashAlgorithm base class

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

You should not share these classes between threads where different threads try and call ComputeHash on the same instance at the same time.

EDIT This is what is causing your error. The stress test below yields a variety of errors due to multiple threads calling ComputeHash on the same hash algorithm instance. Your error is one of them.

Specifically, I have seen the following errors with this stress test:

  • System.Security.Cryptography.CryptographicException: Hash not valid for use in specified state.
  • System.ObjectDisposedException: Safe handle has been closed

Stress test code sample:

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();

这篇关于为什么SHA1.ComputeHash高负荷下失败,多个线程?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆