Instantiating a X509Certificate object in C# which holds a private key as well

2.2k views Asked by At

I'm trying to implement a secure TCP server and as the result I need to create an object of class X509Certificate2 in order to authenticate the clients.

I believe such a certificate object should contain the private key (as well) in order to be able to decrypt incoming messages, isn't that true? Well no matter how I generate a certificate file, when I give its file address to X509Certificate2's constructor the object's HasPrivateKey property is false and clients are not authenticated!

In the Microsoft's page on how to use the X509Certificate2 class, in source code's comments it indicates that the certificate can be generated using makecert program like this:

makecert -r -pe -n "CN=CERT_SIGN_TEST_CERT" -b 01/01/2010 -e 01/01/2012 -sky exchange -ss my

In which -pe switch should include the private key in certificate but looking at the generated file I can tell that it does not do that.

Since I'm implementing this software in Ubuntu using Mono I thought I can use openssl instead. So following the instructions given in this page I created a private key and a public key. X509Certificate2 class accepts the public key as if it was created by makecert command but not the private key (it throws an exception when it is constructed).

There is a relatively old post in SO which asks the same question but it has no accepted answer. And the two given ones suggest using two different formats for certificates, PKCS8 and PKCS12 while in the documentation it is clearly said that X509Certificate make use of PKCS7!

Anyway I'm all confused. Has anyone ever been able to use X509Certificate2 with a private key loaded? How?

1

There are 1 answers

3
gtrig On BEST ANSWER

An X509 certificate should only contain a public key. It binds the public key to an identity and is signed. RFC 5280 contains the details on X509 certificates.

However, the X509Certificate2 object can contain a private key according to the MSDN documentation.

Also, a keystore, such as a PKCS12 keystore can contain a private key and a corresponding certificate.

PKCS7 is a specification for signing and encrypting messages.

PKCS8 is a specification for private keys.

See PKCS for the differences between different PKCS standards.

The MSDN link above has some example C# code to encrypt and decrypt files. It also has an example makecert command line to generate a certificate. However this certificate and associated private key is stored in the Windows local user store, so I'm not sure if that will translate correctly to Ubuntu.

There is also some discussion in this SO question about using PKCS12 keystores to instantiate the X509Certificate2 object and then to access the private key. This might be the better way for you to accomplish your goal. You can use openssl to generate a private key, a signed certificate, and import them into a PKCS12 keystore. You can create a PKCS12 keystore using the commands here. For example, create a text file (file.pem) containing both the PEM format of your private key and corresponding X509 certificate. Then run this command:

openssl pkcs12 -export -in file.pem -out file.p12 -name "My Certificate"

Also on the makecert documentation page, it says, "for testing purposes only". So I wouldn't depend on those certificates for a production secure server.