我正在尝试从字节数组中的PKCS#12 blob构造一个X509Certificate2
,但是遇到了一个相当令人困惑的错误。这段代码在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 for C#生成的真正的PKCS#12,其中包含一个RSA私钥和证书(自签名或最近由CA注册)——我的目标是将BouncyCastle库中的私钥和证书转换为System.Security.Cryptography库,通过从一个库导出并导入到另一个库中。这段代码在大多数系统上都可以工作;我只是从来没有见过这个特定的错误从那个构造函数中抛出。它可能是某种环境上的奇怪问题。
编辑2:错误发生在另一个城市的不同环境中,我无法在本地重现它,所以我可能会将其归咎于破损的XP安装。
既然你问了,这里就是有问题的代码片段。该代码接受以BouncyCastle表示的私钥和证书,从个人密钥存储中删除任何先前具有相同Distinguished Name的证书,并通过一个中间的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();
PersistKeySet
在您的情况下不好用,那么您应该不使用它。另一方面,如果使用PersistKeySet
导入证书,则密钥将被放置在密钥存储中作为文件(在用户配置文件中)。使用CertGetCertificateContextProperty
和CERT_KEY_PROV_INFO_PROP_ID
获取信息。可以使用PP_UNIQUE_CONTAINER
获取文件名。该文件位于CommonApplicationData
下(带有Microsoft\Crypto\RSA\MachineKeys
后缀)。 - Oleg