为什么.NET RSACryptoServiceProvider抛出"安全句柄已关闭"例外?

时间:2015-02-11 22:47:17

标签: c# .net security rsa

以下方法用于使用" SHA1"来验证针对公钥的数据。第一次调用该方法是正常的。但是,当该方法被调用时,第二行和后续行会出现以下行

isVerified = RSA.VerifyData(tokenData, CryptoConfig.MapNameToOID(hashType), signature);

导致此异常

{"Safe handle has been closed"} System.Exception {System.ObjectDisposedException}

关于我可能做错了什么的想法?

internal static bool VerifyTokenData(byte[] tokenData, byte[] signature, string hashType)
{
  try
  {
    bool isVerified = false;

    using (RSACryptoServiceProvider RSA = (RSACryptoServiceProvider)CompanyAuthentication.publicKey)
    {
      isVerified = RSA.VerifyData(tokenData, CryptoConfig.MapNameToOID(hashType), signature);
    }

    return isVerified;
  }
  catch (CryptographicException cryptoExc)
  {
    throw new InvalidOperationException("Exception verifying token data", cryptoExc);
  }
  catch (Exception exc)
  {
    throw new InvalidOperationException("Exception verifying token data", exc);
  }
}

使用的公钥使用

加载到类变量中
internal static void LoadKeys()
{
  try
  {
    X509Certificate2 certificate = new X509Certificate2();
    lock (CompanyAuthentication.thisLock)
    {
      certificate.Import(System.Configuration.ConfigurationManager.AppSettings["companyKeyFilePath"].ToString(), System.Configuration.ConfigurationManager.AppSettings["companyKeyFilePassword"].ToString(), X509KeyStorageFlags.UserKeySet);
      CompanyAuthentication.publicKey = certificate.PublicKey.Key;
      CompanyAuthentication.privateKey = certificate.PrivateKey;
    }
  }
  catch (CryptographicException cryptoExc)
  {
    throw new InvalidOperationException("Exception creating public/private keys", cryptoExc);
  }
  catch (Exception exc)
  {
    throw new InvalidOperationException("Exception creating public/private keys", exc);
  }
}

编辑: 这是经过修改的正常运行的代码。它每次都会加载密钥文件,而不是在类构造函数中加载一次。

    SalesNetAuthentication.LoadKeys();
    using (RSACryptoServiceProvider RSA = (RSACryptoServiceProvider)SalesNetAuthentication.publicKey)
    {
      isVerified = RSA.VerifyData(tokenData, CryptoConfig.MapNameToOID(hashType), signature);
    }

2 个答案:

答案 0 :(得分:3)

由于using (RSACryptoServiceProvider RSA = ... using范围结束,因此您处理了该对象。

解决方案是删除using,以便对象可以在后续尝试中使用,或者每次需要使用时重新创建对象。

答案 1 :(得分:2)

问题是您正在重用CompanyAuthentication.publicKey,即使您第一次调用它时将其丢弃(将其包装在using块中会导致调用.Dispose()方法) 。

如果您打算继续使用它,我认为您不想处置此对象。由于这似乎是一个静态变量,您可能不希望在关闭应用程序之前将其丢弃。