C#: Forcing TLS1.2 but Https server still giving common algorithm error

665 views Asked by At

Im trying to setup a simple HTTPS web server using TcpClient, SslStream, and a self signed certificate.

The code starts fine, displays waiting for client, but when I connect to it via a web browser I get

"A call to SSPI failed, The client and server cannot communicate, because they do not possess a common algorithm"

From what I have read, this typically means that the server is trying to use a protocol type that the client doesnt have or cannot use (IE: outdated), and many say to make sure that both the server and client are using TLS 1.2.

-I have made sure to include "ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12" to force tls1.2, and am using Firefox(and others) which I have verified are up to date and work with tls12.

-Im on .net 4.7, so that shouldnt be an issue I dont think.

-I have manually imported the certificate into firefox.

-I have tried allowing all protocols, and no protocols, and "default"

-I have gone into the registry and enabled all TLS, and disabled all but tls1.2, both with same result.

Im sure this has been answered before, but I have been scouring SO and google for a couple days now, so I give up, roast away!

static X509Certificate serverCertificate = null;

public static int Main(string[] args)
{
    ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;  //Force tls 1.2
    MakeCert();                                                         //Create self signed certificate and assign to serverCertificate
    SslTcpServer.RunServer();
    return 0;
}

static void MakeCert()
{
    var ecdsa = ECDsa.Create(); // generate asymmetric key pair
    var req = new CertificateRequest("cn=localhost", ecdsa, HashAlgorithmName.SHA256);
    var cert = req.CreateSelfSigned(DateTimeOffset.Now, DateTimeOffset.Now.AddYears(5));

    // Create PFX (PKCS #12) with private key
    string pfxPath = Path.Combine(Environment.CurrentDirectory, "mycert.pfx");
    File.WriteAllBytes(pfxPath, cert.Export(X509ContentType.Pfx, "Password"));
    // Create Base 64 encoded CER (public key only)
    string cerPath = Path.Combine(Environment.CurrentDirectory, "mycert.cer");
    File.WriteAllText(cerPath,
        "-----BEGIN CERTIFICATE-----\r\n"
        + Convert.ToBase64String(cert.Export(X509ContentType.Cert), Base64FormattingOptions.InsertLineBreaks)
        + "\r\n-----END CERTIFICATE-----");

    string keyfilename = "mycert.pfx";
    string certpath = Path.Combine(Environment.CurrentDirectory, keyfilename);
    X509Certificate certificate = new X509Certificate2(certpath, "Password");
    serverCertificate = certificate;
}

public static void RunServer()
{
    TcpListener listener = new TcpListener(IPAddress.Any, 8080);
    listener.Start();
    while (true)
    {
        Console.WriteLine("Waiting for a client to connect...");
        TcpClient client = listener.AcceptTcpClient();
        ProcessClient(client);
    }
}

static void ProcessClient(TcpClient client)
{
    SslStream sslStream = new SslStream(client.GetStream(), false);
    try
    {
        sslStream.AuthenticateAsServer(serverCertificate, clientCertificateRequired: false, enabledSslProtocols : SslProtocols.Tls12, checkCertificateRevocation: false);
        Console.WriteLine("Authenticated");
    }
    catch (AuthenticationException e)
    {
        Console.WriteLine("Exception: {0}", e.Message);
        if (e.InnerException != null)
        {
            Console.WriteLine("Inner exception: {0}", e.InnerException.Message);
        }
        Console.WriteLine("Authentication failed - closing the connection.");
        sslStream.Close();
        client.Close();
        return;
    }
    finally
    {
        sslStream.Close();
        client.Close();
    }
}

Code never reaches "Authenticated", always throws exception

"A call to SSPI failed, see inner exception"

with inner exception

"The client and server cannot communicate, because they do not possess a common algorithm"

1

There are 1 answers

0
Perfect28 On BEST ANSWER

This issue is not about SSL/TLS protocols. It's about the signature algorithm ECDsa. It looks as if nistP521 (the default curve used by ECDsa.Create) is not supported by Firefox (I didn't check any documentation) as it works perfectly with nistP256 or nistP384

  var ecdsa = ECDsa.Create(ECCurve.NamedCurves.nistP384); // generate asymmetric key pair
  var req = new CertificateRequest("cn=localhost",ecdsa, HashAlgorithmName.SHA256);