HTTPS协议的SSL握手过程
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HTTPS协议的SSL握手过程相关的知识,希望对你有一定的参考价值。
HTTPS常被定义为为 HTTP over SSL ,超文本传输安全协议。
以往HTTP通讯直接使用的明文传输,容易被人抓包,破解数据包,而 HTTPS 经由 HTTP 进行通信,但利用 SSL/TLS 来加密数据包。
HTTP的URL由“http://”起始且默认使用端口80,
HTTPS的URL由“https://”起始且默认使用端口443。
注意:
SSL是一个介于HTTP协议与TCP之间的一个可选层,为数据通讯提供安全支持。SSL协议可分为两层:
如果用右边的TCP/IP协议来划分,SSL是属于应用层与传输层之间的协议,如果还是用OSI七层协议划分,SSL是属于表示层与会话层的。
以下是SSL协议握手的一个主要过程,主要分为4个阶段。
此时,client和server都持有3个随机数,客户端和服务端用商定的算法利用3个随机数生成一个 对话密钥(session key) ,随后的通信就用这个密钥进行加密解密。之所以用3个随机数,因为证书是静态的,增加随机数可以使得密钥更加有随机性。SSL协议传输过程中,使用的是由相同的3个随机数生成的 对话密钥(session key) ,而生成的规则是client与server商议好的算法,所以这个 对话密钥(session key) 是相同的,这个加密方法称为 对称加密 。
HTTPS通讯也不一定是绝对安全的,有可能会被人劫持,如路由,代理,防火墙,通常是中间人攻击。所谓中间人,就是攻击端欺骗服务端,伪造成客户端。反过来欺骗客户端,伪造成服务端。
简单过程如下
中间人攻击一般发生在SSL握手协议中,协商密钥的时候(非对称加密阶段),中间人攻击的主要目的是要欺骗客户端,与客户端协商生成最后的对话密钥(3个随机数生成),这样客户端的数据经过这个对话密钥加密后,就可以被中间人轻易解密出来。所以中间人攻击必须得使用自己证书(包含公钥)进行握手,这样才能有自己的私钥解密出客户端发过来的随机数。
如果客户端与服务端会话初始化完成,开始进行数据通讯(对称加密阶段),想要完成中间人攻击是非常困难的。
防御中间人攻击的手段是做好证书的校验,一般来说,客户端收到了服务端下发的证书,对证书的颁发机构、有效期等进行严格校验(证书是验证服务端身份合法与否的唯一方式):
Charles其实是扮演一个中间人的角色,就是上述的中间人攻击。客户端选择信任并安装Charles的CA证书,否则客户端就会“报警”并中止连接。这样看来,HTTPS还是很安全的。
大概示例图如下
如果需要App进行抓包调试,一般需要设置Mode为AFSSLPinningModeNone。
加密和解密可以使用不同的规则,只要这两种规则之间存在某种对应关系即可,这样就避免了直接传递密钥。这种加密模式被称为"非对称加密算法"。RSA算法一直是最广为使用的"非对称加密算法",2048位的密钥极其安全。SSL握手过程,客户端使用服务端的公钥解密随机数,服务端使用私钥解密出随机数的过程就是非对称加密。
http://www.nsfocus.net/index.php?act=magazine&do=view&mid=841
https://www.jianshu.com/p/9c52693a09dc
https://www.jianshu.com/p/405f9d76f8c4
第二步:服务端收到请求以后也会给客户端发一个server hello请求,请求中会告诉客户端它选择的协议版本、加密套件、压缩算法以及一个随机数。
第三步:服务端会给客户端发一个server certificate请求,里面包含服务端的数字证书,用于客户端进行校验。
第四步:服务端会给客户端发一个server hello done告诉客户端信息已发送完毕。
第五步:客户端收到证书以后进行校验获取到服务端的公钥。
第六步:客户端会将自己的数字证书发给服务端用于校验。
第七步:客户端计算出一个随机数pre-master,然后用公钥进行加密发送给服务器端。
第八步:服务端和客户端都根据自己的随机数+对端的随机数+pre-master算出对称密钥,然后再根据对称密钥进行通信。 参考技术B 如果可以的话,让我们消除一些困惑
关于SSL/TLS握手如何工作的一些混淆是由于握手只是实际的、安全的会话本身的前奏。让我们尝试解决一些共同点:
非对称与对称加密
握手本身使用非对称加密——使用两个单独的密钥,一个公钥,一个私钥。由于非对称加密系统的开销要高得多,因此它们不能用于提供全时的、真实世界的安全性。因此,仅在握手期间使用公钥进行加密,使用私钥进行解密,这允许双方秘密地设置和交换新创建的“共享密钥”。会话本身使用这个单一的共享密钥来执行对称加密,这就是使安全连接在实际实践中可行的原因(开销大大降低)。因此,“SSL/TLS加密是非对称的还是对称的?”的完整而正确的答案是“第一个,然后另一个”。
什么是“密码套件”?
握手本身有多个阶段,每个阶段根据不同的规则进行管理。细节可以在这里找到,但它的核心是,而不是一系列单独的来回协商(关于使用什么密钥,如何加密握手本身,如何验证握手等等)各方可以同意使用“密码套件”——预先存在的选择或商定组件套件。(请记住,非对称加密在时间和资源方面都非常昂贵——使用密码套件作为快捷方式可以加快握手本身的速度。)TLS规范允许使用相当多的密码套件,并且客户端和服务器几乎总是可以访问他们都可以雇用的人。
基本与相互认证的握手
另一个令人困惑的地方是,我们上面描述的基本模型让客户端验证服务器,而绝大多数受TLS保护的会话只需要这样做。但是,一些密码套件会要求客户端同时发送证书和公钥以供双方相互验证。这种双向身份验证当然会增加握手的开销——但是,在某些情况下(例如,两家银行正在协商资金转账的安全连接)密码套件会坚持这样做,并且额外的安全性被认为是值得的它。
不同的会话会有不同的安全参数
每次新的握手都会创建一个新的会话,并且根据所选的密码套件,一个会话中使用的设置可能与另一个会话有很大不同。这就是该死的握手图存在如此多不同迭代的原因之一,也是我们在这里给出相当广泛的概述的原因之一。还要知道会话可以设置可能与您期望的不完全相同的参数。根据密码套件的不同,可能会添加一些步骤(例如双向身份验证的要求)或不添加。事实上,实际上有密码套件协商会话以不使用任何加密。(是的,我们知道,决定以明文方式发送数据的端口443上的HTTPS连接对我们来说也毫无意义。
SSL/TLS 握手过程详解***
我们知道,HTTP 协议都是明文传输内容,在早期只展示静态内容时没有问题。伴随着互联网的快速发展,人们对于网络传输安全性的要求也越来越高,HTTPS 协议因此出现。如上图所示,在 HTTPS 加密中真正起作用的其实是 SSL/TLS 协议。SSL/TLS 协议作用在 HTTP 协议之下,对于上层应用来说,原来的发送接收数据流程不变,这就很好地兼容了老的 HTTP 协议,这也是软件开发中分层实现的体现。
SSL/TLS 握手是为了安全地协商出一份对称加密的秘钥,这个过程很有意思,下面我们一起来了解一下。
以下内容需要你对加解密、数字签名和数字证书的概念有一定了解,这里有一篇文章可以帮你快速了解这几个概念。
SSL/TLS 握手过程
上图大致描述了 SSL/TLS 的握手过程,但缺少了一些信息不利于理解,我会在后面的讲解里再列出来。
Client Hello
握手第一步是客户端向服务端发送 Client Hello 消息,这个消息里包含了一个客户端生成的随机数 Random1、客户端支持的加密套件(Support Ciphers)和 SSL Version 等信息。通过 Wireshark 抓包,我们可以看到如下信息:
Wireshark 抓包的用法可以参考这篇文章
Server Hello
第二步是服务端向客户端发送 Server Hello 消息,这个消息会从 Client Hello 传过来的 Support Ciphers 里确定一份加密套件,这个套件决定了后续加密和生成摘要时具体使用哪些算法,另外还会生成一份随机数 Random2。注意,至此客户端和服务端都拥有了两个随机数(Random1+ Random2),这两个随机数会在后续生成对称秘钥时用到。
Certificate
这一步是服务端将自己的证书下发给客户端,让客户端验证自己的身份,客户端验证通过后取出证书中的公钥。
Server Key Exchange
如果是DH算法,这里发送服务器使用的DH参数。RSA算法不需要这一步。
Certificate Request
Certificate Request 是服务端要求客户端上报证书,这一步是可选的,对于安全性要求高的场景会用到。
Server Hello Done
Server Hello Done 通知客户端 Server Hello 过程结束。
Certificate Verify
客户端收到服务端传来的证书后,先从 CA 验证该证书的合法性,验证通过后取出证书中的服务端公钥,再生成一个随机数 Random3,再用服务端公钥非对称加密 Random3 生成 PreMaster Key。
Client Key Exchange
上面客户端根据服务器传来的公钥生成了 PreMaster Key,Client Key Exchange 就是将这个 key 传给服务端,服务端再用自己的私钥解出这个 PreMaster Key 得到客户端生成的 Random3。至此,客户端和服务端都拥有 Random1 + Random2 + Random3,两边再根据同样的算法就可以生成一份秘钥,握手结束后的应用层数据都是使用这个秘钥进行对称加密。为什么要使用三个随机数呢?这是因为 SSL/TLS 握手过程的数据都是明文传输的,并且多个随机数种子来生成秘钥不容易被暴力破解出来。客户端将 PreMaster Key 传给服务端的过程如下图所示:
Change Cipher Spec(Client)
这一步是客户端通知服务端后面再发送的消息都会使用前面协商出来的秘钥加密了,是一条事件消息。
Encrypted Handshake Message(Client)
这一步对应的是 Client Finish 消息,客户端将前面的握手消息生成摘要再用协商好的秘钥加密,这是客户端发出的第一条加密消息。服务端接收后会用秘钥解密,能解出来说明前面协商出来的秘钥是一致的。
Change Cipher Spec(Server)
这一步是服务端通知客户端后面再发送的消息都会使用加密,也是一条事件消息。
Encrypted Handshake Message(Server)
这一步对应的是 Server Finish 消息,服务端也会将握手过程的消息生成摘要再用秘钥加密,这是服务端发出的第一条加密消息。客户端接收后会用秘钥解密,能解出来说明协商的秘钥是一致的。
Application Data
到这里,双方已安全地协商出了同一份秘钥,所有的应用层数据都会用这个秘钥加密后再通过 TCP 进行可靠传输。
双向验证
前面提到 Certificate Request 是可选的,下面这张图展示了双向验证的过程:
握手过程优化
如果每次重连都要重新握手还是比较耗时的,所以可以对握手过程进行优化。从下图里我们看到 Client Hello 消息里还附带了上一次的 Session ID,服务端接收到这个 Session ID 后如果能复用就不再进行后续的握手过程。
除了上述的 Session 复用,SSL/TLS 握手还有一些优化技术,例如 False Start、Session Ticket 等,这方面的介绍具体可以参考这篇文章。
总结
前面我们一起详细地了解了整个 SSL/TLS 的握手过程,这部分知识在平时的开发过程中很少用到,但能让我们更清楚地了解 HTTPS 的工作原理,而不仅仅是只知道 HTTPS 会加密数据十分安全。同时这个过程也是各种加密技术的一个经典运用,也能帮助我们加深加密相关技术的理解。最后,建议大家也用 Wireshark 实际抓包体验一下这个过程来加深印象,enjoy~
参考资料
http://www.ruanyifeng.com/blog/2014/02/ssl_tls.html
https://segmentfault.com/a/1190000002554673
以上是关于HTTPS协议的SSL握手过程的主要内容,如果未能解决你的问题,请参考以下文章