15

I'm lost in a twisty maze of certificates and private keys.

I am writing a server in C#. I want it to accept SSL connections. For test purposes, I want to generate a certificate for "localhost", and use that certificate for the server. Ideally I don't want to pollute my certificate store, so I just want a file, or files, on disk that the C# code can load to provide the certificate.

Everything I have tried (using cookbook approaches suggested by web searches) either gives me "The credentials supplied to the package were not recognized" or "The server mode SSL must use a certificate with the associated private key."

Is there a way to generate a certificate and private key, and subsequently to load them into an X509Certificate object without also loading them into my machine certificate store?

Nikki Locke
  • 2,759
  • 6
  • 29
  • 53
  • do you really need this certificate or do want just skip cert. check using it?? – VladL Jan 08 '13 at 11:57
  • The server is a web server. I need to connect to it from a browser, using https protocol. So I guess I need the certificate. I am aware that the certificate will not be trusted, so the browser user will have to accept it as such. – Nikki Locke Jan 08 '13 at 12:43

6 Answers6

19

In the end, I ran the following to create a server.pfx file:

makecert.exe -r -pe -n "CN=localhost" -sky exchange -sv server.pvk server.cer
pvk2pfx -pvk server.pvk -spc server.cer -pfx server.pfx

Then I loaded it in code with:

certificate = new X509Certificate2("server.pfx", "password");

(I didn't actually hard code the password like that :-)

The trick was to know that I needed a pfx file, and that I needed to load it using the X509Certificate2 class, rather than X509Certificate.

Nikki Locke
  • 2,759
  • 6
  • 29
  • 53
  • Saved my life. I used this method to provide certificate via my proxy server application to client's browser. I know its not a right method, but still everything is OK. – Aditya Bokade Feb 07 '13 at 19:56
  • But this method does not work well for proxy server. Do you have any idea how to solve it? – Aditya Bokade Mar 19 '13 at 08:31
  • 1
    Does not work. I get a `CryptographicException` saying “The specified network password is not correct.”, which is patently false because I used the password `x`, which is very hard to mistype. Any ideas for a fix? – Timwi Apr 17 '13 at 20:17
  • Can't help there, otherwise than to say the code above works for me. Can you open the pfx with any other tool, using the password "x"? – Nikki Locke Apr 22 '13 at 11:19
  • What is the purpose of the other generated files, and do they need to be present as well? – Nyerguds Jun 26 '13 at 08:12
  • As far as I know, they are intermediate files, and not required once the pfx is generated. – Nikki Locke Jun 27 '13 at 10:36
  • 1
    To others that can't get this to work, see: http://stackoverflow.com/a/19719140/103959 – Jean-Bernard Pellerin Mar 12 '15 at 20:51
8

Niki Loche method works.

If you get The specified network password is not correct., then you should try it without password in C#. It doesn't matter what your input password was in makecert.

certificate = new X509Certificate2("Server.pfx", "");

But if you want to use password (there is a reason, it's there :)), try changing pvk2pfx.exe command to:

pvk2pfx.exe" -pi password -pvk Server.pvk -spc Server.cer -pfx Server.pfx

and in C# enter:

certificate = new X509Certificate2("Server.pfx", "password");

Password must be the same as it is in creating cer file.

That did the trick for me. I hope it will help someone.

ac989
  • 81
  • 1
  • 2
1

There are a number of tools that should let you act as your own CA and generate a certificate. XCA is one of them. There are also a number of methods using OpenSSL commands, for example.

Generating a self-signed certificate only may seem like the easiest option, but using a test CA (and a separate server certificate) may be worth it. This would allow you to import the test CA into the browser's store if needed to make the tests more realistic. It's not much more difficult with the right tools (e.g. XCA).

Once you have generated your server certificate and its private key, turn it into a PKCS#12 file (.p12/.pfx).

You should then be able to load it using X509Certificate2.import(...). (See example in this answer.)

Community
  • 1
  • 1
Bruno
  • 119,590
  • 31
  • 270
  • 376
  • For those who want to use this solution. I think my answer can complement what @Bruno said, [here](http://stackoverflow.com/questions/9982865/sslstream-example-how-do-i-get-certificates-that-work/38155120#38155120) I show you the way genererate a valid certificate with OpenSSL. – Jose Rodriguez Jul 04 '16 at 15:42
1

I recently developed a SMTP server with TLS. I needed to install the server as a Windows Service on a Windows Server 2012 box. I used a Let's Encrypt SSL Certificate (* wildcard) for my domain. While developing "on the server" I had to run Visual Studio as Administrator for my code to work using "new X509Certificate("cert.pfx", "{password}") and it ran perfectly. However, once installed as a service, that scheme did not work. Turns out the simpler/safer way is to use X509Store. Here's the code that solved the problem...

private X509Certificate GetSslCertificate()
{
    X509Certificate cert = null;
    string certname = "*.mydomain.com";

    try
    {
        X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
        store.Open(OpenFlags.OpenExistingOnly);

        foreach (X509Certificate certificate in store.Certificates)
        {
            if (certificate.Subject.ToLower().Contains(certname))
            {
                cert = certificate;
                break;
            }
        }
    }
    catch (Exception) { /* Handle Exception */ }
    return cert;
}

Also notice I used "LocalMachine" as the StoreLocation. You'll need to change to CurrentUser if that's where you installed your SSL Certificate.

zachar
  • 41
  • 4
0

If you have IIS, you can do it through the IIS Manager as detailed here:

http://blogs.msdn.com/b/ericnel/archive/2009/09/22/using-iis-to-generate-a-x509-certificate-for-use-with-the-windows-azure-service-management-api-step-by-step.aspx

wbt11a
  • 798
  • 4
  • 12
0

I had the same issue when importing a machine certificate from the machine store (not the user store). I solved it by running Visual Studio as an administrator, as administrator privileges are required to access the private key of a machine store certificate.