zoukankan      html  css  js  c++  java
  • C# Socket SSL通讯笔记

     

    一、x.509证书

    1.制作证书

    先进入到vs2005的命令行状态,即:
    开始-->程序-->Microsoft Visual Studio 2005-->Visual Studio Tools-->Visual Studio 2005 命令提示

    键入:

    makecert -r -pe -n "CN=MyServer" -ss My -sky exchange

    解释一下:makecert.exe是一个专门用来制作证书的小工具,上面一行的意思就是制作一个CN=MyServer的服务器证书,默认存储在CurrentUser"My这个位置,同时这个证书标识为可导出。(详细的

    MakeCert参数可参见http://msdn.microsoft.com/zh-cn/bfsktky3(vs.80).aspx)

    再输入:

    makecert -r -pe -n "CN=MyClient" -ss My -sky exchange

    生成客户端证书,证书生成好以后,可以在IE里查看到,IE-->工具-->Internet选项-->内容-->证书

    记得要把证书导入到受信任的那栏,不然是访问不到的, 然后在IE-->工具-->Internet选项-->内容-->证书里导出一个CER,面通知过程中选不要是私钥, 这样给客户端使用

    socket服务器的建立代码如下,注意所引用的命名空间:

    using System;
    using System.ServiceModel;
    using System.Net;
    using System.Net.Sockets;
    using System.Net.Security;
    using System.Text;
    using System.Security.Authentication;
    using System.Security.Cryptography.X509Certificates;
    using System.IdentityModel.Tokens;
    using System.IdentityModel.Selectors;
    
    namespace ConsoleApp
    {
        public class Program
        {
            static X509Certificate serverCertificate = null;
    
            public static void RunServer()
            {
                //serverCertificate = X509Certificate.CreateFromSignedFile(@"C:Program FilesMicrosoft Visual Studio 8SDKv2.0samool.pvk");
                TcpListener listener = new TcpListener(IPAddress.Parse("192.168.20.139"), 901);
                listener.Start();
                while (true)
                {
                    try
                    {
                        Console.WriteLine("Waiting for a client to connect...");
                        TcpClient client = listener.AcceptTcpClient();
                        ProcessClient(client);
                    }
                    catch
                    {
     
                    }
                }
            }
    
            static void ProcessClient(TcpClient client)
            {
                SslStream sslStream = new SslStream(client.GetStream(), false);
                try
                {
                    sslStream.AuthenticateAsServer(serverCertificate, false, SslProtocols.Tls, true);
                    DisplaySecurityLevel(sslStream);
                    DisplaySecurityServices(sslStream);
                    DisplayCertificateInformation(sslStream);
                    DisplayStreamProperties(sslStream);
    
                    sslStream.ReadTimeout = 5000;
                    sslStream.WriteTimeout = 5000;
                    Console.WriteLine("Waiting for client message...");
                    string messageData = ReadMessage(sslStream);
                    Console.WriteLine("Received: {0}", messageData);
                    byte[] message = Encoding.UTF8.GetBytes("Hello from the server.");
                    Console.WriteLine("Sending hello message.");
                    sslStream.Write(message);
                }
                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();
                }
            }
    
            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("") != -1)
                    {
                        break;
                    }
                }
                while (bytes != 0);
    
                return messageData.ToString();
            }
    
            static void DisplaySecurityLevel(SslStream stream)
            {
                Console.WriteLine("Cipher: {0} strength {1}", stream.CipherAlgorithm, stream.CipherStrength);
                Console.WriteLine("Hash: {0} strength {1}", stream.HashAlgorithm, stream.HashStrength);
                Console.WriteLine("Key exchange: {0} strength {1}", stream.KeyExchangeAlgorithm, stream.KeyExchangeStrength);
                Console.WriteLine("Protocol: {0}", stream.SslProtocol);
            }
    
            static void DisplaySecurityServices(SslStream stream)
            {
                Console.WriteLine("Is authenticated: {0} as server? {1}", stream.IsAuthenticated, stream.IsServer);
                Console.WriteLine("IsSigned: {0}", stream.IsSigned);
                Console.WriteLine("Is Encrypted: {0}", stream.IsEncrypted);
            }
    
            static void DisplayStreamProperties(SslStream stream)
            {
                Console.WriteLine("Can read: {0}, write {1}", stream.CanRead, stream.CanWrite);
                Console.WriteLine("Can timeout: {0}", stream.CanTimeout);
            }
    
            static void DisplayCertificateInformation(SslStream stream)
            {
                Console.WriteLine("Certificate revocation list checked: {0}", stream.CheckCertRevocationStatus);
    
                X509Certificate localCertificate = stream.LocalCertificate;
                if (stream.LocalCertificate != null)
                {
                    Console.WriteLine("Local cert was issued to {0} and is valid from {1} until {2}.",
                    localCertificate.Subject,
                        localCertificate.GetEffectiveDateString(),
                        localCertificate.GetExpirationDateString());
                }
                else
                {
                    Console.WriteLine("Local certificate is null.");
                }
                X509Certificate remoteCertificate = stream.RemoteCertificate;
                if (stream.RemoteCertificate != null)
                {
                    Console.WriteLine("Remote cert was issued to {0} and is valid from {1} until {2}.",
                        remoteCertificate.Subject,
                        remoteCertificate.GetEffectiveDateString(),
                        remoteCertificate.GetExpirationDateString());
                }
                else
                {
                    Console.WriteLine("Remote certificate is null.");
                }
            }
    
            private static void DisplayUsage()
            {
                Console.WriteLine("To start the server specify:");
                Console.WriteLine("serverSync certificateFile.cer");
                //Environment.Exit(1);
            }
    
            public static void Main(string[] args)
            {
                //string certificate = null;
                //if (args == null || args.Length < 1)
                //{
                //    DisplayUsage();
                //}
                //certificate = args[0];
                try
                {
                    X509Store store = new X509Store(StoreName.My);
                    store.Open(OpenFlags.ReadWrite);
    
                    // 检索证书 
                    X509Certificate2Collection certs = store.Certificates.Find(X509FindType.FindBySubjectName, "MyServer", false); // vaildOnly = true时搜索无结果。
                    if (certs.Count == 0) return;
    
                    serverCertificate = certs[0];
                    RunServer();
                    store.Close(); // 关闭存储区。
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
                Console.ReadLine();
                //return 0;
    
    
    
                //try
                //{
                //    Console.WriteLine("服务端输出:" + ServiceSecurityContext.Current.PrimaryIdentity.AuthenticationType);
                //    Console.WriteLine(ServiceSecurityContext.Current.PrimaryIdentity.Name);
                //    Console.WriteLine("服务端时间:" + DateTime.Now.ToString());
                //}
                //catch (Exception ex)
                //{
                //    Console.WriteLine(ex.Message);
                //}
                //Console.ReadLine();
    
            }
        }
    
    
    }

    Sokect客户端代码如下:

    using System;
    using System.Security;
    using System.Net;
    using System.Net.Sockets;
    using System.Net.Security;
    using System.Text;
    using System.Security.Authentication;
    using System.Security.Cryptography.X509Certificates;
    
    namespace ConsoleAppClient
    {
        using System;
        using System.Collections;
        using System.Net;
        using System.Net.Security;
        using System.Net.Sockets;
        using System.Security.Authentication;
        using System.Text;
        using System.Security.Cryptography.X509Certificates;
        using System.IO;
    
        namespace Examples.System.Net
        {
            public class SslTcpClient
            {
                private static Hashtable certificateErrors = new Hashtable();
                // The following method is invoked by the RemoteCertificateValidationDelegate.
                public static 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;
                }
    
                public static void RunClient(string machineName)
                {
                    // Create a TCP/IP client socket.
                    // machineName is the host running the server application.
                    TcpClient client = new TcpClient(machineName, 901);
                    Console.WriteLine("Client connected.");
                    // Create an SSL stream that will close the client's stream.
                    SslStream sslStream = new SslStream(client.GetStream(), false, new RemoteCertificateValidationCallback(ValidateServerCertificate), null);
                    // The server name must match the name on the server certificate.
    
                    //X509Store store = new X509Store(StoreName.My);
                    //store.Open(OpenFlags.ReadWrite);
    
                    //// 检索证书 
                    //X509Certificate2Collection certs = store.Certificates.Find(X509FindType.FindBySubjectName, "MyServer", false); // vaildOnly = true时搜索无结果。
    
                    X509CertificateCollection certs = new X509CertificateCollection();
                    X509Certificate cert = X509Certificate.CreateFromCertFile(@"D:cashcer.cer");
                    certs.Add(cert);
                    try
                    {
                        sslStream.AuthenticateAsClient("MyServer", 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();
                        return;
                    }
                    // Encode a test message into a byte array.
                    // Signal the end of the message using the "<EOF>".
                    byte[] messsage = Encoding.UTF8.GetBytes("Hello from the client.<EOF>");
                    // Send hello message to the server. 
                    sslStream.Write(messsage);
                    sslStream.Flush();
                    // Read message from the server.
                    string serverMessage = ReadMessage(sslStream);
                    Console.WriteLine("Server says: {0}", serverMessage);
                    // Close the client connection.
                    client.Close();
                    Console.WriteLine("Client closed.");
                }
    
                static string ReadMessage(SslStream sslStream)
                {
                    // Read the  message sent by the server.
                    // The end of the message is signaled using the
                    // "<EOF>" marker.
                    byte[] buffer = new byte[2048];
                    StringBuilder messageData = new StringBuilder();
                    int bytes = -1;
                    do
                    {
                        bytes = sslStream.Read(buffer, 0, buffer.Length);
    
                        // Use Decoder class to convert from bytes to UTF8
                        // in case a character spans two buffers.
                        Decoder decoder = Encoding.UTF8.GetDecoder();
                        char[] chars = new char[decoder.GetCharCount(buffer, 0, bytes)];
                        decoder.GetChars(buffer, 0, bytes, chars, 0);
                        messageData.Append(chars);
                        // Check for EOF.
                        if (messageData.ToString().IndexOf("<EOF>") != -1)
                        {
                            break;
                        }
                    } while (bytes != 0);
    
                    return messageData.ToString();
                }
    
                private static void DisplayUsage()
                {
                    Console.WriteLine("To start the client specify:");
                    Console.WriteLine("clientSync machineName [serverName]");
                    Environment.Exit(1);
                }
    
                public static void Main(string[] args)
                {
                    string machineName = null; 
                    machineName = "192.168.20.139";
    
                    try
                    {                  
                        RunClient(machineName);
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine(ex.Message);
                    }
                    Console.ReadLine();
                }
            }
        }
    
    }

    运行就可以了。

    注意的是证书的取得, 客户端有个向服务器验证证书的方法:

    public static 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;
                }
    如果上面返回的SslPolicyErrors枚举值不是None你就应该检查你的证书是否正确, 是否添加到信任里面。

    转自http://www.cnblogs.com/whtydn/archive/2009/12/23/1630750.html

  • 相关阅读:
    leetcode 78. 子集 JAVA
    leetcode 91. 解码方法 JAVA
    leetcode 75. 颜色分类 JAVA
    leetcode 74 搜索二维矩阵 java
    leetcode 84. 柱状图中最大的矩形 JAVA
    last occurance
    first occurance
    classical binary search
    LC.234.Palindrome Linked List
    LC.142. Linked List Cycle II
  • 原文地址:https://www.cnblogs.com/guojian/p/5391723.html
Copyright © 2011-2022 走看看