8

I'm working on some code that currently uses OpenSSL.net to create a public/private key pair for a Certificate Signing Request. The request is equipped with the public key and sent to a CA which returns a signed certificate. Then the previously created private key is added to the certificate:

myCert.PrivateKey = CryptoKey.FromPrivateKey(rsa.PrivateKeyAsPEM, null);

The problem is I need a .net X509Certificate because the rest of the software uses SslStream and other .net classes for TLS.

I was able to create a certificate from the CA's response, but I did not find a way to add the private key to it. I also tried creating an OpenSSL certificate from the CA's response, exporting that as DER or PEM and creating the .net certificate from that, but it always ignores the private key.

Any ideas on how I could solve this problem?

PogoMips
  • 3,497
  • 8
  • 27
  • 34
  • Did this ever get resolved ?? I am having the same issue. – The Lazy Coder Oct 24 '13 at 23:21
  • 2
    yes, I did: http://stackoverflow.com/questions/18462064/associate-a-private-key-with-the-x509certificate2-class-in-net – PogoMips Oct 27 '13 at 18:51
  • Nice. After posting here I was eventually able to figure it out. My approach was a little more manual. But here it is. http://stackoverflow.com/questions/243646/how-to-read-a-pem-rsa-private-key-from-net/19579157#19579157 – The Lazy Coder Oct 28 '13 at 16:51

2 Answers2

15

I've created a small helper NuGet package to create a X509 certificate based on public key and private (rsa) key.

// Generate with: openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout private.key -out certificate_pub.crt
string certificateText = File.ReadAllText("certificate_pub.crt");
string privateKeyText = File.ReadAllText("private.key");

ICertificateProvider provider = new CertificateFromFileProvider(certificateText, privateKeyText);
X509Certificate2 certificate = provider.Certificate;

// Example: use the PrivateKey from the certificate above for signing a JWT token using Jose.Jwt:
string token = Jose.JWT.Encode(payload, certificate.PrivateKey, JwsAlgorithm.RS256);

See NuGet and Github-project for functionality and code-examples based on opensslkey.

Stef Heyenrath
  • 9,335
  • 12
  • 66
  • 121
2

I guess maybe you are missing some conceptual ideas here?

A Certificate is not supposed to contain a Private Key. The Private Key is always private, a certificate is what that binds your public key to your distinguished name. In other words a Certificate is a document that is signed by an authority that confirms that a particular Public Key, that you share with the world, belongs to you and no one else. Therefore it never can contain the Private Key, because you share your certificate with the world!

LonelyDeveloper
  • 424
  • 8
  • 15
  • 2
    Well, true, that makes sense. But then I still wonder about two things: 1. Why is it possible in OpenSSL to add a private key to a certificate? 2. If certificates are not supposed to have private keys, what does this Exception mean? thrown by "AuthenticateAsServer()": System.NotSupportedException: The server mode SSL must use a certificate with the associated private key – PogoMips Aug 27 '13 at 07:14
  • It isn't possible. Maybe their terminology is sloppy, but what is possible is to create a *file* containing both a private key and a certificate. I don't see anything hard to understand about 'a certificate *with* the associated private key'. It doesn't say anything about the key being inside. – user207421 Aug 27 '13 at 07:46
  • Okay, then can you maybe give me some advice on how I can associate the private key with the certificate in .net? I have a private key that is created with OpenSSL and stored on the disc in a .key file. in OpenSSL it's possible to simply call cert.PrivateKey = Key, but since there is no documentation for the .net wrappers, I don't know what it does. Apparently not adding it to the certificate. – PogoMips Aug 27 '13 at 08:00
  • Hmm, I have never used the .net wrapper for openssl, but I guess maybe the exception that you get is thrown because you are using the wrong private key for your ssl connection. You know that you should use the same Private and Public Key pair that you generated in the first place. You cannot use any Private Key with the certificate that is issued for a certain Public Key. – LonelyDeveloper Aug 27 '13 at 20:38
  • 4
    X509Certificate2 can contain private keys. https://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates.x509certificate2.privatekey%28v=vs.110%29.aspx – Oran Dennison Mar 10 '15 at 19:11
  • 4
    The certs themselves, as far as the system in which the cert exists, do have private keys. They need to know the private key because how would you decrypt any messages sent encrypted with the public key the cert represents? They are also stored on the system the generated them. This is not an answer to the question posed but and should have been a comment. – Richard Barker Jun 07 '16 at 18:20