栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

协商了哪个TLS版本?

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

协商了哪个TLS版本?

您可以使用反射来获取

TlsStream->SslState->SslProtocol
属性值。
这些信息可以从双方返回的流中提取
HttpWebRequest.GetRequestStream()
HttpWebRequest.GetResponseStream()

ExtractSslProtocol()
还处理压缩
GzipStream
或者
DeflateStream
当被返回
WebRequest

AutomaticDecompression被激活。

验证将在中进行

ServerCertificatevalidationCallback
,当使用初始化请求时会调用。
request.GetRequestStream()

注意

SecurityProtocolType.Tls13
包含在.Net framework
4.8+
和.Net
Core中
3.0+

using System.IO.Compression;using System.Net;using System.Net.Security;using System.Reflection;using System.Security.Authentication;using System.Security.Cryptography;using System.Security.Cryptography.X509Certificates;    //(...)    ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 |SecurityProtocolType.Tls |SecurityProtocolType.Tls11 |SecurityProtocolType.Tls12 |SecurityProtocolType.Tls13;    ServicePointManager.ServerCertificatevalidationCallback += TlsValidationCallback;    Uri requestUri = new Uri("https://somesite.com");    var request = WebRequest.CreateHttp(requestUri);    request.Method = WebRequestMethods.Http.Post;    request.ServicePoint.Expect100Continue = false;    request.AllowAutoRedirect = true;    request.cookieContainer = new cookieContainer();    request.ContentType = "application/x-www-form-urlenpred";    var postdata = Encoding.UTF8.GetBytes("Some postdata here");    request.ContentLength = postdata.Length;    request.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident / 7.0; rv: 11.0) like Gecko";    request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;    request.Headers.Add(HttpRequestHeader.AcceptEncoding, "gzip, deflate;q=0.8");    request.Headers.Add(HttpRequestHeader.CacheControl, "no-cache");    using (var requestStream = request.GetRequestStream()) {        //Here the request stream is already validated        SslProtocols sslProtocol = ExtractSslProtocol(requestStream);        if (sslProtocol < SslProtocols.Tls12)        { // Refuse/close the connection        }    }    //(...)private SslProtocols ExtractSslProtocol(Stream stream){        if (stream is null) return SslProtocols.None;        BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.NonPublic;        Stream metaStream = stream;        if (stream.GetType().baseType == typeof(GZipStream)) { metaStream = (stream as GZipStream).baseStream;        }        else if (stream.GetType().baseType == typeof(DeflateStream)) { metaStream = (stream as DeflateStream).baseStream;        }        var connection = metaStream.GetType().GetProperty("Connection", bindingFlags).GetValue(metaStream);        if (!(bool)connection.GetType().GetProperty("UsingSecureStream", bindingFlags).GetValue(connection)) { // Not a Https connection return SslProtocols.None;        }        var tlsStream = connection.GetType().GetProperty("NetworkStream", bindingFlags).GetValue(connection);        var tlsState = tlsStream.GetType().GetField("m_Worker", bindingFlags).GetValue(tlsStream);        return (SslProtocols)tlsState.GetType().GetProperty("SslProtocol", bindingFlags).GetValue(tlsState);}

RemoteCertificatevalidationCallback
对所使用的安全协议的一些有用的信息。(请参阅:传输层安全性(TLS)参数(IANA)和RFC
5246)。
使用的安全协议的类型可以提供足够的信息,因为每个协议版本都支持哈希和加密算法的子集。
Tls 1.2引入
HMAC-SHA256
并弃用
IDEA
DES
加密(所有变体在链接的文档中列出)。

在这里,我插入了

OIDExtractor
,其中列出了正在使用的算法。
请注意,TcpClient()和WebRequest()都将到达此处。

