How to Create a TCP Client connection with a Client Certificate in Powershell

10.2k views Asked by At

With Following code i can establish a SSL Connection:

   $cert = dir cert:\CurrentUser\My | where {$_.Subject -like "*Alice*"}

   $computerName = "google.com"
   $port = "443"

   $socket = New-Object Net.Sockets.TcpClient($computerName, $port)
   $stream = $socket.GetStream()

   $sslStream = New-Object System.Net.Security.SslStream $stream,$false
   $sslStream.AuthenticateAsClient($computerName)


    $sslStream

This Works fine. But now i wan't to add a Client Certificate for Authentication. Think i just need to substitute

$sslStream.AuthenticateAsClient($computerName)

with

$sslStream.BeginAuthenticateAsClient($computerName,$cert,"SslProtocols",$false,"Foo" ,"Bar")

But i wasn't lucky to get the Arguments right. Can Sombody solve the Assync Calls please ;-) Maybe i need some C# code for this?!?

Arguments are:

System.IAsyncResult BeginAuthenticateAsClient(

string targetHost, 
System.Security.Cryptography.X509Certificates.X509CertificateCollection clientCertificates, 
System.Security.Authentication.SslProtocols enabledSslProtocols,
bool checkCertificateRevocation, 
System.AsyncCallback asyncCallback, 
System.Object asyncState)

What i finally want to achieve is to list and later specify the CipherSuites the client is connected to. (I could use Wireshark i know ;-) )

2

There are 2 answers

0
icnivad On BEST ANSWER

Finally got it working, wasnt argument 4 but the $Cert which was no collection.

   $cert = dir cert:\CurrentUser\My | where {$_.Subject -like "*alice*"}

   $computerName = "google.com"
   $port = "443"

    [System.Security.Authentication.SslProtocols]$protocol = "ssl3"

   $certcol = New-object System.Security.Cryptography.X509Certificates.X509CertificateCollection
   $certcol.Add($cert)




   $socket = New-Object Net.Sockets.TcpClient($computerName, $port)
   $stream = $socket.GetStream()

   $sslStream = New-Object System.Net.Security.SslStream $stream,$false
   #$sslStream.AuthenticateAsClient($computerName)
   $sslStream.AuthenticateAsClient($computerName,$certcol,$protocol,$false) 


    $sslStream
2
Bruno On

According to the documentation, the difference between AuthenticateAsClient and BeginAuthenticateAsClient is that the latter is for asynchronous use.

You should try AuthenticateAsClient(String, X509CertificateCollection, SslProtocols, Boolean), where the second argument is a collection of client certificates that can be used (preferably X509Certificate2, since you'll need the private key associated with the certificate for it to be usable for authentication).