【发布时间】:2014-04-30 04:20:44
【问题描述】:
我正在尝试读取第三方服务提供商与我共享的证书的私钥,因此我可以使用它来加密某些 XML,然后再通过网络将其发送给他们。我在 C# 中以编程方式执行此操作,但我认为这是权限或配置错误问题,因此我将重点关注似乎最相关的事实:
- 我认为这个问题与代码无关;我的代码可以在其他计算机上运行,并且该问题会影响 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 管理器以及来自同一颁发者的旧证书。我在 MMC 中看不到任何旧证书或重复证书的痕迹。但是,我确实有许多大小相同的私钥文件,根据上次写入时间,在我进行各种安装尝试后,这些文件肯定被遗忘了。这些位于以下位置,分别用于本地计算机和当前用户存储:
c:\ProgramData\Microsoft\Crypto\RSA\MachineKeys
c:\Users\\AppData\Roaming\Microsoft\Crypto\RSA\S-1-5-21-[其余用户 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();
}
【问题讨论】:
-
我建议您发布相关代码...
-
@DavidW 请参阅上面的代码示例,正如您所建议的那样 - 但是,我认为这几乎肯定是证书配置错误或文件损坏的问题,而不是编码错误。
-
嗯......如果它与编程无关,很难诊断出这样的事情,但我做了一点窥探,发现了以下内容:blogs.msdn.com/b/alejacma/archive/2009/12/22/… 这听起来可能是相关的(晦涩的无效提供者类型除外。读取私钥)..
-
@DavidW 好主意,谢谢!尝试访问可疑证书的密钥时,进程监视器中不会出现 ACCESS DENIED。不过,我确实证明了您的建议的概念,方法是拥有我的 IIS 测试证书的密钥文件并拒绝自己访问。 Process Monitor 检测到了,但抛出的异常略有不同:“Keyset 不存在”。
-
抱歉,我们从未找到解决方案,最终从 IT 部门获得了一个新系统。祝你好运!
标签: c# windows certificate mmc certificate-store