我正在尝试使用本地HDD上的证书将rsa-sha512签名应用于邮件。 最终的SignData会引发加密异常“指定的无效算法”。 但是,如果我在RSACryptoServiceProvider的新实例上使用SignData(通过导入原始RSACryptoServiceProvider的导出创建),我不会得到该异常。 是否有某些原因导致原始版本引发异常?由于“副本”明显不同,我宁愿使用原件。
我正在使用的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());
答案 0 :(得分:0)
从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(半)个新版本),所以不应该因为依赖而导致困难。