【C#】Socket中的ssl通信

引言 
   有个项目中用到了Socket ssl通信,在此记录一下.

证书

Socket ssl需要用到证书用来校验身份,而作为调试,我们只需用测试证书即可.

有个工具可以很方便地制作测试证书,下载地址为http://supersocket.codeplex.com/releases/view/59311

首先, 输入Common Name,密码和保存路径后,我们可以得到包含私钥的证书server.pfx.

然后,安装证书到电脑中,在IE选项中导出一份证书作为client.cer.

客户端

使用客户端的电脑需要安装client.cer到<受信任的根证书颁发机构>,且要把证书放在程序目录中,具体代码如下

 class Program
    {
        private static SslStream _sslStream;

        static void Main(string[] args)
        {

            try
            {
                TcpClient client = new TcpClient("127.0.0.1", 6000);
                Console.WriteLine("Client connected.");
                _sslStream = new SslStream(
                   client.GetStream(),
                   false,
                   new RemoteCertificateValidationCallback(ValidateServerCertificate),
                   null
                   );

                X509CertificateCollection certs = new X509CertificateCollection();
                X509Certificate cert = X509Certificate.CreateFromCertFile(System.Environment.CurrentDirectory + @"\" + "client.cer");
                certs.Add(cert);
                //验证证书
                try
                {
                    _sslStream.AuthenticateAsClient("test", certs, SslProtocols.Tls, false);
                }
                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.");
                    client.Close();
                    Console.ReadLine();
                    return;
                }

                //开始读取消息
                Task.Factory.StartNew(() =>
                {
                    ReadMessage(_sslStream);
                });

                Console.WriteLine("按Q退出程序");
                string message = "";
                message = Console.ReadLine() + "<EOF>";
                while (message != "Q")
                {
                    byte[] bytes = Encoding.UTF8.GetBytes(message);
                    _sslStream.Write(bytes);
                    _sslStream.Flush();
                    Console.WriteLine("send:" + message);
                    message = Console.ReadLine() + "<EOF>";
                }

                client.Close();
            }
            catch (Exception ex)
            {

                Console.WriteLine(ex);
                Console.ReadLine();
            }
        }

        public static void ReadMessage(SslStream sslStream)
        {
            byte[] buffer = new byte[2048];
            StringBuilder messageData = new StringBuilder();
            int bytes = -1;
            do
            {
                bytes = sslStream.Read(buffer, 0, buffer.Length);
                Decoder decoder = Encoding.UTF8.GetDecoder();
                char[] chars = new char[decoder.GetCharCount(buffer, 0, bytes)];
                decoder.GetChars(buffer, 0, bytes, chars, 0);
                messageData.Append(chars);
                if (messageData.ToString().IndexOf("<EOF>", StringComparison.Ordinal) != -1)
                {
                    break;
                }
            } while (bytes != 0);

            string message = messageData.ToString().Replace("<EOF>", "");
            Console.WriteLine("recevied:" + message);
            ReadMessage(sslStream);
        }

        private 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;
        }
    }

服务端

服务端电脑要安装server.pfx证书,且要把证书放在程序目录中,具体代码如下

  class Program
    {
        static void Main(string[] args)
        {
            TcpListener listener = new TcpListener(IPAddress.Any, 6000);
            listener.Start();

            Console.WriteLine("Waiting for a client to connect...");
            TcpClient client = listener.AcceptTcpClient();

            _sslStream = new SslStream(client.GetStream(), true);

            try
            {
                serverCertificate = new X509Certificate(Environment.CurrentDirectory + @"\" + "server.pfx", "1");
                _sslStream.AuthenticateAsServer(serverCertificate, false, SslProtocols.Tls, true);
            }
            catch (Exception ex)
            {
                 Console.WriteLine(ex);
                 Console.ReadLine();
                 return;
            }

            while (true)
            {
                string receivedMessage = ReadMessage(_sslStream);
                Console.WriteLine("received:" + receivedMessage);
                byte[] message = Encoding.UTF8.GetBytes("Success.<EOF>");
                _sslStream.Write(message);
                _sslStream.Flush();
            }
        }

        static X509Certificate serverCertificate = null;
        private static SslStream _sslStream;

        static string ReadMessage(SslStream sslStream)
        {
            byte[] buffer = new byte[2048];
            StringBuilder messageData = new StringBuilder();
            int bytes = -1;
            do
            {
                bytes = sslStream.Read(buffer, 0, buffer.Length);
                Decoder decoder = Encoding.UTF8.GetDecoder();
                char[] chars = new char[decoder.GetCharCount(buffer, 0, bytes)];
                decoder.GetChars(buffer, 0, bytes, chars, 0);
                messageData.Append(chars);
                if (messageData.ToString().IndexOf("<EOF>") != -1)
                {
                    break;
                }
            } while (bytes != 0);

            return messageData.ToString();
        }

        static void ProcessClient(TcpClient client)
        {

            SslStream sslStream = new SslStream(
                client.GetStream(), true);

            try
            {
                sslStream.AuthenticateAsServer(serverCertificate, true, SslProtocols.Tls, true);

                Console.WriteLine("Waiting for client message...");
                string messageData = ReadMessage(sslStream);
                Console.WriteLine("Received: {0}", messageData);

                byte[] message = Encoding.UTF8.GetBytes("已收到信息.<EOF>");
                sslStream.Write(message);
                sslStream.Flush();
            }
            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();
            }
        }

    }

