I am trying to retrieve the TLS Version information. The code I have below makes a successful HTTP GET call using HttpClient. What am I missing? Where do I get the TLS Version information from HttpClient?
I am kind of doing the same thing as was suggested in Which TLS version was negotiated? but that is specific to WebRequest which is not the same as HttpClient.
static async Task MainAsync()
{
Uri baseURI = new Uri("https://jsonplaceholder.typicode.com/posts/1");
string apiPath = "";
using (var client = new HttpClient())
{
client.BaseAddress = baseURI;
HttpResponseMessage response = await client.GetAsync(apiPath);
Console.WriteLine("HTTP status code: " + response.StatusCode.ToString());
GetSSLConnectionInfo(response, client.BaseAddress.ToString(), apiPath);
}
Console.ReadKey();
}
static async Task GetSSLConnectionInfo(HttpResponseMessage response, string baseURI, string apiPath)
{
using (Stream stream = await response.RequestMessage.Content.ReadAsStreamAsync())
{
BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.NonPublic;
Stream CompressedStream = null;
if (stream.GetType().BaseType == typeof(GZipStream))
{
CompressedStream = (GZipStream)stream;
}
else if (stream.GetType().BaseType == typeof(DeflateStream))
{
CompressedStream = (DeflateStream)stream;
}
var objbaseStream = CompressedStream?.GetType().GetProperty("BaseStream").GetValue(stream);
if (objbaseStream == null)
{
objbaseStream = stream;
}
var objConnection = objbaseStream.GetType().GetField("m_Connection", bindingFlags).GetValue(objbaseStream);
var objTlsStream = objConnection.GetType().GetProperty("NetworkStream", bindingFlags).GetValue(objConnection);
var objSslState = objTlsStream.GetType().GetField("m_Worker", bindingFlags).GetValue(objTlsStream);
SslProtocols b = (SslProtocols)objSslState.GetType().GetProperty("SslProtocol", bindingFlags).GetValue(objSslState);
Console.WriteLine("SSL Protocol Used for " + baseURI + apiPath + System.Environment.NewLine + "The TLS version used is " + b);
}
}
I am expecting TLS connection Info but I get an exception.
Right-click the page or select the Page drop-down menu, and select Properties. In the new window, look for the Connection section. This will describe the version of TLS or SSL used.
You need TLS 1.2+ support for HttpClient . You don't need TLS 1.2+ support for WebClient .
Under the hood HttpClient
uses internal TlsStream
class (as in your example for WebRequest
). We just need to find it in another location. Here is an example:
static void Main(string[] args)
{
using (var client = new HttpClient())
{
using (var response = client.GetAsync("https://example.com/").Result)
{
if (response.Content is StreamContent)
{
var webExceptionWrapperStream = GetPrivateField(response.Content, "content");
var connectStream = GetBasePrivateField(webExceptionWrapperStream, "innerStream");
var connection = GetPrivateProperty(connectStream, "Connection");
var tlsStream = GetPrivateProperty(connection, "NetworkStream");
var state = GetPrivateField(tlsStream, "m_Worker");
var protocol = (SslProtocols)GetPrivateProperty(state, "SslProtocol");
Console.WriteLine(protocol);
}
else
{
// not sure if this is possible
}
}
}
}
private static object GetPrivateProperty(object obj, string property)
{
return obj.GetType().GetProperty(property, BindingFlags.Instance | BindingFlags.NonPublic).GetValue(obj);
}
private static object GetPrivateField(object obj, string field)
{
return obj.GetType().GetField(field, BindingFlags.Instance | BindingFlags.NonPublic).GetValue(obj);
}
private static object GetBasePrivateField(object obj, string field)
{
return obj.GetType().BaseType.GetField(field, BindingFlags.Instance | BindingFlags.NonPublic).GetValue(obj);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With