C #. ССЛ подтверждаю. System.NotSupportedException - PullRequest
0 голосов
/ 19 ноября 2018

Я создаю клиент-серверное приложение.

Код сервера:

public sealed class SslTcpServer {
    static X509Certificate serverCertificate = null;
    public static void RunServer(string certificate) {
        serverCertificate = new X509Certificate2(certificate, "123", X509KeyStorageFlags.MachineKeySet);
        TcpListener listener = new TcpListener(IPAddress.Parse("127.0.0.1"), 56748);
        listener.Start();
        while (true) {
            Console.WriteLine("Waiting for a client to connect...");
            TcpClient client = listener.AcceptTcpClient();
            ProcessClient(client);
        }
    }
    static void ProcessClient(TcpClient client) {
        SslStream sslStream = new SslStream(client.GetStream());
        try {
            sslStream.AuthenticateAsServer(serverCertificate,
                clientCertificateRequired: false, 
                checkCertificateRevocation: true);

            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.<EOF>");
            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("<EOF>") != -1)
                break;
        } while (bytes != 0);

        return messageData.ToString();
    }
    public static int Main(string[] args) {
        string certificate = "server.crt";
        RunServer(certificate);
        return 0;
    }
}

Код клиента:

public class SslTcpClient {
    private static Hashtable certificateErrors = new Hashtable();

    public 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;
    }
    public static void RunClient(string machineName, string serverName) {
        TcpClient client = new TcpClient("127.0.0.1", 56748);
        Console.WriteLine("Client connected.");
        SslStream sslStream = new SslStream(
            client.GetStream(),
            false,
            new RemoteCertificateValidationCallback(ValidateServerCertificate),
            null
            );
        try {
            sslStream.AuthenticateAsClient("127.0.0.1");
        } catch (AuthenticationException e) {
            Console.WriteLine("Exception: {0}", e.Message);
            Console.WriteLine(e.StackTrace);
            if (e.InnerException != null) {
                Console.WriteLine("Inner exception: {0}", e.InnerException.Message);
            }
            Console.WriteLine("Authentication failed - closing the connection.");
            client.Close();
            return;
        }
        byte[] messsage = Encoding.UTF8.GetBytes("Hello from the client.<EOF>");
        sslStream.Write(messsage);
        sslStream.Flush();
        string serverMessage = ReadMessage(sslStream);
        Console.WriteLine("Server says: {0}", serverMessage);
        client.Close();
        Console.WriteLine("Client closed.");
    }
    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();
    }
    public static int Main(string[] args) {
        string serverCertificateName = "127.0.0.1";
        string machineName = "127.0.0.1";
        SslTcpClient.RunClient(machineName, serverCertificateName);
        return 0;
    }
}

Я уже создал сертификат SSL "server.crt", но не могу подключить пользователя к серверу.

У меня есть необработанное исключение:

System.NotSupportedException: серверный режим SSL должен использовать сертификат со связанным закрытым ключом.

1 Ответ

0 голосов
/ 19 ноября 2018

Исключение говорит о том, что вам нужен закрытый ключ также и сертификата сервера, поскольку сервер SSL должен иметь его для расшифровки ключа сеанса, сгенерированного клиентом.Сказав это, сертификат, который вы передаете методу RunServer , - это Server.crt, который является только открытым сертификатом (т. Е. У него нет связанного закрытого ключа).Если вы сгенерировали этот сертификат самостоятельно, вы также должны сгенерировать файл server.p12 или server.pfx (в котором также есть закрытый ключ), а затем создать сертификат X509 из него.Как то так ..

var certificate = new X509Certificate("server.pfx", "password_of_the_private_key");
...