【问题标题】:Invalid algorithm while creating rsa-sha512 signature创建 rsa-sha512 签名时算法无效
【发布时间】:2018-04-30 08:24:32
【问题描述】:

我正在尝试使用本地 HDD 上的证书将 rsa-sha512 签名应用于消息。 最终的 SignData 引发加密异常“指定的算法无效”。 但是,如果我在 RSACryptoServiceProvider 的新实例(通过导入原始 RSACryptoServiceProvider 的导出创建)上使用 SignData,则不会出现该异常。 原始版本引发异常是否有某种原因?由于“副本”明显不同,我更喜欢使用原件。

我使用的c#代码如下:

X509Certificate2 cert = new X509Certificate2("C:\\Certs\\" + certName + ".p12", certPassword, X509KeyStorageFlags.Exportable);
RSACryptoServiceProvider csp = (RSACryptoServiceProvider)cert.PrivateKey;
UTF8Encoding ByteConverter = new UTF8Encoding();
byte[] unsignedBytes = ByteConverter.GetBytes(unsignedText);
byte[] signature;

//This raises an exception, "Invalid algorithm specified."
signature = csp.SignData(unsignedBytes, new SHA512CryptoServiceProvider());

//But if I make a copy of the RSACryptoServiceProvider, no exception is raised
RSACryptoServiceProvider cspCopy = new RSACryptoServiceProvider();
RSAParameters Key = csp.ExportParameters(true);
cspCopy.ImportParameters(Key);
signature = cspCopy.SignData(unsignedBytes, new SHA512CryptoServiceProvider());

【问题讨论】:

    标签: c# .net cryptography digital-signature


    【解决方案1】:

    a previous answer引用我自己的话:

    只有当 CSP ProviderType 值为 24 (PROV_RSA_AES) 且 ProviderName 为“Microsoft Enhanced RSA and AES Cryptographic Provider” (MS_ENH_RSA_AES_PROV) 时,软件支持的 RSACryptoServiceProvider 才能使用 SHA-2 摘要算法进行 RSA 签名。硬件可能需要也可能不需要 PROV_RSA_AES,这取决于硬件。

    在这种情况下,PFX 将私钥识别为属于较旧的 CSP(或者,它可能没有 CSP 标识符,并且 PFX 导入选择了错误的默认值)。对于软件密钥,可以从密钥中提取 CspParameterInfo 数据并使用 ProviderType 24 重新打开它,这是解决问题的一种方法。导出原始 RSA 参数并将其导入新对象(默认为 ProviderType 24)是一种更激进的解决方法。

    解决此问题的更好方法是放弃 RSACryptoServiceProvider。而不是使用cert.PrivateKey,而是使用cert.GetRSAPrivateKey(),它几乎总是会返回一个没有这个问题的RSACng实例(但如果你可以避免它,请不要强制转换它(如果没有别的,总是看到“几乎” ))。

    byte[] signature;
    
    using (RSA rsa = cert.GetRSAPrivateKey())
    {
        signature = rsa.SignData(
            unsignedBytes,
            HashAlgorithmName.SHA512,
            RSASignaturePadding.Pkcs1);
    }
    

    using 语句对于 GetRSAPrivateKey 是正确的,因为它每次调用都会返回一个不同的对象。

    RSACng 和 GetRSAPrivateKey 都需要 .NET 4.6,但此时已经有两年多的历史了(当时已经发布了 4 个(半)新版本),因此作为依赖项不应该给您带来困难。

    【讨论】:

    • 这一行解决了我的问题:“不要使用 cert.PrivateKey,而是使用 cert.GetRSAPrivateKey()”谢谢
    猜你喜欢
    • 2019-11-19
    • 2018-08-11
    • 2011-02-02
    • 2018-10-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-24
    • 2022-01-26
    相关资源
    最近更新 更多