注意事项

  1.服务端验证方法AuthenticateAsServer的参数clientCertificateRequired如果为true,那在客户端也要安装server.pfx.

2.客户端验证方法AuthenticateAsClient的参数targetHost对应证书中Common Name,也就是受颁发者.

参考资料

   https://msdn.microsoft.com/zh-cn/library/system.net.security.sslstream(v=vs.110).aspx

时间: 2024-11-03 05:44:30

【C#】Socket中的ssl通信的相关文章

在HAProxy中使用SSL证书进行连接

一.环境介绍 接到通知,要求网站由http改为使用https,目前我的网站前端架构如下图所示: 假设我们有两台物理机,每台物理机上面有很多的tomcat容器,前端使用的是haproxy进行的http层负载均衡,再前端我们使用了LVS负载均衡,整个LVS使用的是DR模型. 刚开始我打算把tomcat改成https,设置成之后再设置haproxy的时候,发现haproxy不能再使用负载均衡了,因为SSL是在第四层的,所以这个方案就结束了,下面我就尝试在haproxy层设定SSL,到后端还使用普通的连

SSL 通信原理及Tomcat SSL 配置

SSL 通信原理及Tomcat SSL 双向配置 目录1 参考资料 .................................................................................................................................. 12 SSL(Server Socket Layer)简介 .......................................................

在IIS中使用SSL配置HTTPS网站

在IIS中使用SSL配置HTTPS网站 由于Windows系统的普及,很多中小企业在自己的网站和内部办公管理系统都是用默认的IIS来做WEB服务器使用.    默认情况下我们所使用的HTTP协议是没有任何加密措施的,所有的消息全部都是以明文形式在网络上传送的,恶意的攻击者可以通过安装监听程序来获得我们和服务器之间的通讯内容.这点危害在一些企业内部网络中尤其比较大,对于使用HUB的企业内网来说简直就是没有任何安全可讲因为任何人都可以在一台电脑上看到其他人在网络中的活动,对于使用交换机来组网的网络来

SSL通信-证书认证错误忽略

.NET的SSL通信过程中,使用的证书可能存在各种问题,某种情况下可以忽略证书的错误继续访问. 经过下面的处理服务器证书验证中不会有错误发生,证书认证一直通过,并正常通信 1.设置回调属性ServicePointManager.ServerCertificateValidationCallback 注:这个属性设置为要用于客户端的服务器证书的自定义验证方法 C#代码 1 ServicePointManager.ServerCertificateValidationCallback = 2 new

Android中的HTTP通信

前言:近期在慕课网学习了慕课网课程Android中的HTTP通信,就自己总结了一下,其中参考了不少博文,感谢大家的分享. 文章内容包括:1.HTTP简介2.HTTP/1.0和HTTP/1.1之间的区别3.HTTP的请求头.响应头和状态码4.Android中的HttpUrlConnection 1.Http简介Http(Hypertext transfer protocol)定义了浏览器怎么向万维网服务器发送万维网文档,以及服务器怎么将文档发送给服务器.从层次上看,http是面向应用层协议的,它是

YS端对端之间SSL通信安全问题

1.简介:          传统的互联网,SSL通信主要基于客户端和服务器之间,在物联网时代,端和端之间的加密通信将变得很普遍,在YS业务中主要的端和端通信为: (1).客户端(移动APP,YS工作室和web)和设备之间的双向通信. (2).设备和设备之间的双向通信. 为保障用户通信安全,端和端之间的通信实施SSL通信. 注:实际上是基于客户端的hik的SDK和设备之间的通信,使用了hik SDK的客户端都可以和hik的设备进行通信. 主要的场景图如下:   2.业务需求:         

C#中使用UDP通信实例

网络通信协议中的UDP通信是无连接通信,客户端在发送数据前无需与服务器端建立连接,即使服务器端不在线也可以发送,但是不能保证服务器端可以收到数据.本文实例即为基于C#实现的UDP通信.具体功能代码如下: 服务器端代码如下: static void Main(string[] args) { UdpClient client = null; string receiveString = null; byte[] receiveData = null; //实例化一个远程端点,IP和端口可以随意指定

mosquitto配置通过ssl通信

mosquitto配置通过ssl通信 摘自https://www.cnblogs.com/stin/p/9258211.html 注意项: For openssl >= 1.0.1 the valid values are tlsv1.2 tlsv1.1 and tlsv1. For openssl < 1.0.1 the  valid values are tlsv1.我本机上用的openssl 1.0.2g , tls_version要配置为 tlsv1.2 ca 和client,serv

网络编程 TCP协议:三次握手,四次回收,反馈机制 socket套接字通信 粘包问题与解决方法

TCP协议:三次握手,四次挥手 TCP协议建立双向通道. 三次握手, 建连接: 1:客户端向服务端发送建立连接的请求 2:服务端返回收到请求的信息给客户端,并且发送往客户端建立连接的请求 3:客户端接收到服务端发来的请求,返回接成功给服务端,完成双向连接 第一客戶向服务端发送请求,请求建立连接 服务端同客户端的请求,并同时向客户端发送建立 连接的请求,最后客户端同意后建立 双向连接. C ----> S C <---- S - 反馈机制: 客户端往服务端发送请求,服务端必须返回响应, 告诉客户