CryptographicException:使用 SHA-512 时“指定的算法无效”

Posted

技术标签:

【中文标题】CryptographicException:使用 SHA-512 时“指定的算法无效”【英文标题】:CryptographicException: 'Invalid algorithm specified' when using SHA-512 【发布时间】:2019-05-29 12:20:27 【问题描述】:

在我的 WPF 应用程序 (.NET 4.6) 中,我需要使用 P12 证书文件使用 SHA-512 算法对字符串进行签名(包括在 Web 请求的标头中)。我这样做如下:

using (var rsa = myX509Certificate2.GetRSAPrivateKey()) 
  myBytes = rsa.SignData(
    Encoding.UTF8.GetBytes(stringToSign), 
    HashAlgorithmName.SHA512, 
    RSASignaturePadding.Pkcs1
  );

这适用于测试和我的几乎所有客户,但奇怪的客户得到以下例外:

System.Security.Cryptography.CryptographicException: Invalid algorithm specified.
  at System.Security.Cryptography.CryptographicException.ThrowCryptographicException(Int32 hr)
  at System.Security.Cryptography.Utils.SignValue(SafeKeyHandle hKey, Int32 keyNumber, Int32 calgKey, Int32 calgHash, Byte[] hash, Int32 cbHash, ObjectHandleOnStack retSignature)
  at System.Security.Cryptography.Utils.SignValue(SafeKeyHandle hKey, Int32 keyNumber, Int32 calgKey, Int32 calgHash, Byte[] hash)
  at System.Security.Cryptography.RSACryptoServiceProvider.SignHash(Byte[] rgbHash, Int32 calgHash)
  at System.Security.Cryptography.RSACryptoServiceProvider.SignHash(Byte[] hash, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding)
  at System.Security.Cryptography.RSA.SignData(Byte[] data, Int32 offset, Int32 count, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding)
  at System.Security.Cryptography.RSA.SignData(Byte[] data, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding)

最近发生在一位使用 Windows 7 SP1 的客户身上。

我正在努力通过现有的 SO 问题或一般的谷歌寻找答案。据我所知,这可能是由于在后台使用了不受支持的 Windows 加密服务提供商,但我不确定,因为我自己无法复制错误。

任何想法如何解决这个问题,无论是通过代码还是让受影响的客户安装任何特定的 Windows 更新?

【问题讨论】:

【参考方案1】:

如果您正在使用 cert.GetRSAPrivateKey() 并且它返回一个 RSACryptoServiceProvider 实例,这表明它不是来自 PFX,而是来自带有旧驱动程序的智能卡。既然你说它来自 .p12/.pfx,那么 PFX 可能包含对 CNG 没有接管的常用加密服务提供商名称的引用(但我从未在软件密钥中看到过)。 (奥卡姆剃刀提出一个问题:你确定他们不是不小心使用了错误的证书吗?)

如果您知道它来自 PFX,并且您已使用 Exportable 位将其导入,您可以手动将其从 RSACryptoServiceProvider 转换为 RSACng:

using (RSA rsa = cert.GetRSAPrivateKey())

    byte[] toSign = Encoding.UTF8.GetBytes(stringToSign);
    myBytes = null;

    try
    
        myBytes = rsa.SignData(
            toSign, 
            HashAlgorithmName.SHA512, 
            RSASignaturePadding.Pkcs1);
    
    catch (CryptographicException)
    
        try
        
            using (RSA rsaCng = new RSACng())
            
                rsaCng.ImportParameters(rsa.ExportParameters(true));

                myBytes = rsaCng.SignData(
                    toSign,
                    HashAlgorithmName.SHA512, 
                    RSASignaturePadding.Pkcs1);
            
        
        catch
        
        

        if (myBytes == null)
        
            // Let the original exception continue
            throw;
        
    

(作为原始异常抛出的替代方案,您可以决定让“重试”异常被抛出)


另外,Windows 10 修复了许多 RSACryptoServiceProvider“无效算法”行为,因此他们可以随时尝试升级。

【讨论】:

谢谢 - 我会用它来构建并提供给客户试用。

以上是关于CryptographicException:使用 SHA-512 时“指定的算法无效”的主要内容,如果未能解决你的问题,请参考以下文章

CryptographicException - 无法更新密码

使用无效密钥解密并不总是抛出 CryptographicException

CryptographicException 未处理:系统找不到指定的文件

RSACryptoServiceProvider CryptographicException 系统找不到 ASP.NET 下指定的文件

尝试加载证书的私钥时出现“指定的提供程序类型无效”CryptographicException

CryptographicException异常处理方法