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