在windows中使用makecert.exe签发根证书、iis https服务端证书,并使用数字证书进行ssl socket通信

版权声明:本文为博主原创文章,转载请注明出处。 https://blog.csdn.net/lwwl12/article/details/80799604

首先放出几个参考文档:

数字证书

如果想深入理解数字证书,有几个概念必须要搞清楚

  • 数字证书标准 x.509
  • 数字证书格式 PEM(字符/ASCII格式)、DER(二进制格式)
  • 证书链

制作证书需要用到几个工具:

  • makecert.exe证书制作工具
  • Cert2Spc.exe公钥证书格式转换成SPC
  • pvk2pfx.exe将公钥证书和私钥合并成一个PFX格式的证书文件

制作根证书

根证书就是自签名的证书,在证书链的顶端,自己验证自己。
证书最初生成时是一个自签名证书。自签名证书是其签发者(签名者)与主题(其公共密钥由该证书进行验证的实体)相同的证书。如果拥有者向 CA 发送证书签名请求 (CSR),然后输入响应,自签名证书将被证书链替换。链的底部是由 CA 发布的、用于验证主题的公共密钥的证书(回复)。链中的下一个证书是验证 CA 的公共密钥的证书。通常,这是一个自签名证书(即,来自 CA、用于验证其自身的公共密钥的证书)并且是链中的最后一个证书。

makecert -n “CN=Root” -r -sv RootIssuer.pvk RootIssuer.cer

注意: 服务端和客户端的电脑上都需要先导入根证书

制作https数字证书

我们需要使用刚才生成的根证书签发一张https数字证书(其实并没有指定一定是https使用的,socket一样可以用,下文ssl socket也是使用的此数字证书)

makecert -n “CN=www.lwwl.tech” -b 06/22/2018 -e 06/23/2019 -eku 1.3.6.1.5.5.7.3.1 -ss my -sr localmachine -sky exchange -sp “Microsoft RSA SChannel Cryptographic Provider” -sy 12 -$ commercial -cy authority -iv RootIssuer.pvk -ic RootIssuer.cer -sv lwwl.pvk lwwl.cer

注意:CN=www.lwwl.tech必须是你服务器绑定的域名,否则浏览器会提示安全验证问题。
-n 中还可以带其他参数:
-n “CN=公司名称, E=E-MAIL地址, O=组织名称, OU=组织单位, C=国家, S=省份(州), P=县城”

签发证书的较理想方式是:
(1)首先生成一张根证书,根证书需安装在各个设备中,永远不能改变;
(2)使用根证书签发一张用于签发证书的证书A(姑且称为签发证书A);
(3)然后使用签发证书A去签发实际使用的数字证书B(姑且称为叶子证书B);
证书链:根证书 << 签发证书A << 叶子证书B

我们可以看一下csdn的证书链:
这里写图片描述

好处是方便使用签发证书来管理此证书签发的所有证书,还有其他的可以留言补充。

制作pfx并添加到iis

在iis中导入证书必须为.pfx格式,所以我们需要将之前生成的lwwl.pvk和lwwl.cer。

(1)首先生成.spc格式证书(需要使用cert2spc.exe工具)

cert2spc lwwl.cer lwwl.spc

.spc 意思是 软件发布者证书(Software Pulisher Cerificate).

(2)将公钥证书和私钥合并成一个PFX格式的证书文件。pvk2pfx.exe

pvk2pfx -pvk lwwl.pvk -spc lwwl.spc -pfx lwwl.pfx

然后再进入iis导入.pfx证书即可:
这里写图片描述
注意: 密码 一栏不填

将网站设为https:
这里写图片描述

C# ssl socket 通信

可以参考:C# Socket SSL通讯笔记

