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

2023-09-03 00:05:36 作者:半夜浅唱、撕心裂肺的伤

我试图构建一个 X509Certificate2 从PKCS#12 BLOB的字节数组,并得到一个相当令人费解的错误。这code运行在Windows XP上的管理员权限的桌面应用程序。

堆栈跟踪如下所示,但我失去了试图解决,因为 _LoadCertFromBlob 标记 [MethodImpl(MethodImplOptions.InternalCall)]

  System.Security.Cryptography.CryptographicException:系统找不到指定的文件。
  在System.Security.Cryptography.CryptographicException.ThrowCryptogaphicException(的Int32小时)
  在System.Security.Cryptography.X509Certificates.X509Utils._LoadCertFromBlob(字节[] RAWDATA,IntPtr的密码,UInt32的dwFlags中,布尔persistKeySet,SafeCertContextHandle和放大器; pCertCtx)
  在System.Security.Cryptography.X509Certificates.X509Certificate.LoadCertificateFromBlob(字节[] RAWDATA,对象密码,X509KeyStorageFlags keyStorageFlags)
  在System.Security.Cryptography.X509Certificates.X509Certificate2..ctor(字节[] RAWDATA,字符串密码,X509KeyStorageFlags keyStorageFlags)
 

编辑:的斑点是由 BouncyCastle的为C#含有产生真正的PKCS#12 RSA私钥和证书(自签名或最近参加了加利福尼亚州) - 我想要做的是从一个出口将来自BouncyCastle的库中的System.Security.Cryptography库中的私钥和证书,并导入到其他。这code工作在它一直试图在绝大多数系统;我只是从没见过从构造函数抛出特定的错误。这可能是某种形式的,一个箱子环保古怪的。

编辑2:的错误发生在不同的环境在不同的城市,我无法在本地重现它,所以我可能最终不得不记在一个破碎的XP安装。

既然你这么问,不过,这里是有问题的片段。在code需要在BouncyCastle的重新presentation私钥和证书,删除任何previous证书从个人密钥存储相同的专有名称,并导入新的私钥和证书到个人密钥存储经由中间PKCS#12斑点

  //打开个人密钥库
VAR msMyStore =新的X509Store(StoreName.My);
msMyStore.Open(OpenFlags.MaxAllowed);

//删除对相同的DN pviously发出的任何证书$ P $
VAR oldCerts =
    msMyStore.Certificates.Cast< X509Certificate2>()
        。凡(C => X509Name
                        .GetInstance(Asn1Object.FromByteArray(c.SubjectName.RawData))
                        .Equivalent(CurrentCertificate.SubjectDN))
        .ToArray();
如果(oldCerts.Length大于0)msMyStore.RemoveRange(新X509Certificate2Collection(oldCerts));

//构建私钥和证书PKCS#12斑点
VAR pkcs12store =新Pkcs12StoreBuilder()建立()。
pkcs12store.SetKeyEntry(_Pkcs12KeyName,
                        新AsymmetricKeyEntry(KeyPair.Private)
                        新的[] {新X509CertificateEntry(CurrentCertificate)});
VAR pkcs12data =新的MemoryStream();
pkcs12store.Save(pkcs12data,_Pkcs12Password.ToCharArray(),随机);

//并将其导入。此构造函数调用炸毁
_MyCertificate2 =新X509Certificate2(pkcs12data.ToArray()
                                       _Pkcs12Password,
                                       X509KeyStorageFlags.Exportable);
msMyStore.Add(_MyCertificate2);
msMyStore.Close();
 

解决方案

你有PKCS#12或只是PFX文件?在微软的世界是一样的,但其他另想(见http://www.drh-consultancy.demon.co.uk/pkcs12faq-old.html#PFX).

宽字节注入

您可以尝试只以下

  X509Certificate2证书= X509Certificate2(byte []的RAWDATA,密码);
X509Certificate2 cert2 = X509Certificate2(byte []的RAWDATA,密码,
              X509KeyStorageFlags.MachineKeySet |
              X509KeyStorageFlags.PersistKeySet |
              X509KeyStorageFlags.Exportable);
 

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

  X509Certificate2证书= X509Certificate2(C:\路径\ my.pfx​​,密码);
 

(见http://msdn.microsoft.com/en-us/library/ms148420.aspx和http://msdn.microsoft.com/en-us/library/ms148442.aspx如果你需要用一些标志)

更新时间::如果你插入一个code片段,这将是有益的,不仅异常堆栈跟踪

其中 X509KeyStorageFlags ,你呢?您可以使用进程监视器,以找出哪些文件无法找到 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.

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)

EDIT: 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.

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.

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();

解决方案

Do you have PKCS#12 or just PFX-file? In the Microsoft world it is the same, but other think another (see http://www.drh-consultancy.demon.co.uk/pkcs12faq-old.html#PFX).

You can try just following

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

(see http://msdn.microsoft.com/en-us/library/ms148418.aspx) or

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

(see http://msdn.microsoft.com/en-us/library/ms148420.aspx and http://msdn.microsoft.com/en-us/library/ms148442.aspx if you need use some flags)

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

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.