如何从PKCS#12字节数组构造一个X509Certificate2抛出密码异常(“系统找不到指定的文件”)?

时间:2022-07-12 18:25:42

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.

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

The stack trace is as follows, but I got lost trying to troubleshoot because _LoadCertFromBlob is marked [MethodImpl(MethodImplOptions.InternalCall)].

堆栈跟踪如下所示,但是我在尝试排除故障时丢失了,因为_LoadCertFromBlob被标记为[MethodImpl(method dimploptions.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.

编辑:blob是由BouncyCastle为c#生成的一个真正的PKCS#12,它包含RSA私钥和证书(要么是自签名的,要么是最近注册的CA)——我要做的是将私有密钥和证书从BouncyCastle库转换为System.Security。从其中一个导出并导入到另一个的加密库。这个代码适用于它所尝试过的绝大多数系统;我只是从未见过构造函数抛出的特定错误。这可能是某种环境上的怪异。

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.

编辑2:错误发生在不同城市的不同环境中,我无法在本地复制它,因此我可能不得不将其归咎于XP安装失败。

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.

既然你问了,这就是问题的部分。该代码在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();

5 个解决方案

#1


35  

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).

你有PKCS#12还是pfx文件?在微软的世界里,这是一样的,但是其他人会有不同的看法(见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

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

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)

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

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.

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

#2


8  

I ran into the same issue.

我遇到了同样的问题。

According to this kb article the problem was that the constructor tries to load the cert into the current user's profile, but the .Net code I was impersonating the user and so it had not loaded the user profile. The constructor requires the loaded user profile to work properly.

根据这篇kb文章,问题是构造函数试图将cert加载到当前用户的概要文件中,但是. net代码我模拟了用户,所以它没有加载用户概要文件。构造函数要求加载的用户配置文件正常工作。

From the article:

从这篇文章:

The X509Certificate2 class constructors attempt to import the certificate into the user profile of the user account that the application runs in. Many times, ASP.NET and COM+ applications impersonate clients. When they do, they do not load the user profiles for the impersonated user for performance reasons. So, they cannot access the "User" certificate store for the impersonated user.

X509Certificate2类构造函数尝试将证书导入应用程序运行的用户帐户的用户配置文件。很多时候,ASP。NET和COM+应用程序模拟客户端。当它们加载时,由于性能原因,它们不会加载模拟用户的用户配置文件。因此,他们无法访问模拟用户的“用户”证书存储。

Loading the user profile fixed the error.

加载用户概要文件修复错误。

#3


4  

Running into this in an web application on Windows 2012, Setting application pool option Load User Profile to true made it work.

在Windows 2012上的web应用程序中,将应用程序池选项Load User Profile设置为true,可以使其工作。

To do this, run inetmgr.exe, go to Advanced Settings for the right application pool, change Load User Profile under Process Model to true.

要做到这一点,运行inetmgr。exe,转到正确的应用程序池的高级设置,将流程模型下的Load用户配置文件更改为true。

#4


1  

I had exactly the same problem. The same code and data/certs ran fine on Windows 2003 x86 when running under a specific user, but failed under another account (which was also used for running IIS app pools).

我也有同样的问题。当在特定用户下运行时,Windows 2003 x86上的代码和数据/证书运行良好,但在另一个帐户(也用于运行IIS应用程序池)下运行失败。

Apparently, some other thing exhausted resources on Windows, so that the failing user could not really load the user's profile (his desktop was weird-looking), although there were no related events in Event Viewer.

显然,其他一些东西耗尽了Windows上的资源,导致失败的用户无法真正加载用户的概要文件(他的桌面看上去很奇怪),尽管在事件查看器中没有相关事件。

A reboot solved the problem temporarily. Although this is no permanent solution to the problem, it shows that there's something else (eg, COM+ components, native code services, etc) consuming resources that needs to be investigated. It also shows the instability of Windows platforms...

重新启动暂时解决了这个问题。尽管这不是问题的永久解决方案,但它表明还有一些其他的东西(例如,COM+组件、本地代码服务等)需要研究。这也显示了Windows平台的不稳定性……

#5


1  

I had this same problem.

