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 Files\Microsoft Visual Studio 8\SDK\v2.0\samool.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



    返回导读目录,阅读更多随笔



    分割线,以下为博客签名:

    软件臭虫情未了
    • 编码一分钟
    • 测试十年功


    随笔如有错误或不恰当之处、为希望不误导他人,望大侠们给予批评指正。

  • 相关阅读:
    数据结构与算法系列——排序(6)_树形选择排序
    数据结构与算法系列——排序(7)_堆排序
    数据结构与算法系列——排序(5)_简单选择排序
    数据结构与算法系列——排序(4)_Shell希尔排序
    数据结构与算法系列——排序(3)_折半插入排序
    数据结构与算法系列——排序(2)_直接插入排序
    数据结构与算法系列——排序(1)_概述
    Java高级开发_性能优化的细节
    图形推理
    美团点评面试20190515
  • 原文地址:https://www.cnblogs.com/08shiyan/p/2036541.html
Copyright © 2011-2022 走看看