如何从 PKCS#12 字节数组构造 X509Certificate2 抛出 CryptographicException(“系统找不到指定的文件.")? [英] How can constructing an X509Certificate2 from a PKCS#12 byte array throw CryptographicException("The system cannot find the file specified.")?

查看:13
本文介绍了如何从 PKCS#12 字节数组构造 X509Certificate2 抛出 CryptographicException(“系统找不到指定的文件.")?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to construct an X509Certificate2 from a PKCS#12 blob in a byte array and getting a rather puzzling error. This code is running in a desktop application with administrator rights on Windows XP.

堆栈跟踪如下,但我在尝试排除故障时迷路了,因为 _LoadCertFromBlob 被标记为 [MethodImpl(MethodImplOptions.InternalCall)].

The stack trace is as follows, but I got lost trying to troubleshoot because _LoadCertFromBlob is marked [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 for C#<生成的真正 PKCS#12/a> 包含 RSA 私钥和证书(自签名或最近向 CA 注册)——我正在尝试将私钥和证书从 BouncyCastle 库转换为 System.Security.Cryptography 库通过从一个导出并导入到另一个.该代码适用于它尝试过的绝大多数系统.我只是从未见过该构造函数抛出的特定错误.那个盒子上可能有某种环境怪异.

The blob is a true PKCS#12 generated by BouncyCastle for C# containing a RSA private key and certificate (either self-signed or recently enrolled with a CA) -- what I'm trying to do is convert the private key and certificate from the BouncyCastle library to the System.Security.Cryptography library by exporting from one and importing to the other. This code works on the vast majority of systems it's been tried on; I've just never seen that particular error thrown from that constructor. It may be some sort of environmental weirdness on that one box.

编辑 2: 错误发生在不同城市的不同环境中,我无法在本地重现它,因此我最终可能不得不将其归咎于 XP 损坏安装.

EDIT 2: The error is occurring in a different environment in a different city, and I'm unable to reproduce it locally, so I may end up having to chalk it up to a broken XP installation.

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

Since you asked, though, here is the fragment in question. The code takes a private key and certificate in BouncyCastle representation, deletes any previous certificates for the same Distinguished Name from the personal key store, and imports the new private key and certificate into the personal key store via an intermediate 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();

推荐答案

你有 PKCS#12 还是只有 PFX 文件?在 Microsoft 世界中是一样的,但其他人认为不同(参见 此存档页面).

Do you have PKCS#12 or just PFX-file? In the Microsoft world it is the same, but other think another (see this archived page).

你可以试试关注

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

(X509Certificate2(Byte[])) 或

X509Certificate2 cert = X509Certificate2("C:Pathmy.pfx", "password");

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

(see X509Certificate2(String, String) and Import(String, String, X509KeyStorageFlags) on Microsoft Docs if you need use some flags)

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

UPDATED: It would be helpful if you insert a code fragment and not only the exception stack trace.

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

Which X509KeyStorageFlags do you use? You can use Process Monitor to find out which file could not find the X509Certificate2 constructor. It can be for example that there are no default key container for the current user on the Windows XP having the problem. You can create it and retry the import.

这篇关于如何从 PKCS#12 字节数组构造 X509Certificate2 抛出 CryptographicException(“系统找不到指定的文件.")?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