C#:强制执行TLS1.2,但Https服务器仍给出常见算法错误



我正在尝试使用TcpClient、SslStream和自签名证书来设置一个简单的HTTPS web服务器。

代码启动良好,显示正在等待客户端,但当我通过网络浏览器连接到它时,我会得到

"对SSPI的调用失败,客户端和服务器无法通信,因为他们没有通用的算法">

据我所知,这通常意味着服务器正在尝试使用客户端没有或不能使用的协议类型(IE:过时),许多人说要确保服务器和客户端都使用TLS 1.2。

-我已经确保包含"ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12"以强制使用tls1.2,并且正在使用Firefox(和其他),我已经验证这些Firefox是最新的,可以与tls12一起使用。

-我在.net 4.7上,所以我认为这不应该是个问题。

-我已手动将证书导入firefox。

-我尝试过允许所有协议,但没有协议,以及"默认">

-我已经进入注册表,启用了所有TLS,禁用了除tls1.2之外的所有TLS,两者的结果都是一样的。

我确信这个问题以前已经得到了回答,但我已经在SO和谷歌上搜索了几天了,所以我放弃了,吐槽吧!

静态X509Certificate服务器证书=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-----rn"
+ Convert.ToBase64String(cert.Export(X509ContentType.Cert), Base64FormattingOptions.InsertLineBreaks)
+ "rn-----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();
}
}

代码从未达到"Authenticated",总是抛出异常

"对SSPI的调用失败,请参阅内部异常">

内部异常

"客户端和服务器无法通信,因为它们不拥有一种常见的算法">

此问题与SSL/TLS协议无关。这是关于签名算法ECDsa。看起来nistP521(ECDsa.Create使用的默认曲线)不受Firefox支持(我没有查看任何文档),因为它与nistP256或nistP384 完美配合

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

最新更新