服务端代码:

    // ssl socket server
    class SocketServer
    {
        static X509Certificate serverCertificate = null;
        Socket socket { get; set; }

        public void startListen()
        {

            X509Store store = new X509Store(StoreName.My);
            store.Open(OpenFlags.ReadWrite);

            // 检索证书 
            X509Certificate2Collection certs = store.Certificates.Find(X509FindType.FindBySubjectName, "www.lwwl.tech", false); // vaildOnly = true时搜索无结果。
            if (certs.Count == 0) throw new Exception("没有找到合法的数字证书");

            serverCertificate = certs[0];

            IPAddress ip = IPAddress.Any;

            //端口号
            IPEndPoint point = new IPEndPoint(ip, 8080);

            //创建监听用的Socket

            /*
             * AddressFamily.InterNetWork:使用 IP4地址。
               SocketType.Stream:支持可靠、双向、基于连接的字节流,而不重复数据。此类型的 Socket 与单个对方主机进行通信,并且在通信开始之前需要远程主机连接。Stream 使用传输控制协议 (Tcp) ProtocolType 和 InterNetworkAddressFamily。
               ProtocolType.Tcp:使用传输控制协议。
             */

            //使用IPv4地址,流式socket方式,tcp协议传递数据

            Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            //创建好socket后,必须告诉socket绑定的IP地址和端口号。

            //让socket监听point
            try
            {

                //socket监听哪个端口
                socket.Bind(point);

                //同一个时间点过来10个客户端,排队
                socket.Listen(10);

                ShowMsg("服务器开始监听");

                Thread thread = new Thread(AcceptInfo);
                thread.IsBackground = true;
                thread.Start(socket);
            }

            catch (Exception ex)
            {
                ShowMsg(ex.Message);
            }
        }

        void AcceptInfo(object o)
        {
            Socket socket = o as Socket;

            while (true)
            {
                try
                {
                    //创建通信用的Socket
                    Socket tSocket = socket.Accept();

                    // 配置ssl
                    var m_DataStream = new NetworkStream(tSocket, true);
                    SslStream sslStream = new SslStream(m_DataStream, false);
                    sslStream.AuthenticateAsServer(serverCertificate, false, SslProtocols.Default, true);

                    Console.WriteLine("Waiting for client message...");

                    string point = tSocket.RemoteEndPoint.ToString();

                    ShowMsg(point + "连接成功!");


                    Thread th = new Thread(ReceiveSslMsg);
                    th.IsBackground = true;
                    th.Start(sslStream);

                }
                catch (Exception ex)
                {
                    ShowMsg(ex.Message);
                    break;
                }
            }
        }

        void ReceiveSslMsg(object o)
        {
            SslStream sslStream = o as SslStream;
            while (true)
            {
                try
                {
                    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);

                    ShowMsg("Server SSL Data = " + messageData.ToString());

                    sslStream.Write(Encoding.UTF8.GetBytes("Server Receive SSL Data Success<EOF>"));
                    sslStream.Flush();

                }
                catch (Exception ex)
                {
                    Console.WriteLine("Server ReceiveSslMsg :" + ex.Message);
                }
            }
        }

        void ShowMsg(string msg)
        {
            Console.WriteLine(msg);
        }

        public void StopListen()
        {
            if (socket != null)
            {
                socket.Close();
            }
        }
    }

客户端代码:

    // ssl socket client
    class SocketClient
    {
        private SslStream sslStream;
        private Socket client;

        public void SendMsg(string msg)
        {
            byte[] messsage = Encoding.UTF8.GetBytes(msg + "<EOF>");
            sslStream.Write(messsage);
            sslStream.Flush();
        }

        public void Connect()
        {
            client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            Connection(client);
        }

        private void DisConnect(Socket client)
        {
            try
            {
                if (client != null)
                {
                    client.Close();
                }
            }
            catch (Exception ex)
            {
            }
        }

        private void Connection(Socket client)
        {
            //连接到的目标IP

            IPAddress ip = IPAddress.Parse("127.0.0.1");

            //IPAddress ip = IPAddress.Any;

            //连接到目标IP的哪个应用(端口号!)

            IPEndPoint point = new IPEndPoint(ip, 8080);
            try
            {
                //连接到服务器

                client.Connect(point);

                ShowMsg("连接成功");

                // 验证ssl
                var m_DataStream = new NetworkStream(client, true);
                sslStream = new SslStream(m_DataStream, false, new RemoteCertificateValidationCallback(ValidateServerCertificate), null);
                try
                {
                    sslStream.AuthenticateAsClient("www.lwwl.tech");
                }
                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();
                    return;
                }


                ShowMsg("服务器" + client.RemoteEndPoint.ToString());

                ShowMsg("客户端:" + client.LocalEndPoint.ToString());

                //连接成功后,就可以接收服务器发送的信息了
                Thread th = new Thread(new ParameterizedThreadStart(ReceiveSslMsg));
                th.IsBackground = true;
                th.Start(sslStream);
            }
            catch (Exception ex)
            {

                ShowMsg(ex.Message);
            }
        }

        private bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
        {
            if (sslPolicyErrors == SslPolicyErrors.None)
                return true;

            Console.WriteLine("Certificate error: {0}", sslPolicyErrors);

            // Do not allow this client to communicate with unauthenticated servers.
            return false;
        }

        void ReceiveSslMsg(object o)
        {
            SslStream sslStream = o as SslStream;

            while (true)
            {
                try
                {
                    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);

                    ShowMsg("Client SSL Data = " + messageData.ToString());
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Client ReceiveSslMsg :" + ex.Message);
                }
            }
        }

        void ShowMsg(string msg)
        {
            Console.WriteLine(msg);
        }

        private void send(Socket client, string msg)
        {
            //客户端给服务器发消息
            if (client != null)
            {
                try
                {
                    byte[] buffer = Encoding.UTF8.GetBytes(msg);
                    client.Send(buffer);
                }
                catch (Exception ex)
                {
                    ShowMsg(ex.Message);
                }
            }
        }
    }

Main函数测试:

    static class Program
    {
        static void Main()
        {
            SocketServer server = new SocketServer();
            server.startListen();

            SocketClient _client = new SocketClient();
            _client.Connect();

            _client.SendMsg("ABC");
        }
    }

猜你喜欢

转载自blog.csdn.net/lwwl12/article/details/80799604