gpt4 book ai didi

c# - 如何将 SslStream/AuthenticateAsServer 与自签名证书/ key 一起使用?

转载 作者:行者123 更新时间:2023-12-05 03:47:50 30 4
gpt4 key购买 nike

我想编写(使用 C# 和 dotnet 4.8)使用 TLS 确保安全的 TCP 服务。为此,我想将 SslStream 与 TcpListener 一起使用,但我不断收到奇怪的错误。

我的实验程序如下。简而言之:

  • 程序根据 https://stackoverflow.com/a/52535184/3568 处的代码创建一个自签名 PFX
  • 它启动一个线程来运行服务,而主线程运行客户端。
  • 服务线程监听连接。
  • 客户端连接。
  • 该服务发送一条线路以确认底层 TCP 连接有效。
  • 客户收到线路。
  • 服务器和客户端都将控制权移交给 SslStream,服务器使用之前创建的 PFX。
    • 这是抛出异常的地方。
  • 协商 TLS 后,服务器会发送另一行,这次是在 TLS channel 内。
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Security;
using System.Net.Sockets;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading;

namespace TestTlsService
{
class Program
{
static string tempCert;

static void Main(string[] args)
{
/* Create a cert. */
var cr = new CertificateRequest("cn=this.is.invalid", ECDsa.Create(), HashAlgorithmName.SHA256);
using (var cert = cr.CreateSelfSigned(DateTime.UtcNow.AddDays(-1), DateTime.UtcNow.AddYears(+1)))
{
var exp = cert.Export(X509ContentType.Pfx);
tempCert = Path.Combine(Path.GetTempPath(), "MySelfSignedCert.pfx");
File.WriteAllBytes(tempCert, exp);
}

/* Launch a service thread. */
Thread svc = new Thread(ServiceMain);
svc.Start();
Thread.Sleep(100);

/* Connect as a client. */
using (var tcp = new TcpClient())
{
tcp.Connect("localhost", 1984);
var stream = tcp.GetStream();

/* Read the line "GoTLS" from the server. */
var insecureLine = ReadLine(stream);

/* Hand over control to TLS. */
using (var tls = new SslStream(stream, false, CheckCert))
{
tls.AuthenticateAsClient("this.is.invalid");

/* Read a different line, this time securely. */
string line = ReadLine(tls);
}
}
}

static void ServiceMain()
{
/* Open a listener and start listening. */
var listen = new TcpListener(IPAddress.Loopback, 1984);
listen.Start();
using (var tcp = listen.AcceptTcpClient())
{
/* Send "GoTLS" to the client insecurely. */
var stream = tcp.GetStream();
stream.Write(Encoding.ASCII.GetBytes("GoTLS\r\n"), 0, 7);

/* Hand over control to TLS, using the self-signed cert from earlier. */
using (var tls = new SslStream(stream))
{
var cert = new X509Certificate2(tempCert);
tls.AuthenticateAsServer(cert);

/* Send a new message inside the secure channel. */
tls.Write(Encoding.ASCII.GetBytes("Hello\r\n"), 0, 7);
}
}
}

/* Simple function that just reads a line. */
static string ReadLine(Stream stream)
{
byte[] line = new byte[100];
int bytesIn = stream.Read(line, 0, 100);
string lineAscii = Encoding.ASCII.GetString(line, 0, bytesIn);
return lineAscii;
}

/* Accept all certificates. DO NOT COPY THIS INTO YOUR OWN CODE! */
private static bool CheckCert(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
/* The full version will check the cert, but for now we'll just... */
return true;
}
}
}

此程序在 AuthenticateAsServer 行中抛出 AuthenticationException 并显示消息“对 SSPI 的调用失败,请参阅内部异常。”而内部异常有“客户端和服务器无法通信,因为它们不具备通用算法”。我发现 SslStream 库找不到与自身通用的协议(protocol)的可能性很小。

我怀疑问题的根源在于我使用的是自签名证书,因为我能找到的所有 AuthenticateAsServer 示例都使用了预生成的证书文件,可惜我没有.

如何在服务器端使用 SslStream 与自签名证书协商 TLS?


抢占预期的问题...

我知道客户端可以正常工作,因为我已经用邮件服务器替换了“localhost”(并跳过了 read-a-line)并且客户端线程可以正常读取远程邮件服务器发送的安全欢迎行在协商 TLS 之后。

ServicePointManager.SecurityProtocol 设置为 Tls12 没有帮助。

如果删除 SslStream 之前的“GoTLS”交换,我会遇到同样的错误。

我已经搜索了错误消息。我能找到的所有答案都建议将 SecurityProtocol 设置为 Tls12,我已经尝试过了。

我尝试了其他格式的证书而不是 PFX,但我收到不同的错误,提示我丢失了私钥。

最佳答案

我不知道为什么,但它不喜欢你颁发的 ECDSA 证书。如果您改为使用标准 RSA:

var cr = new CertificateRequest(new X500DistinguishedName("cn=this.is.invalid"), RSA.Create(), HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);

并保持其他一切不变 - 然后它将按预期工作。理论上,TLS 支持 ECC(椭圆曲线) key ,但我不是这方面的专家,也不确定为什么 SslStream.AuthenticateAsServer 不喜欢该证书。希望您不需要专门的 ECC,那么使用 RSA 的上述解决方法就完全没问题。

关于c# - 如何将 SslStream/AuthenticateAsServer 与自签名证书/ key 一起使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64721364/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com