当我使用以下代码从本地或天蓝网站访问文件系统中的证书时,我没有遇到任何问题:
X509Certificate2 certificate = new X509Certificate2(keyFilePath, "mysecret", X509KeyStorageFlags.MachineKeySet |
X509KeyStorageFlags.PersistKeySet |
X509KeyStorageFlags.Exportable);
但是,当我按照https://azure.microsoft.com/en-us/blog/using-certificates-in-azure-websites-applications/中的说明使用azure证书存储区时,一切都适用于前3到9个请求,所有后续调用都在以下行中失败
var rsa = certificate.PrivateKey as RSACryptoServiceProvider;
错误“System.Security.Cryptography.CryptographicException:Keyset不存在”,直到网站重新启动,然后将为另一个至少3个请求工作。
我很困惑为什么它适用于至少3个和最多9个请求,然后总是因错误而失败。我很感激任何建议。
答案 0 :(得分:1)
从PFX加载时,您指定的是PersistKeySet,通常只应在计划将证书持久保存到证书库时设置。虽然代码的某些方面可能通过将RSACryptoServiceProvider对象的PersistKeyInCsp
标记为false
来尝试变得聪明并清理它自己的私钥,但是有可能。
我指出这一点的原因是“Keyset不存在”错误几乎总是意味着“证书存储被告知私钥存在,但有人已经删除它而没有通知证书存储”。最可能的罪魁祸首是某处设置PersistKeyInCsp
到false
(这意味着“删除Dispose / Finalize上的密钥文件”)。
如果您将PersistKeyInCsp设置为false但未手动处理该对象,则会因终结器而得到延迟清理,这可以解释为什么它是3-9次成功而不是确定性数字。
(我也不得不指出你应该使用cert.GetRSAPrivateKey()
而不是cert.PrivateKey
,因为a)它是类型安全的,b)它是来电者拥有的生命(你应该处置)它)而不是共享/模糊的生命。它使事情变得更加可预测,尽管它几乎从不返回RSACryptoServiceProvider,所以你不应该尝试强制转换它。)
答案 1 :(得分:0)
看起来像显式处置(使用using
关键字)可以解决此问题:
using (X509Certificate2 certificate = new X509Certificate2(keyFilePath, "mysecret", X509KeyStorageFlags.MachineKeySet |
X509KeyStorageFlags.PersistKeySet |
X509KeyStorageFlags.Exportable))
{
// ... use cert
}
答案 2 :(得分:0)
一个单身人士为我工作:
class static CertificateSingleton
{
private static X509Certificate2 certificate;
public Get()
{
if (certificate == null)
{
byte[] certificateBytes = .....;
string password = .....;
certificate = new X509Certificate2(certificateBytes, password, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable);
}
return certificate;
}
}
因此,每次我想使用它时,我都使用CertificatesSingleton.Get()
,这保证了我每次都使用相同的实例。