- 我不认为这个问题与代码相关; 我的代码在其他计算机上运行良好,并且该问题影响了来自Microsoft的示例代码。
- 证书以PFX文件的形式提供,仅用于测试目的,因此它还包括一个虚拟的认证机构。
- 使用MMC.exe,我可以将证书导入到本地计算机的个人存储中,然后授予所有相关帐户的私钥权限,并将认证机构拖放到“受信任的根证书颁发机构”中。
- 使用C#,我可以加载证书(由其指纹标识),并验证它是否具有私钥,使用
X509Certificate2.HasPrivateKey
。 但是,尝试读取密钥会导致错误。 在.NET中,当尝试访问属性X509Certificate2.PrivateKey
时,会抛出CryptographicException
异常,其中错误消息为“指定了无效的提供程序类型”。 在Win32中,调用方法CryptAcquireCertificatePrivateKey
会返回相应的HRESULT,NTE_BAD_PROV_TYPE
。 - 当使用Microsoft自己的两个代码示例读取证书的私钥时,也会出现此相同的异常。
- 将相同的证书安装在当前用户等效存储中,而不是本地计算机中,可以成功加载私钥。
- 我在Windows 8.1上拥有本地管理员权限,并尝试以正常和提升的模式运行我的代码。 使用同一证书的同事在Windows 7和Windows 8上能够从本地计算机存储中加载密钥。
- 我可以成功读取位于相同存储位置的自签名IIS测试证书的私钥。
- 我已经瞄准.NET 4.5(这个错误已经报告了某些旧版本的框架)。
- 我不认为这是与证书模板有关的问题,因为我希望它会对本地计算机和当前用户存储都产生影响?
与我的同事不同,我已经多次尝试使用各种方法卸载和重新安装证书,包括通过IIS Manager并包括来自相同发行者的旧证书。 我在MMC中看不到任何旧的或重复的证书痕迹。 但是,我有许多大小相同的私钥文件,根据上一次写入时间,它们必须是在各种安装尝试之后留下的。 这些文件分别位于本地计算机和当前用户存储的以下位置:
c:\ ProgramData \ Microsoft \ Crypto \ RSA \ MachineKeys
c:\ Users \\ AppData \ Roaming \ Microsoft \ Crypto \ RSA \ S-1-5-21-[rest of user ID]
因此,是否有人可以建议:
- 使用MMC卸载证书,删除所有看起来像是孤立的私钥的文件,然后重新安装证书并重试是否是一个好主意?
- 还有其他文件应该尝试手动删除吗?
- 是否还应尝试其他操作?
更新 - 添加了一个代码
static void Main()
{
// Exception occurs when trying to read the private key after loading certificate from here:
X509Store store = new X509Store("MY", StoreLocation.LocalMachine);
// Exception does not occur if certificate was installed to, and loaded from, here:
//X509Store store = new X509Store("MY", StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
X509Certificate2Collection collection = (X509Certificate2Collection)store.Certificates;
X509Certificate2Collection fcollection = (X509Certificate2Collection)collection.Find(X509FindType.FindByTimeValid, DateTime.Now, false);
X509Certificate2Collection scollection = X509Certificate2UI.SelectFromCollection(fcollection, "Test Certificate Select", "Select a certificate from the following list to get information on that certificate", X509SelectionFlag.MultiSelection);
Console.WriteLine("Number of certificates: {0}{1}", scollection.Count, Environment.NewLine);
foreach (X509Certificate2 x509 in scollection)
{
try
{
Console.WriteLine("Private Key: {0}", x509.HasPrivateKey ? x509.PrivateKey.ToXmlString(false) : "[N/A]");
x509.Reset();
}
catch (CryptographicException ex)
{
Console.WriteLine(ex.Message);
}
}
store.Close();
Console.ReadLine();
}