The server mode SSL must use a certificate with the associated private key - during TLS handshake

10,754

Solution 1

Between Jesse's comment and Dave's answer, I could work out that I'd somehow created and installed some kind of partial certificate, sort half-jobbed it.

I had made a cert using makecert.exe and somehow managed to install it and load it into Kestrel, but it failed when a request from Chrome came in.

I couldn't find a copy of pvk2pfx.exe in order to make a PFX file from the two files that makecert.exe had kicked out, so I just tried to carry on without it.

After that failure and reading the above, I figured that the PFX step is mandatory. So I used classic PowerShell 4 (PS6 Core wouldn't load the module):

> $cert = New-SelfSignedCertificate -certstorelocation cert:\currentuser\my -dnsname windows
> $pwd = ConvertTo-SecureString -String 'password1234' -Force -AsPlainText
> $path = 'cert:\currentuser\my\' + $cert.thumbprint
> Export-PfxCertificate -cert $path -FilePath c:\DATA\~Scrap\windows.pfx -Password $pwd

Credit to https://medium.com/the-new-control-plane/generating-self-signed-certificates-on-windows-7812a600c2d8

Tbh, I originally half-jobbed this. I stopped after the first command which produced a certificate in my store, but gave me a different strange error from Kestrel's stack when hit from Chrome. Again, the PFX step is needed for some reason.

At present I can't find a way to trust the signer, but Chrome let's me proceed so I'll sort that when I'm not so tired.

Solution 2

For a proper tls handshake, the server is required to have a private key paired with the public key embedded in the certificate. When a client connects, it is presented with the certificate. This allows for validation that the server is who it says it is based on trust of an issuance authority. The client, during the handshake will generate a symmetric cipher key that is encrypted for the server using the public key from the certificate. The server will decrypt the symmetric key using the private half.

I'm grossly over simplifying the handshake process here. So take the above with a grain of salt. (No crypto pun intended)

Share:
10,754
Andrei
Author by

Andrei

There are 2 hard problems in computer science: cache invalidation, naming things, and off-by-1 errors. .NET, Azure, ASP.NET MVC, JavaScript, React-Native

Updated on June 04, 2022

Comments

  • Andrei
    Andrei almost 2 years

    I have a certificate someCert.cer. I imported it into my local certificates store using MMC utility. My C# application is able to access it using following code:

    var store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
    X509Certificate2 certificate = null;
    store.Open(OpenFlags.ReadOnly);
    try
    {
        var certificateCollection = store.Certificates.Find(X509FindType.FindByThumbprint, "THUMBPRINT", false);
        certificate = certificateCollection[0];
    }
    finally
    {
        store.Close();
    }
    

    The application exposes TCP socket and when I try to connect to it with my client app I get exception: The server mode SSL must use a certificate with the associated private key

    Indeed my certificate's PrivateKey property is empty. Did I import my certificate incorrect or should I do something with the certificate before importing it into the store?

    My server authentication code looks like that:

    stream.AuthenticateAsServerAsync(certificate, false, SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12, true);