如何从PKCS#12字节数组构造X509Certificate2抛出CryptographicException("系统找不到指定的文件.")?

Jef*_*tin 37 .net c# cryptography pkcs#12 x509certificate2

我正在尝试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)
Run Code Online (Sandbox Code Playgroud)

编辑: 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();
Run Code Online (Sandbox Code Playgroud)

Ole*_*leg 43

你有PKCS#12还是只有PFX文件?在微软世界中它是相同的,但其他人认为另一个(参见http://www.drh-consultancy.demon.co.uk/pkcs12faq-old.html#PFX).

您可以尝试以下

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

(请参阅http://msdn.microsoft.com/en-us/library/ms148418.aspx)或

X509Certificate2 cert = X509Certificate2("C:\Path\my.pfx", "password");
Run Code Online (Sandbox Code Playgroud)

(如果需要使用一些标志,请参阅http://msdn.microsoft.com/en-us/library/ms148420.aspxhttp://msdn.microsoft.com/en-us/library/ms148442.aspx)

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

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

  • 添加X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | 从byte []加载时,X509KeyStorageFlags.Exportable到构造函数. (4认同)
  • 我在Windows Server 2012上遇到了同样的错误,因为完全相同的代码在Windows 7或Azure云中没有问题.将标志更改为MachineKeySet可以解决问题. (2认同)
  • 请注意此示例中的PersistKetSet标志 - 它会将关键文件保留在磁盘上,而这些文件永远不会被清除.如果你经常拨打这个电话,那么你最终会得到一个巨大的清理任务.(问我怎么知道.)如果你只在内存中使用cert,那么只需指定MachineKeySet.如果您在代码中完成了内存中的证书,请调用Reset方法立即删除密钥文件.不过,最好一次添加到商店并重新加载.这就是它的用途. (2认同)

Zai*_*zvi 10

我遇到了同样的问题.

根据这篇kb文章,问题是构造函数尝试将cert加载到当前用户的配置文件中,但.Net代码我冒充用户,因此它没有加载用户配置文件.构造函数要求加载的用户配置文件正常工作.

来自文章:

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

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


paq*_*mez 5

我有同样的问题。

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

这允许加密子系统工作。

在此处输入图片说明