我正在尝试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();