How to Install a Certificate into the Local MAChine Store Programmatically Using C#

How can I install a certificate into the local machine store programmatically using c#?

I believe that this is correct:

using (X509Store store = new X509Store(StoreName.TrustedPeople, StoreLocation.LocalMachine)) 
{
store.Open(OpenFlags.ReadWrite);
store.Add(cert); //where cert is an X509Certificate object
}

How to programmatically add x509 certificate to local machine store using c#

Thank you to Oscar and Bob for asking the questions and leading me in the right direction +10 to you both :)

My issue, as I think we all knew (even me) was the user running the application had insufficient privilages to add a certificate to the local machine store.

But various attempts to elevate the user permissions were failing for me, let me explain why.

I had 3 seperate projects in my solution, the wcf service which requires the X509certificates, the windows form client and the cryptography class library which, amongst other things, installs the certificates provided via the windows form client.

As most of the code within all 3 projects could run without elevated permissions, I really wanted to only elevate them at the certificate install stage within the class library but I tried to use Process and Verb= "runas" in code and this didn't work.
Then I tried to add a custom manifest but if you try to alter the properties of a class library to use a custom manifest, you'll find the option is disabled.

So I changed things.
My cryptography class is now within my windows form client and I've added the custom manifest to the client. This now means the whole client opens with elevated privilages but I'd rather that than the alternative.

Thank you again

how to install the certificate in certificate store without private key?

Get a copy of public part of the certificate and add it to the store. That is, replace this line:

store.Add(cert);

with this:

store.Add(new X509Certificate2(cert.RawData));

in this case, you will install only public part of the certificate without associating it with private key.

Programmatically adding certificate to personal store

This line:

var cert = new X509Certificate2("location.pfx", "password", X509KeyStorageFlags.MachineKeySet);

should have been

var cert = new X509Certificate2("location.pfx", "password", X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet);

It was X509KeyStorageFlags.PersistKeySet that was missing.

I got some helpful information on certificates from here.

Add certificate to Trusted Publisher programmatically

The problem is that you are installing the certificate in CurrentUser store, while it must be presented in LocalMachine store. Certutil defaults to local machine.

X509Store store = new X509Store(StoreName.TrustedPublisher, StoreLocation.LocalMachine);

Install SSL certificate programmatically using Microsoft.Web.Administration

There is a method overload for adding Bindings that will add the certificate to HTTP.sys correctly, see: http://msdn.microsoft.com/en-us/library/bb355650(v=VS.90).aspx

Optionally you can actually set the binding settings:

binding.CertificateHash and binding.CertificateStoreName and when commiting it will register correctly with HTTP.sys:
http://msdn.microsoft.com/en-us/library/microsoft.web.administration.binding_properties(v=VS.90).aspx

Cannot find the certificate in either the LocalMachine store or the CurrentUser store

That means,

  • probably you have the wrong certificates installed.
  • you installed the certificates to the wrong place.

An easy way to tell if you have a client certificate installed properly is

  1. launch IE.
  2. Open Tools | Internet options.
  3. In Content tab, click Certificates button.

Then you should see the cert in Personal (read cert path and see whether it contains errors), and will be able to use it in your WinForms application.

Import X509 certificate to certlm with private key (.NET Core 6)

How can I import the cert + private key without resorting to this awkward workaround?

By creating the key as a persisted key to begin with.

using RSA rsa = RSA.Create(2048);

This line creates an ephemeral (in-memory only) private key. Instead you can do

CngKeyCreationParameters keyParams = new CngKeyCreationParameters
{
ExportPolicy = CngExportPolicies.AllowPlaintextExport,
KeyCreationOptions = CngKeyCreationOptions.MachineKey,
Parameters =
{
new CngProperty("Length", BitConverter.GetBytes(2048), CngPropertyOptions.Persist),
},
};

using CngKey cngKey = CngKey.Create(CngAlgorithm.Rsa, Guid.NewGuid().ToString("D"), keyParams);
using RSA rsa = new RSACng(cngKey);

And now the created certificate is associated with an already-persisted key.

(Note that this snippet uses MachineKey and exportable because that's what the question has as the PFX import flags)



Related Topics



Leave a reply



Submit