我也有同样的问题。

  1. Open IIS on the server hosting the site.
  2. 在托管站点的服务器上打开IIS。
  3. Find the application pool for the site.
  4. 找到站点的应用程序池。
  5. Click Advanced Settings.
  6. 点击高级设置。
  7. Change "Load User Profile" to true. (may require restart or reboot)
  8. 将“Load User Profile”更改为true。(可能需要重新启动或重新启动)

This allows the crypto subsystem to work.

这允许加密子系统工作。

如何从PKCS#12字节数组构造一个X509Certificate2抛出密码异常(“系统找不到指定的文件”)?

#1


35  

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).

你有PKCS#12还是pfx文件?在微软的世界里,这是一样的,但是其他人会有不同的看法(见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

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

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)

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

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.

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

#2


8  

I ran into the same issue.

我遇到了同样的问题。

According to this kb article the problem was that the constructor tries to load the cert into the current user's profile, but the .Net code I was impersonating the user and so it had not loaded the user profile. The constructor requires the loaded user profile to work properly.

根据这篇kb文章,问题是构造函数试图将cert加载到当前用户的概要文件中,但是. net代码我模拟了用户,所以它没有加载用户概要文件。构造函数要求加载的用户配置文件正常工作。

From the article:

从这篇文章:

The X509Certificate2 class constructors attempt to import the certificate into the user profile of the user account that the application runs in. Many times, ASP.NET and COM+ applications impersonate clients. When they do, they do not load the user profiles for the impersonated user for performance reasons. So, they cannot access the "User" certificate store for the impersonated user.

X509Certificate2类构造函数尝试将证书导入应用程序运行的用户帐户的用户配置文件。很多时候,ASP。NET和COM+应用程序模拟客户端。当它们加载时,由于性能原因,它们不会加载模拟用户的用户配置文件。因此,他们无法访问模拟用户的“用户”证书存储。

Loading the user profile fixed the error.

加载用户概要文件修复错误。

#3


4  

Running into this in an web application on Windows 2012, Setting application pool option Load User Profile to true made it work.

在Windows 2012上的web应用程序中,将应用程序池选项Load User Profile设置为true,可以使其工作。

To do this, run inetmgr.exe, go to Advanced Settings for the right application pool, change Load User Profile under Process Model to true.

要做到这一点,运行inetmgr。exe,转到正确的应用程序池的高级设置,将流程模型下的Load用户配置文件更改为true。

#4


1  

I had exactly the same problem. The same code and data/certs ran fine on Windows 2003 x86 when running under a specific user, but failed under another account (which was also used for running IIS app pools).

我也有同样的问题。当在特定用户下运行时,Windows 2003 x86上的代码和数据/证书运行良好,但在另一个帐户(也用于运行IIS应用程序池)下运行失败。

Apparently, some other thing exhausted resources on Windows, so that the failing user could not really load the user's profile (his desktop was weird-looking), although there were no related events in Event Viewer.

显然,其他一些东西耗尽了Windows上的资源,导致失败的用户无法真正加载用户的概要文件(他的桌面看上去很奇怪),尽管在事件查看器中没有相关事件。

A reboot solved the problem temporarily. Although this is no permanent solution to the problem, it shows that there's something else (eg, COM+ components, native code services, etc) consuming resources that needs to be investigated. It also shows the instability of Windows platforms...

重新启动暂时解决了这个问题。尽管这不是问题的永久解决方案,但它表明还有一些其他的东西(例如,COM+组件、本地代码服务等)需要研究。这也显示了Windows平台的不稳定性……

#5


1  

I had this same problem.

我也有同样的问题。

  1. Open IIS on the server hosting the site.
  2. 在托管站点的服务器上打开IIS。
  3. Find the application pool for the site.
  4. 找到站点的应用程序池。
  5. Click Advanced Settings.
  6. 点击高级设置。
  7. Change "Load User Profile" to true. (may require restart or reboot)
  8. 将“Load User Profile”更改为true。(可能需要重新启动或重新启动)

This allows the crypto subsystem to work.

这允许加密子系统工作。

如何从PKCS#12字节数组构造一个X509Certificate2抛出密码异常(“系统找不到指定的文件”)?