Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to programmatically import a pfx with a chain of certificates into the certificate store?

Tags:

I am trying to programmatically import a X509 certificate (pfx / PKCS#12) in my local machine's certificate store. This particular certificate has a chain of certificates, the certification path looks something like this:

  • Root certificate CA
    • Organization certificate CA
      • Organization 2 certificate CA
        • My certificate

The code I use looks like this:

cert = new X509Certificate2(pathToCert, password);  if (cert != null) {     var store = new X509Store(StoreName.My, StoreLocation.LocalMachine);     store.Open(OpenFlags.ReadWrite);     if (!store.Certificates.Contains(cert))     {         store.Add(cert);     } } 

This code does import the certificate, however it seems to ignore the chain. If I check the certificate in the store, the certification path only shows:

  • My certificate

However when I import the pfx manually, it does show the full path. Am I skipping a step here, or am I missing some parameter? Can someone shed some light on this?

like image 830
Edwin de Koning Avatar asked Feb 04 '12 13:02

Edwin de Koning


People also ask

How do I import a PFX to a certificate store?

Start Windows Explorer and select and hold (or right-click) the . pfx file, then select Open to open the Certificate Import Wizard. Follow the procedure in the Certificate Import Wizard to import the code-signing certificate into the Personal certificate store.

Does a PFX file contain the certificate chain?

A PFX file, also known as PKCS #12 , is a single, password protected certificate archive that contains the entire certificate chain plus the matching private key. Essentially it is everything that any server will need to import a certificate and private key from a single file.

How do I import a certificate into a personal store?

Right-click the Personal folder, select All tasks and Import… Type the file name or click Browse and select the certificate you want to import. Certificate store.


1 Answers

You should be able to iterate over the certs in your PFX (and import each into the cert store of your choice) by opening the PFX file as an X509Certificate2Collection object.

Here are the docs on X509Certificate2Collection:

http://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates.x509certificate2collection.aspx

MSDN provides some sample code in that docs page on how to inspect each cert in the collection.

Once you know the CNs/Issuers/other info about each cert it should be clear which certificate store each one needs to be added to. For that you can use the X509Store class and the StoreName enumeration to specify which store you want to open/add to:

http://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates.x509store.aspx

http://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates.storename.aspx

Also see my answer to a similar SO question:

How to retrieve certificates from a pfx file with c#?

As mentioned in one of the latest comments on that answer, when you try to import a cert to the current user's Root store ("StoreName.Root" and "StoreLocation.CurrentUser" as the name/location) you will get a popup dialog asking you to confirm.

To solve that I just added a little MS UI Automation code to my cert import method, to click OK on the prompt.

Or, as the commenter "CodeWarrior" says in the other SO answer's comment, to avoid the popup dialog you can try putting the root cert into the LocalMachine store instead of CurrentUser.

Sample code:

string certPath = <YOUR PFX FILE PATH>; string certPass = <YOUR PASSWORD>;  // Create a collection object and populate it using the PFX file X509Certificate2Collection collection = new X509Certificate2Collection(); collection.Import(certPath, certPass, X509KeyStorageFlags.PersistKeySet);  foreach (X509Certificate2 cert in collection) {     Console.WriteLine("Subject is: '{0}'", cert.Subject);     Console.WriteLine("Issuer is:  '{0}'", cert.Issuer);      // Import the certificate into an X509Store object } 
like image 165
Bill Agee Avatar answered Sep 28 '22 12:09

Bill Agee