force cipher suite for PowerShell session without changing system settings
Is there a .NET/PowerShell equivalent to the -cipher switch in OpenSSL? That is, to attempt an HTTPS connection using a particular cipher suite without changing the cipher order in all of Windows?
For instance, the following command will succeed against a system with Diffie-Hellman key exchange enabled, but will fail otherwise:
openssl s_client -connect foo.example.com:443 -cipher "DHE"
The PowerShell script below will connect at the strongest negotiated cipher, so when run against a host that supports both DiffieHellman and ECDH_Ephem key exchange, it will always show the latter, unless I first remove all cipher suites except TLS_DHE ones using Disable-TlsCipherSuite. However I don't want to do that, since that impacts TCP connections for the entire OS. Is there a way to do it on a per-session basis?
$remotehost = 'foo.example.com'
$port = '443'
$protocol = 'TLS12'
$clientcert = $null
$checkrevocation = $true
$keyexchanges = @{
0 = 'None'
9216 = 'RsaSign'
41984 = 'RsaKeyX'
43522 = 'DiffieHellman'
44550 = 'ECDH_Ephem'
}
$tcpclient = new-object "System.Net.Sockets.TcpClient"
try {
$tcpclient.Connect([System.String]$remotehost, [System.Int32]$port)
}
catch {"Error making TCP connection to $remotehost" + ":" + $port}
[System.Net.Security.SslStream]$sslstream = $null
try {
$sslstream = new-object System.Net.Security.SslStream(
$tcpclient.GetStream(),
$true,
[System.Net.Security.RemoteCertificateValidationCallback]{$true}
)
}
catch {'Error establishing SSL stream.'}
try {
$sslstream.AuthenticateAsClient(
$remotehost, $clientcert, $protocol, $checkrevocation)
$keyex = [int]$sslstream.KeyExchangeAlgorithm
'Connection successful with key exchange algorithm: ' + $keyexchanges.$keyex
}
catch {"Connection with $protocol failed."}
try {
$sslstream.Close()
$tcpclient.Close()
}
catch {}