private bool TlsValidationCallback(object sender, X509Certificate CACert, X509Chain CAChain, SslPolicyErrors sslPolicyErrors){    List<Oid> oidExtractor = CAChain       .ChainElements       .Cast<X509ChainElement>()       .Select(x509 => new Oid(x509.Certificate.SignatureAlgorithm.Value))       .ToList();    // Inspect the oidExtractor list    if (sslPolicyErrors == SslPolicyErrors.None)         return true;    X509Certificate2 certificate = new X509Certificate2(CACert);    //If you needed/have to pass a certificate, add it here.    //X509Certificate2 cert = new X509Certificate2(@"[localstorage]/[ca.cert]");    //CAChain.ChainPolicy.ExtraStore.Add(cert);    CAChain.Build(certificate);    foreach (X509ChainStatus CACStatus in CAChain.ChainStatus)    {        if ((CACStatus.Status != X509ChainStatusFlags.NoError) & (CACStatus.Status != X509ChainStatusFlags.UntrustedRoot)) return false;    }    return true;}

更新2:

secur32.dll
- >
QueryContextAttributesW()
方法,允许查询一个初始化流的连接安全性上下文。

[Dllimport("secur32.dll", CharSet = CharSet.Auto, ExactSpelling=true, SetLastError=false)]private static extern int QueryContextAttributesW(SSPIHandle contextHandle,      [In] ContextAttribute attribute,      [In] [Out] ref SecPkgContext_ConnectionInfo ConnectionInfo);

从文档中可以看到,此方法返回一个

void* buffer
引用
SecPkgContext_ConnectionInfo
结构的:

//[SuppressUnmanagedCodeSecurity]private struct SecPkgContext_ConnectionInfo{    public SchProtocols dwProtocol;    public ALG_ID aiCipher;    public int dwCipherStrength;    public ALG_ID aiHash;    public int dwHashStrength;    public ALG_ID aiExch;    public int dwExchStrength;}

所述

SchProtocols dwProtocol
构件是SslProtocol。

有什么收获。

TlsStream.Context.m_SecurityContext._handle
引用连接上下文句柄是不公开的。
因此,您只能再次通过反射或通过返回的
System.Net.Security.AuthenticatedStream
派生类(
System.Net.Security.SslStream
System.Net.Security.NegotiateStream
)来获取它
TcpClient.GetStream()

不幸的是,WebRequest / WebResponse返回的Stream不能转换为这些类。仅通过非公共属性和字段引用连接和流类型。

我正在发布汇编的文档,它可能会帮助您找到获取该Context Handle的另一条路径。

声明,结构,枚举器列表位于QueryContextAttributesW(PASTEBIN)中。

Microsoft TechNet
身份验证结构

MSDN
使用Schannel创建安全连接

获取有关Schannel连接的信息

查询Schannel上下文的属性

QueryContextAttributes(Schannel)

代码库(部分)

.NET参考源

Internals.cs

内部结构SSPIHandle
{}

内部枚举ContextAttribute
{}


更新1:

我在您对另一个答案的评论中看到,您

TcpClient()
不接受使用该解决方案
。我还是把它留在这里,所以本·沃伊特(Ben
Voigt)在这本书中的评论
将对其他感兴趣的人有用。另外,3种可能的解决方案要优于2种。

在提供的上下文中,有关TcpClient()
SslStream用法的一些实现细节。

如果在初始化WebRequest之前需要协议信息,则可以使用TLS连接所需的相同工具在相同的上下文中建立TcpClient()连接。即,

ServicePointManager.SecurityProtocol
定义支持的协议和
ServicePointManager.ServerCertificatevalidationCallback
验证服务器证书。

TcpClient()和WebRequest都可以使用以下设置:
-启用所有协议,并让Tls握手确定将使用哪个协议。
-定义一个

RemoteCertificatevalidationCallback()
委托来验证
X509Certificates
服务器传递的
X509Chain

实际上,建立TcpClient或WebRequest连接时,Tls握手是相同的。
这种方法使您知道HttpWebRequest 与同一服务器协商哪些Tls协议。

设置一个

TcpClient()
以接收和评估
SslStream

checkCertificateRevocation
标志设置为
false
,因此该过程不会浪费时间来查找吊销列表。
证书验证回调与在中指定的相同
ServicePointManager

TlsInfo tlsInfo = null;IPHostEntry dnsHost = await Dns.GetHostEntryAsync(HostURI.Host);using (TcpClient client = new TcpClient(dnsHost.HostName, 443)){    using (SslStream sslStream = new SslStream(client.GetStream(), false,    TlsValidationCallback, null))    {        sslstream.AuthenticateAsClient(dnsHost.HostName, null,      (SslProtocols)ServicePointManager.SecurityProtocol, false);        tlsInfo = new TlsInfo(sslStream);    }}//The HttpWebRequest goes on from here.HttpWebRequest httpRequest = WebRequest.CreateHttp(HostURI);//(...)

TlsInfo
级收集建立安全连接的一些信息:
- TLS协议版本
-密码和Hash算法
- SSL握手中使用的服务器证书

public class TlsInfo{    public TlsInfo(SslStream SecureStream)    {        this.ProtocolVersion = SecureStream.SslProtocol;        this.CipherAlgorithm = SecureStream.CipherAlgorithm;        this.HashAlgorithm = SecureStream.HashAlgorithm;        this.RemoteCertificate = SecureStream.RemoteCertificate;    }    public SslProtocols ProtocolVersion { get; set; }    public CipherAlgorithmType CipherAlgorithm { get; set; }    public HashAlgorithmType HashAlgorithm { get; set; }    public X509Certificate RemoteCertificate { get; set; }}


转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/576223.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号