C# SSL 安全套接字
我有一个用 C# 编写的、运行良好的通信器应用程序。现在我需要实现与服务器的安全连接。我尝试将 Socket 和 TcpClient 对象更改为 SslStream,但出现了一些错误。
首先,我使用 makecert 生成了一个 .cer 证书。 OpenSSL 证书对我不起作用,因为它们不包含私钥。接下来,我在服务器上创建了一个证书对象并将其绑定到 SslStream:
X509Certificate serverCertificate = X509Certificate.CreateFromCertFile("ca.cer");
TcpClient clientSocket = this.tcpListener.AcceptTcpClient();
SslStream ssls = new SslStream(clientSocket.GetStream(), false);
ssls.AuthenticateAsServer(serverCertificate, false, SslProtocols.Tls, true);
在客户端,我正在这样做:
TcpClient client = new TcpClient(settings.IP, settings.Port);
sslStream = new SslStream(client.GetStream(), false,
new RemoteCertificateValidationCallback(ValidateServerCertificate), null);
sslStream.AuthenticateAsClient(settings.IP);
public static bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
if (sslPolicyErrors == SslPolicyErrors.None)
return true;
Console.WriteLine("Certificate error: {0}", sslPolicyErrors);
return false;
}
但 AuthenticateAsClient 函数抛出异常。我尝试了其他几个方法参数,但这些都不适合我。
谁能帮助我,或者逐步解释如何将简单的套接字更改为安全的套接字?需要明确的是,SSL 不是必需的 - 如果有更简单的方法来确保连接安全,我可以使用它。
编辑: 异常消息如下:
The remote certificate is invalid according to the validation procedure.
I have a fine, working communicator application, written in C#. Now I need to implement a secure connection to the server. I've tried changing Socket and TcpClient objects into SslStream, but I got a few errors.
Firstly I generated a .cer certificate using makecert. OpenSSL certificates didn't worked for me, because they didn't include private key. Next I created a certificate object on the server and bound it to the SslStream:
X509Certificate serverCertificate = X509Certificate.CreateFromCertFile("ca.cer");
TcpClient clientSocket = this.tcpListener.AcceptTcpClient();
SslStream ssls = new SslStream(clientSocket.GetStream(), false);
ssls.AuthenticateAsServer(serverCertificate, false, SslProtocols.Tls, true);
On the client side I'm doing this:
TcpClient client = new TcpClient(settings.IP, settings.Port);
sslStream = new SslStream(client.GetStream(), false,
new RemoteCertificateValidationCallback(ValidateServerCertificate), null);
sslStream.AuthenticateAsClient(settings.IP);
public static bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
if (sslPolicyErrors == SslPolicyErrors.None)
return true;
Console.WriteLine("Certificate error: {0}", sslPolicyErrors);
return false;
}
but the AuthenticateAsClient function throws an exception. I tried several other method parameters, but none of this worked for me.
Could anyone help me, or explain step by step how to change simple sockets into secure ones? To be clear, SSL isn't the requirement - if there is simpler way to make the connection secure I can use that.
Edit:
Message in exception is following:
The remote certificate is invalid according to the validation procedure.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
有什么例外吗?
我猜您遇到了异常,因为您的客户端证书被服务器拒绝为有效(除非您做了必要的事情来建立信任)。
当您使用自签名证书(由 makecert 创建的证书)时,您还必须在创建 SslStream 对象时提供客户端证书验证回调。使用此构造函数重载 http://msdn.microsoft.com/en-us/library /ms145056.aspx
What's the exception ?
I guess you are getting the exception because your client certificate is rejected as valid from the server (unless you did the necessary things to set up trust).
When you use self signed certificates(the ones created by makecert), you would have to also supply a Client Certificate Validation callback when creating the SslStream object. Use this constructor overload http://msdn.microsoft.com/en-us/library/ms145056.aspx
.CER 文件通常包含没有私钥的证书。将其加载到服务器中是行不通的。您还需要一个私钥。最简单的方法是生成证书和密钥并将它们一起保存为 PFX 格式。然后从服务器上的 PFX 加载证书和密钥。
现在,您的代码仅对服务器进行身份验证。这是您想要做的吗(即您不想在服务器上对客户端进行身份验证)吗?
.CER file usually contains a certificate without a private key. Loading it into the server just won't work. You need a private key as well. The easiest is to generate the certificate and a key and save them together to PFX format. Then load the certificate and a key from PFX on the server.
Now with your code only only authenticate the server. Is this what you want to do (i.e. don't you want to authenticate the client on the server as well)?