创建 rsa-sha512 签名时算法无效

Invalid algorithm while creating rsa-sha512 signature

我正在尝试使用本地 HDD 上的证书将 rsa-sha512 签名应用于邮件。 最终的 SignData 引发了一个加密异常 "Invalid algorithm specified"。 但是,如果我在 RSACryptoServiceProvider 的新实例(通过导入原始 RSACryptoServiceProvider 的导出创建)上使用 SignData,我不会得到该异常。 原始版本引发异常是否有某种原因?由于 "copy" 明显不同,我更愿意使用原来的

我使用的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());

引自

Software-backed RSACryptoServiceProvider is only capable of doing RSA signature using a SHA-2 digest algorithm when the CSP ProviderType value is 24 (PROV_RSA_AES) and the ProviderName is "Microsoft Enhanced RSA and AES Cryptographic Provider" (MS_ENH_RSA_AES_PROV). Hardware may or may not require PROV_RSA_AES, just depends on the hardware.

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

解决该问题的更好方法是放弃 RSACryptoServiceProvider。而不是使用 cert.PrivateKey,而是使用 cert.GetRSAPrivateKey(),它几乎总是 return 一个 RSACng 实例,它没有这个问题(但如果你能避免它就不要转换它(如果没有别的,总是看到 "almost")).

byte[] signature;

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

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

RSACng 和 GetRSAPrivateKey 都需要 .NET 4.6,但此时已超过两年(那时已经发布了 4(半)个新版本),所以不应该给您带来困难依赖。