39

我正在尝试X509Certificate2从字节数组中的 PKCS#12 blob 构造一个并得到一个相当令人费解的错误。此代码在 Windows XP 上具有管理员权限的桌面应用程序中运行。

堆栈跟踪如下,但由于_LoadCertFromBlob标记为[MethodImpl(MethodImplOptions.InternalCall)].

System.Security.Cryptography.CryptographicException: The system cannot find the file specified.
  at System.Security.Cryptography.CryptographicException.ThrowCryptogaphicException(Int32 hr)
  at System.Security.Cryptography.X509Certificates.X509Utils._LoadCertFromBlob(Byte[] rawData, IntPtr password, UInt32 dwFlags, Boolean persistKeySet, SafeCertContextHandle& pCertCtx)
  at System.Security.Cryptography.X509Certificates.X509Certificate.LoadCertificateFromBlob(Byte[] rawData, Object password, X509KeyStorageFlags keyStorageFlags)
  at System.Security.Cryptography.X509Certificates.X509Certificate2..ctor(Byte[] rawData, String password, X509KeyStorageFlags keyStorageFlags)

编辑: blob 是由BouncyCastle 为 C#生成的真正的 PKCS#12,包含 RSA 私钥和证书(自签名或最近使用 CA 注册)——我要做的是转换私钥和证书从 BouncyCastle 库到 System.Security.Cryptography 库,方法是从一个库导出并导入到另一个库。该代码适用于它尝试过的绝大多数系统。我只是从未见过该构造函数抛出的特定错误。在那个盒子上可能是某种环境怪异。

编辑2:错误发生在不同城市的不同环境中,我无法在本地重现它,所以我最终可能不得不将其归结为XP安装损坏。

不过,既然你问了,这是有问题的片段。该代码采用 BouncyCastle 表示形式的私钥和证书,从个人密钥存储中删除相同专有名称的任何先前证书,并通过中间 PKCS#12 blob 将新的私钥和证书导入个人密钥存储。

// open the personal keystore
var msMyStore = new X509Store(StoreName.My);
msMyStore.Open(OpenFlags.MaxAllowed);

// remove any certs previously issued for the same DN
var oldCerts =
    msMyStore.Certificates.Cast<X509Certificate2>()
        .Where(c => X509Name
                        .GetInstance(Asn1Object.FromByteArray(c.SubjectName.RawData))
                        .Equivalent(CurrentCertificate.SubjectDN))
        .ToArray();
if (oldCerts.Length > 0) msMyStore.RemoveRange(new X509Certificate2Collection(oldCerts));

// build a PKCS#12 blob from the private key and certificate
var pkcs12store = new Pkcs12StoreBuilder().Build();
pkcs12store.SetKeyEntry(_Pkcs12KeyName,
                        new AsymmetricKeyEntry(KeyPair.Private),
                        new[] {new X509CertificateEntry(CurrentCertificate)});
var pkcs12data = new MemoryStream();
pkcs12store.Save(pkcs12data, _Pkcs12Password.ToCharArray(), Random);

// and import it.  this constructor call blows up
_MyCertificate2 = new X509Certificate2(pkcs12data.ToArray(),
                                       _Pkcs12Password,
                                       X509KeyStorageFlags.Exportable);
msMyStore.Add(_MyCertificate2);
msMyStore.Close();
4

5 回答 5

46

你有 PKCS#12 还是只有 PFX 文件?在 Microsoft 世界中它是相同的,但其他人认为不同(请参阅此存档页面)。

您可以尝试以下

X509Certificate2 cert = X509Certificate2(byte[] rawData, "password");
X509Certificate2 cert2 = X509Certificate2(byte[] rawData, "password",
              X509KeyStorageFlags.MachineKeySet |
              X509KeyStorageFlags.PersistKeySet |
              X509KeyStorageFlags.Exportable);

( X509Certificate2(Byte[]) ) 或

X509Certificate2 cert = X509Certificate2("C:\Path\my.pfx", "password");

(如果您需要使用一些标志,请参阅 Microsoft Docs 上的X509Certificate2(String, String)Import(String, String, X509KeyStorageFlags) )

更新:如果您插入代码片段而不仅仅是异常堆栈跟踪,这将很有帮助。

你用哪个X509KeyStorageFlags?您可以使用Process Monitor找出哪个文件找不到X509Certificate2构造函数。例如,在出现问题的 Windows XP 上,当前用户没有默认密钥容器。您可以创建它并重试导入。

于 2010-09-29T22:34:47.430 回答
10

我遇到了同样的问题。

根据这篇旧知识库文章,问题在于构造函数试图将证书加载到当前用户的配置文件中,但是我模拟用户的 .Net 代码没有加载用户配置文件。构造函数需要加载的用户配置文件才能正常工作。

来自文章:

X509Certificate2 类构造函数尝试将证书导入到运行应用程序的用户帐户的用户配置文件中。很多时候,ASP.NET 和 COM+ 应用程序模拟客户端。当他们这样做时,出于性能原因,他们不会为模拟用户加载用户配置文件。因此,他们无法访问模拟用户的“用户”证书存储。

加载用户配置文件修复了错误。

于 2014-08-15T23:09:53.320 回答
5

我有同样的问题。

  1. 在托管站点的服务器上打开 IIS。
  2. 找到该站点的应用程序池。
  3. 单击高级设置。
  4. 将“加载用户配置文件”更改为 true。(可能需要重新启动或重新启动)

这允许加密子系统工作。

在此处输入图像描述

于 2017-03-06T01:07:31.410 回答
4

在 Windows 2012 上的 Web 应用程序中遇到此问题,将应用程序池选项设置Load User Profile为 true 使其工作。

为此,请运行inetmgr.exe,转到Advanced Settings正确的应用程序池,将其更改Load User ProfileProcess Modeltrue。

于 2016-03-19T07:37:26.777 回答
1

我有完全相同的问题。在特定用户下运行时,相同的代码和数据/证书在 Windows 2003 x86 上运行良好,但在另一个帐户下失败(该帐户也用于运行 IIS 应用程序池)。

显然,其他一些事情耗尽了 Windows 上的资源,因此失败的用户无法真正加载用户的配置文件(他的桌面看起来很奇怪),尽管Event Viewer 中没有相关事件

重新启动暂时解决了问题。虽然这不是问题的永久解决方案,但它表明还有其他东西(例如,COM+ 组件、本机代码服务等)消耗资源需要调查。这也说明了Windows平台的不稳定性……

于 2011-10-16T15:57:22.210 回答