简体   繁体   中英

c# TLS client without client certificate

I'm trying to create a TLS client without the need for TLS client certificate .

This works with client certificate :

using System;
using System.Diagnostics;
using System.Globalization;
using System.Net.Security;
using System.Net.Sockets;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
using System.Text;

namespace SslClient {
    class App {

        private static readonly string ServerIpAddress = "127.0.0.1";
        private static readonly int ServerPort = 3000;
        private static readonly string ServerCertificateName = "MyServer";

        private static readonly string ClientCertificateFile = "client.pfx";
        private static readonly string ClientCertificatePassword = null;


        static void Main(string[] args) {
            try {
                var clientCertificate = new X509Certificate2(ClientCertificateFile, ClientCertificatePassword);
                var clientCertificateCollection = new X509CertificateCollection(new X509Certificate[] { clientCertificate });

                using (var client = new TcpClient(ServerIpAddress, ServerPort))
                using (var sslStream = new SslStream(client.GetStream(), false, App_CertificateValidation)) {
                    Console.WriteLine("Device connected.");

                    sslStream.AuthenticateAsClient(ServerCertificateName, clientCertificateCollection, SslProtocols.Tls12, false);

                    var outputMessage = "Hello";
                    var outputBuffer = Encoding.UTF8.GetBytes(outputMessage);
                    sslStream.Write(outputBuffer);

                    var inputBuffer = new byte[4096];
                    var inputBytes = 0;
                    while (inputBytes == 0) {
                        inputBytes = sslStream.Read(inputBuffer, 0, inputBuffer.Length);
                    }
                    var inputMessage = Encoding.UTF8.GetString(inputBuffer, 0, inputBytes);
                    Console.WriteLine(inputMessage);
                }
            } catch (Exception ex) {
                Console.WriteLine("***** {0}\n***** {1}!", ex.GetType().Name, ex.Message);
            }
        }


        private static bool App_CertificateValidation(Object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) {
            if (sslPolicyErrors == SslPolicyErrors.None) { return true; }
            if (sslPolicyErrors == SslPolicyErrors.RemoteCertificateChainErrors) { return true; } //we don't have a proper certificate tree
            Console.WriteLine("*** SSL Error: " + sslPolicyErrors.ToString());
            return false;
        }
    }
}

Trying to remove the need for TLS client certificate is as follows:

using System;
using System.Diagnostics;
using System.Globalization;
using System.Net.Security;
using System.Net.Sockets;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
using System.Text;

namespace SslClient {
    class App {

        private static readonly string ServerIpAddress = "127.0.0.1";
        private static readonly int ServerPort = 3000;

        static void Main(string[] args) {
            try {
                using (var client = new TcpClient(ServerIpAddress, ServerPort))
                using (var sslStream = new SslStream(client.GetStream(), false)) {
                    Console.WriteLine("Device connected.");

                    var outputMessage = "Hello";
                    var outputBuffer = Encoding.UTF8.GetBytes(outputMessage);

                    try {
                        sslStream.Write(outputBuffer);
                    } catch (Exception x) {
                        var baseException = x.GetBaseException();
                        Console.WriteLine(baseException);
                    }


                    var inputBuffer = new byte[4096];
                    var inputBytes = 0;
                    while (inputBytes == 0) {
                        inputBytes = sslStream.Read(inputBuffer, 0, inputBuffer.Length);
                    }
                    var inputMessage = Encoding.UTF8.GetString(inputBuffer, 0, inputBytes);
                    Console.WriteLine(inputMessage);
                }
            } catch (Exception ex) {
                Console.WriteLine("***** {0}\n***** {1}!", ex.GetType().Name, ex.Message);
            }
        }

    }
}

But this outputs:

Device connected.
System.InvalidOperationException: This operation is only allowed using a successfully authenticated context.
  at Mono.Net.Security.MobileAuthenticatedStream.CheckThrow (System.Boolean authSuccessCheck, System.Boolean shutdownCheck) [0x0001e] in <cbad0c8bbe7b432eb83038c06be00093>:0
  at Mono.Net.Security.MobileAuthenticatedStream+<StartOperation>d__58.MoveNext () [0x00011] in <cbad0c8bbe7b432eb83038c06be00093>:0
***** AggregateException
***** One or more errors occurred.!

you need to change your code if use tls you need to authenticate first.

using System;
using System.Diagnostics;
using System.Globalization;
using System.Net.Security;
using System.Net.Sockets;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
using System.Text;

namespace SslClient {
class App {

    private static readonly string ServerIpAddress = "127.0.0.1";
    private static readonly int ServerPort = 3000;

    static void Main(string[] args) {
        try {
            using (var client = new TcpClient(ServerIpAddress, ServerPort))
            using (var sslStream = new SslStream(client.GetStream(), false, new RemoteCertificateValidationCallback(App_CertificateValidation)) {
            sslStream.AuthenticateAsClient(ServerIpAddress);
                Console.WriteLine("Device connected.");

                var outputMessage = "Hello";
                var outputBuffer = Encoding.UTF8.GetBytes(outputMessage);

                try {
                    sslStream.Write(outputBuffer);
                } catch (Exception x) {
                    var baseException = x.GetBaseException();
                    Console.WriteLine(baseException);
                }


                var inputBuffer = new byte[4096];
                var inputBytes = 0;
                while (inputBytes == 0) {
                    inputBytes = sslStream.Read(inputBuffer, 0, inputBuffer.Length);
                }
                var inputMessage = Encoding.UTF8.GetString(inputBuffer, 0, inputBytes);
                Console.WriteLine(inputMessage);
            }
        } catch (Exception ex) {
            Console.WriteLine("***** {0}\n***** {1}!", ex.GetType().Name, ex.Message);
        }
    }
 private static bool App_CertificateValidation(Object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) {
        if (sslPolicyErrors == SslPolicyErrors.None) { return true; }
        if (sslPolicyErrors == SslPolicyErrors.RemoteCertificateChainErrors) { return true; } //we don't have a proper certificate tree
        Console.WriteLine("*** SSL Error: " + sslPolicyErrors.ToString());
        return false;
    }
}
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM