C\#를 이용 하여 SSLSocket 암호 화 통신 을 실현 하 는 방법 에 대한 상세 한 설명

머리말
SSL Socket 통신 은 socket 에 대한 확장 으로 Socket 통신 의 데이터 안전성 을 증가 시 키 고 SSL 인증 은 단 방향 과 양 방향 인증 으로 나 뉜 다.단 방향 인증 은 서버 측의 합 법성 만 인증 하고 클 라 이언 트 의 합 법성 을 인증 하지 않 습 니 다.양 방향 인증 은 서버 와 클 라 이언 트 를 동시에 인증 하 는 것 이다.다음은 C\#를 사용 하여 단 방향 인증 과 양 방향 인증 을 실현 하 는 과정 을 말씀 드 리 고 코드 로 이 루어 집 니 다.
일방 인증
STEP 1:디지털 인증 서 를 준비 합 니 다.다음 스 크 립 트 로 생 성 할 수 있 습 니 다.
vs 2005 명령 행 상태 로 들 어가 면:
시작 C>프로그램 C>Microsoft Visual Studio 2005 C>Visual Studio Tools C>Visual Studio 2005 명령 알림
입력:Makecert-r-pe-n"CN=TestServer"-ss Root-sky exchange
설명:위의 명령 은 신뢰 할 수 있 는 루트 인증 서 를 만 들 것 입 니 다.
두 번 째 단 계 는 서버 엔 드 프로그램 을 만 듭 니 다.코드 는 다음 과 같 습 니 다.

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()
  {
    TcpListener listener = new TcpListener(IPAddress.Parse("192.168.1.25"), 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;
      byte[] message = Encoding.UTF8.GetBytes("Hello from the server.");
      Console.WriteLine("Sending hello message.");
      sslStream.Write(message);
      Console.WriteLine("Waiting for client message...");
      while (true)
      {
        string messageData = ReadMessage(sslStream);
        Console.WriteLine("Received: {0}", messageData);
        if (messageData.ToUpper() == "EXIT")
          break;
      } 
    }
    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");
  }

  public static void Main(string[] args)
  {
    try
    {
      X509Store store = new X509Store(StoreName.Root);
      store.Open(OpenFlags.ReadWrite);
      //      
      X509Certificate2Collection certs = store.Certificates.Find(X509FindType.FindBySubjectName, "TestServer", false); // vaildOnly = true      。
      if (certs.Count == 0) return;

      serverCertificate = certs[0];
      RunServer();
      store.Close(); //      。
    }
    catch (Exception ex)
    {
      Console.WriteLine(ex.Message);
    }
    Console.ReadLine();
  }
}
}
3 단계 클 라 이언 트 코드 만 들 기

namespace ConsoleAppClient
{
using System;
using System.Collections;
using System.Net.Security;
using System.Net.Sockets;
using System.Security.Authentication;
using System.Text;
using System.Security.Cryptography.X509Certificates;
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);
      try
      {
        sslStream.AuthenticateAsClient("TestServer");
      }
      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);

      messsage = Encoding.UTF8.GetBytes("exit");
      sslStream.Write(messsage);
      sslStream.Flush();
      // 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.1.25";
      try
      {
        RunClient(machineName);
      }
      catch (Exception ex)
      {
        Console.WriteLine(ex.Message);
      }
      Console.ReadLine();
    }
  }
}
}
다음 그림 과 같이 실행 효과:

통신 실 패 를 초래 할 수 있 는 문 제 는 다음 과 같다.
1)인증 서 는 신뢰 하 는 루트 인증서 목록 에 가 져 오지 않 았 습 니 다.2)인증서 가 효력 을 상실 합 니 다.3)클 라 이언 트 가 AuthenticateasClient 를 사용 하여 등록 할 때 서버 쪽 인증서 이름 을 올 바 르 게 사용 하지 않 았 습 니 다.
2.쌍방 향 인증
STEP 1:필요 한 인증 서 를 만 들 고 서버 에서 필요 한 인증서 와 단 방향 인증 에서 의 생 성 과정
vs 2005 명령 행 상태 로 들 어가 면:
시작 C>프로그램 C>Microsoft Visual Studio 2005 C>Visual Studio Tools C>Visual Studio 2005 명령 알림
입력:
makecert -r -pe -n “CN=TestClient” -ss Root -sky exchange
2 단계:서버 프로그램 만 들 기
서버 쪽 프로그램 과 단 방향 인증 서버 쪽 코드
STEP 3:클 라 이언 트 프로그램 만 들 기

namespace ConsoleAppClient
{
using System;
using System.Collections;
using System.Net.Security;
using System.Net.Sockets;
using System.Security.Authentication;
using System.Text;
using System.Security.Cryptography.X509Certificates;
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.Root);
      store.Open(OpenFlags.ReadWrite);

      ////      
      X509Certificate2Collection certs = store.Certificates.Find(X509FindType.FindBySubjectName, "TestClient", false);        
      try
      {
        sslStream.AuthenticateAsClient("TestServer", 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);

      messsage = Encoding.UTF8.GetBytes("exit");
      sslStream.Write(messsage);
      sslStream.Flush();

      // 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.1.25";
      try
      {
        RunClient(machineName);
      }
      catch (Exception ex)
      {
        Console.WriteLine(ex.Message);
      }
      Console.ReadLine();
    }
  }
}
}
총결산
C\#를 이용 하여 SSLSocket 암호 화 통신 을 실현 하 는 이 글 은 여기까지 소개 되 었 습 니 다.더 많은 관련 C\#SSLSocket 암호 화 통신 을 실현 하 는 내용 은 우리 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 조회 하 시기 바 랍 니 다.앞으로 많은 응원 바 랍 니 다!

좋은 웹페이지 즐겨찾기