Thread: SslStream with client certificates

  1. #1
    Registered User
    Join Date
    Oct 2006
    Posts
    3,445

    SslStream with client certificates

    I'm having no luck getting client certificates working with my SslStream project. No matter what I do, I can't get it to actually use the client certificate, despite the fact that all certificates are valid and trusted, and I have imported the CA certificate for the ones I generated myself, and it just doesn't work. I must be missing something, but I've been over it dozens of times, reviewed documentation, examples, and hours of google searching, and I just can't get it to work. What am I doing wrong?

    Client:
    Code:
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Net.Security;
    using System.Net.Sockets;
    using System.Reflection;
    using System.Security.Cryptography.X509Certificates;
    using System.Text;
    
    namespace SslClient
    {
        class SslClientProgram
        {
            static void Main(string[] args)
            {
                TcpClient client = new TcpClient("localhost", 443);
    
                SslStream stream = new SslStream(client.GetStream(), false, VerifyServerCertificate, null);
    
                Assembly assembly = System.Reflection.Assembly.GetExecutingAssembly();
                string location = assembly.Location;
                int pos = location.LastIndexOf('\\');
                location = location.Substring(0, pos);
                X509Certificate2 certificate = new X509Certificate2(location + "\\my.client.certificate.pfx", "password");
    
                stream.AuthenticateAsClient("my.host.name", new X509Certificate2Collection(certificate), System.Security.Authentication.SslProtocols.Tls, false);
    
                StreamReader reader = new StreamReader(stream);
                StreamWriter writer = new StreamWriter(stream);
    
                while (true)
                {
                    string line = System.Console.ReadLine();
                    writer.WriteLine(line);
                    writer.Flush();
                    if (line == "close") break;
                    line = reader.ReadLine();
                    System.Console.WriteLine("Received: {0}", line);
                }
    
                stream.Close();
            }
    
            private static bool VerifyServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
            {
                return true;
            }
        }
    }
    Server:
    Code:
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Net.Security;
    using System.Net.Sockets;
    using System.Reflection;
    using System.Security.Cryptography.X509Certificates;
    using System.Text;
    
    namespace SslServer
    {
        class SslServerProgram
        {
            static void Main(string[] args)
            {
                TcpListener server = new TcpListener(System.Net.IPAddress.Loopback, 443);
    
                server.Start();
    
                TcpClient client = server.AcceptTcpClient();
    
                SslStream stream = new SslStream(client.GetStream(), false, VerifyClientCertificate, null);
    
                Assembly assembly = System.Reflection.Assembly.GetExecutingAssembly();
                string location = assembly.Location;
                int pos = location.LastIndexOf('\\');
                location = location.Substring(0, pos);
                X509Certificate2 certificate = new X509Certificate2(location + "\\my.server.certificate.pfx", "password");
    
                stream.AuthenticateAsServer(certificate, false, System.Security.Authentication.SslProtocols.Tls, false);
    
                if (stream.RemoteCertificate != null)
                {
                    System.Console.WriteLine(stream.RemoteCertificate.Subject);
                }
                else
                {
                    System.Console.WriteLine("No client certificate.");
                }
    
                StreamReader reader = new StreamReader(stream);
                StreamWriter writer = new StreamWriter(stream);
    
                bool clientClose = false;
                while (!System.Console.KeyAvailable)
                {
                    System.Console.WriteLine("Waiting for data...");
                    string line = reader.ReadLine();
                    System.Console.WriteLine("Received: {0}", line);
                    
                    if (line == "close")
                    {
                        clientClose = true;
                        break;
                    }
    
                    writer.WriteLine(line);
                    writer.Flush();
                }
    
                if (!clientClose) System.Console.ReadKey();
    
                stream.Close();
                server.Stop();
            }
    
            private static bool VerifyClientCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
            {
                return true;
            }
        }
    }
    The server always says "No client certificate."
    What can this strange device be?
    When I touch it, it gives forth a sound
    It's got wires that vibrate and give music
    What can this thing be that I found?

  2. #2
    Registered User
    Join Date
    Oct 2006
    Posts
    3,445
    Seeing no responses, I have posted it as a question on StackOverflow.
    What can this strange device be?
    When I touch it, it gives forth a sound
    It's got wires that vibrate and give music
    What can this thing be that I found?

  3. #3
    Gawking at stupidity
    Join Date
    Jul 2004
    Location
    Oregon, USA
    Posts
    3,218
    Yeah, sorry. I have no experience with this.
    If you understand what you're doing, you're not learning anything.

  4. #4
    Registered User
    Join Date
    Jan 2008
    Posts
    290
    This might be silly, but it looks like you're passing false for the clientCertificateRequired parameter to stream.AuthenticateAsServer. Shouldn't you be passing true?

    This guy has some sample code up on codeproject: Downloads: An Introduction to Mutual SSL Authentication - CodeProject It looks like he's passing true for that param, otherwise I think his socket code looks pretty similar to yours.

  5. #5
    Registered User
    Join Date
    Oct 2006
    Posts
    3,445
    Quote Originally Posted by arpsmack View Post
    This might be silly, but it looks like you're passing false for the clientCertificateRequired parameter to stream.AuthenticateAsServer. Shouldn't you be passing true?
    If I pass true, it just throws exceptions, because there is no client certificate. When it's false, it still allows a client certificate, but doesn't require it.

    Quote Originally Posted by arpsmack View Post
    This guy has some sample code up on codeproject: Downloads: An Introduction to Mutual SSL Authentication - CodeProject It looks like he's passing true for that param, otherwise I think his socket code looks pretty similar to yours.
    I downloaded and tried out the code from that article, and it did exactly the same thing. No client certificate was used, even though it was specified. I'm really starting to think that the advertised client certificate support in .Net is entirely fictional.
    What can this strange device be?
    When I touch it, it gives forth a sound
    It's got wires that vibrate and give music
    What can this thing be that I found?

  6. #6
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    If I pass true, it just throws exceptions, because there is no client certificate.
    When it's false, it still allows a client certificate, but doesn't require it.
    I'm really starting to think that the advertised client certificate support in .Net is entirely fictional.
    O_o

    I admit that I don't do C# programming, but I keep seeing this pop up so I thought I'd take a look.

    I do not know the source of the problem, but I wonder if you've tried the obvious conditional approach.

    Code:
    try
    {
        stream.AuthenticateAsServer(certificate, true, System.Security.Authentication.SslProtocols.Tls, false);
    }
    catch(...) // I don't know the C# version of a generic `catch' block.
    {
        stream.AuthenticateAsServer(certificate, false, System.Security.Authentication.SslProtocols.Tls, false);
    }
    Soma
    “Salem Was Wrong!” -- Pedant Necromancer
    “Four isn't random!” -- Gibbering Mouther

  7. #7
    Registered User
    Join Date
    Oct 2006
    Posts
    3,445
    It turns out I was wrong. If that parameter is false, it ignores client certificates altogether. I got it to work by changing it to true. Oddly enough, that didn't seem to work before, although there may have been other things I was doing wrong at that time.
    What can this strange device be?
    When I touch it, it gives forth a sound
    It's got wires that vibrate and give music
    What can this thing be that I found?

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. System.Net.Security.SslStream closes improperly
    By Elkvis in forum C# Programming
    Replies: 1
    Last Post: 02-24-2012, 12:59 PM
  2. Client/server problem; server either stops receiving data or client stops sending
    By robot-ic in forum Networking/Device Communication
    Replies: 10
    Last Post: 02-16-2009, 11:45 AM
  3. Digital Certificates - Vista
    By Beaner in forum Windows Programming
    Replies: 2
    Last Post: 03-28-2007, 02:45 PM
  4. FTP Client
    By waldoayo in forum Networking/Device Communication
    Replies: 5
    Last Post: 04-29-2006, 11:49 AM
  5. Certificates??
    By afreedboy in forum A Brief History of Cprogramming.com
    Replies: 14
    Last Post: 12-31-2003, 09:14 PM