简体   繁体   中英

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

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);

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)

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.

How did you create the certificate? When creating a certificate a private key is also used to sign it which is what you need. If you have exported the certificate, you probably had the option to provide a password at some point. If you have not provided a password when exporting, the certificate is exported without the private key.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM