我的商店证书有问题。在我的应用中,用户可以使用来自文件的证书或来自商店的证书。加载证书后,我使用证书作为签名数据。
使用来自文件的证书是可以的,但我不能使用商店中的等价物。
签名代码:
// Sign data
using (RSACryptoServiceProvider csp = new RSACryptoServiceProvider())
{
byte[] dataToSign = Encoding.UTF8.GetBytes(plainText);
csp.ImportParameters(((RSACryptoServiceProvider)_certPopl.PrivateKey).ExportParameters(true));
byte[] signature = csp.SignData(dataToSign, "SHA256");
// Verify signature
if (!csp.VerifyData(dataToSign, "SHA256", signature))
throw new Exception("Nepodařilo se vytvořit platný podpisový kód poplatníka.");
PKP = Convert.ToBase64String(signature);
}
从文件中读取证书的代码:
X509Certificate2Collection certStore = new X509Certificate2Collection();
certStore.Import(fileName, password, X509KeyStorageFlags.Exportable);
foreach (X509Certificate2 cert in certStore)
{
// Find the first certificate with a private key
if (cert.HasPrivateKey)
{
_certPopl = cert;
break;
}
}
来自商店的读取证书的代码。从商店加载证书后,我无法签署数据:
public void LoadCertificate(string certificateName, DateTime notAfter, string password)
{
var store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
store.Open(OpenFlags.MaxAllowed);
foreach (var certificate in store.Certificates)
{
if (certificate.FriendlyName.Equals(certificateName) && certificate.NotAfter.Equals(notAfter))
{
//X509Certificate2Collection certStore = new X509Certificate2Collection();
//certStore.Import(certificate.Export(X509ContentType.SerializedCert), password, X509KeyStorageFlags.Exportable);
//_certPopl = certStore[0];
X509Certificate2Collection certStore = new X509Certificate2Collection();
certStore.Import(certificate.GetRawCertData());
foreach (X509Certificate2 cert in certStore)
{
// Find the first certificate with a private key
if (cert.HasPrivateKey)
{
_certPopl = cert;
break;
}
}
break;
}
}
}
我没有使用证书的经验。但我需要等同于从商店获取证书才能签名。
在ExportParameters(true)上抛出System.Security.Cryptography.CryptographicException。 附加信息Exception:Key无法在指定状态下使用。
感谢。
答案 0 :(得分:2)
如果您可以使用.NET 4.6,这更加简单,访问私钥的新方法对SHA-2签名的工作更加可靠:
using (RSA rsa = cert.GetRSAPrivateKey())
{
if (rsa == null)
{
throw new Exception("Wasn't an RSA key, or no private key was present");
}
bool isValid = rsa.VerifyData(
Encoding.UTF8.GetBytes(plainText),
signature,
HashAlgorithmName.SHA256,
RSASignaturePadding.Pkcs1);
if (!isValid)
{
throw new Exception("VerifyData failed");
}
}
答案 1 :(得分:0)
我不清楚为什么要尝试导出CSP参数。 CSP参数导出取决于密钥导出选项,如果密钥不可导出,则会失败。相反,您应该直接在RSACryptoServiceProvider
对象的PrivateKey
属性上使用X509Certificate2
:
// assuming, you have X509Certificate2 object with existing private key in _certPol variable
// retrieve private key
var key = _certPol.PrivateKey as RSACryptoServiceProvider;
// check if it is legacy RSA, otherwise return.
if (key == null) { return; }
byte[] dataToSign = Encoding.UTF8.GetBytes(plainText);
// sign data
byte[] signature = key.SignData(dataToSign, "SHA256");
// Verify signature
if (!key.VerifyData(dataToSign, "SHA256", signature))
throw new Exception("Nepodařilo se vytvořit platný podpisový kód poplatníka.");
...
答案 2 :(得分:0)
工作状态是:
从商店加载证书:
var store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
try
{
store.Open(OpenFlags.ReadOnly);
foreach (var certificate in store.Certificates)
{
if (certificate.FriendlyName.Equals(certificateName) && certificate.NotAfter.Equals(notAfter))
{
_certPopl = certificate;
break;
}
}
}
finally
{
store.Close();
}
签署并验证数据:
byte[] dataToSign = Encoding.UTF8.GetBytes(plainText);
var privKey = (RSACryptoServiceProvider)_certPopl.PrivateKey;
// Force use of the Enhanced RSA and AES Cryptographic Provider with openssl-generated SHA256 keys
var enhCsp = new RSACryptoServiceProvider().CspKeyContainerInfo;
var cspparams = new CspParameters(enhCsp.ProviderType, enhCsp.ProviderName, privKey.CspKeyContainerInfo.KeyContainerName);
privKey = new RSACryptoServiceProvider(cspparams);
byte[] signature = privKey.SignData(dataToSign, "SHA256");
// Verify signature
if (!privKey.VerifyData(dataToSign, "SHA256", signature))
throw new Exception("Nepodařilo se vytvořit platný podpisový kód poplatníka.");