这与X509Certificate2 from store with private key的答案有关。
似乎当我想使用SHA256withRSA时,不能直接从证书的私钥中使用服务提供商-我需要创建新的加密服务提供商:
var bytes = new byte[] { 0, 1, 2, 3 };
//_cert - X509Certificate2 with private key
//csp1 is of type I need, but it won't work
var csp1 = _cert.PrivateKey as RSACryptoServiceProvider;
var cspParameters = new CspParameters
{
KeyContainerName = csp1.CspKeyContainerInfo.KeyContainerName,
KeyNumber = csp1.CspKeyContainerInfo.KeyNumber == KeyNumber.Exchange ? 1 : 2,
};
var csp2 = new RSACryptoServiceProvider(cspParameters);
//I can't use csp1 here - will throw "CryptographicException : Invalid algorithm specified."
//I can use csp1 with "SHA1" though
var signature = csp2.SignData(bytes, CryptoConfig.MapNameToOID("SHA256"));
我在这里找到了一些有关此的信息:
但是上面的解决方案来自注释部分,我真的不明白为什么我需要跳过篮球才能使用一种常见算法。所以我想问的是:
csp1
不能完全与SHA256一起使用? csp2
是否正确? 如果需要,可以如下生成带有私钥的证书:
openssl req -x509 -sha256 -newkey rsa:2048 -keyout ./temp/key.key -out ./temp/crt.crt -days 10 –nodes
openssl pkcs12 -export -out .\temp\cert.pfx -inkey .\temp\key.key –in .\temp\crt.crt
答案 0 :(得分:2)
这完全取决于您的证书来自何处。就像MSDN注释所说的那样,如果它来自Microsoft Base Cryptographic Provider,那么它将不能与SHA256一起使用。该CSP早在1996年就随CryptoAPI的第一个版本一起发布,并且不了解SHA256,因为当时还没有SHA256。
优雅地检查和处理此问题的方法是:
public byte[] SignData(RSACryptoServiceProvider csp, byte[] bytes)
{
byte[] sig = null;
if ((csp.CspKeyContainerInfo.ProviderType == PROV_RSA_FULL || csp.CspKeyContainerInfo.ProviderType == PROV_RSA_SCHANNEL) && !csp.CspKeyContainerInfo.HardwareDevice)
{
var cspParameters = new CspParameters
{
KeyContainerName = csp.CspKeyContainerInfo.KeyContainerName,
KeyNumber = csp.CspKeyContainerInfo.KeyNumber == KeyNumber.Exchange ? 1 : 2,
};
using (var csp2 = new RSACryptoServiceProvider(cspParameters))
{
sig = csp2.SignData(bytes, CryptoConfig.MapNameToOID("SHA256"));
}
}
else {
sig = csp.SignData(bytes, CryptoConfig.MapNameToOID("SHA256"));
}
return sig;
}
仅供参考,CryptoAPI是being deprecated,赞成Cryptography API: Next Generation。使用C#中的CNG进行操作的一种方法是使用System.Security.Cryptography.Cng:
...
using (RSA rsa = new RSACng())
{
byte[] signature = rsa.SignData(message, hashAlgorithm, paddingMode);
...
}