网络协议:HTTPS

一 什么是HTTPS协议?什么是SSL/TLS协议

HTTPS: 就是安全的HTTP协议,由HTTP协议和TLS/SSL协议组成的。

SSL: 是Secure Socket Layer的缩写,安全套接字层,位于应用层和传输层之间。是客户端和web服务器之间的安全交换信息的协议,提供两个基本安全的服务: 鉴别与加密。所有主流的浏览器都是支持SSL协议的。

TLS: 是Transport Layer Security的缩写,那么他和SSL是什么关系呢?TLS是SSL标准化之后的产物,所以很多时候把两者并称,SSL由从前的网景公司开发,有1,2,3个版本, TLS有1.0 1.1 1.2三个版本,TLS1.0和SSL3.0 几乎没有区别,只是做了一些少量的修改,然后TLS就是一个公有的标准,现在我们一般用的也是TLS,只不过很多时候叫的还是SSL

二 TLS协议分析

TLS协议位于网络层和应用层之间,用于对通信数据进行加密,共分为2层:记录层协议(record protocol)和握手协议(handshake protocol)。记录层协议为上层协议(握手协议层)提供压缩和加密等基本功能;握手协议又分为4个子协议,包括握手协议、警告协议、密码切换协议和应用数据协议。如图示:

2.1 Record Protocol(记录协议)

记录层协议:位于传输层之上,为上层协议(握手协议)提供封装,加密和压缩等基本功能。

比如对于上层的握手协议子协议添加消息头,消息头主要包括:消息类型、TLS版本、消息长度。如图示:

其中消息类型1个字节,TLS版本2个字节,消息长度2个字节,总计5个字节。

另外,记录层协议会根据上层握手协议提供的秘钥块进行加密处理;也可以进行数据压缩,但是一般不这么做。

2.2 Handshake Protocol(握手协议)

握手协议:位于记录层之上,主要就是进行身份认证,秘钥协商和秘钥交换等工作,记录层可以根据协商的秘钥套件计算秘钥块,然后对传输数据进行加密。

它主要包括握手协议、警告协议、密码切换协议、应用协议四个子协议。

2.2.1 握手子协议(handshake protocol)

握手协议有很多子消息组成,为了成功完成一次握手,需要客户端和服务器端一般需要经过2个来回才来完成沟通和协商。握手协议的消息格式如下:

握手协议由三部分组成,子消息类型(1个字节)、子消息长度(3个字节)、消息内容(可变长度)。

子消息类型主要包括:

#2 CLIENT_HELLO 客户端向服务段发起的握手消息

#3 SERVER_HELLO 服务器端响应客户端Client Hello消息

#4 CERTIFICATE 服务器端向客户端发送证书

#5 SERVER_KEY_EXCHANGE  如果使用DH作为密码交换算法,需要传递额外的密码交换参数到客户端

#6 CERTIFICATE_REQUEST 服务器端要求客户端提供证书,对客户端身份进行验证

#7 SERVER_HELLO_DONE 服务器端完成Server_Hello了消息

#8 CERTIFICATE_VERIFY 客户端证明自己拥有证书私钥

#9 CLIENT_KEY_EXCHANGE 客户端计算预主秘钥,并且发送到服务器端

#10 FINISHED 根据协商的加密算法,对之前的握手过程中消息生成摘要,然后进行加密,发送给服务器端

2.2.2 警告子协议(alert protocol)

处理握手协议的时候,可能会产生错误,错误信息就需要由警告协议处理。它主要包括警告级别和警告描述。

2.2.3 密码切换子协议(change_cipher_spec protocol)

其作用就是通知TLS记录层协议,其加密所需要的秘钥块已经准备好了,可以对Application Data进行加密处理了。可以是服务器发出,也可以是客户端发出。

2.2.4 应用数据协议(application_data protocol)

就是指的是消息和消息认证码(Message Authentication Code)

三 TLS 协议握手过程

3.1 单向认证的握手过程

#1 客户端向服务器端发送Client Hello消息。这个消息主要包含以下内容:TLS版本、用于生成主秘钥的随机数random1、压缩方式、支持的加密套件、Session ID。如果希望启用Session Ticket,则还会携带一个空的Session Ticket扩展

#2 服务器端向客户端回应Server Hello消息。这个消息主要包括服务器使用的TLS版本、用于生成主秘钥的随机数random2、根据客户端提供的加密套件中选择一个自己支持的加密算法(包括非对称秘钥算法、对称加密算法、哈希算法)用于后续加密和生成摘要、Session ID(如果没有创建会话存在内存,并产生一个Session ID),如果希望启用Session Ticket,则还会携带一个空的Session Ticket扩展

#3 服务器向客户端发送Certificate消息,即发送自己的证书(里面有公钥),用于客户端进行服务器身份认证

#4 如果使用的是RSA作为秘钥交换算法(即公钥加密,私钥解密),则无需此步骤,这个步骤针对的是DH类的秘钥交换算法。服务器向客户端发送Server Key Exchange消息,服务器生成一个随机数y和素数p,以及生成数g,计算出b = g ^ y mod p, 然后将g,p,b值作为消息额外参数发送给客户端

#5 服务器向客户端发送Server Hello Done,表示服务器端已经发送完了Server Hello消息,完成了协商过程

#6 客户端收到服务器端的证书后,先从CA校验证书的合法性,如果证书不是可信的CA机构颁发或者证书的域名与实际域名不相符合或者证书已经过期,就会向访问者显示一个警告,是否继续通信

#7 客户端发送Client Key Exchange消息。如果使用的RSA作为秘钥交换算法,则从证书中获取服务器的公钥,然后再生成一个随机数random3,再使用公钥对随机值random3进行非对称加密,生成预主秘钥(pre-master key); 如果使用的是DH类型秘钥交换算法,则根据服务器端发送过来的g,p参数计算a,然后将计算得到的a发送给服务器端

#8 客户端切换到加密方式,并向服务器发送Change Cipher Spec 消息,通知服务器端可以开始使用加密方式发送报文。客户端使用上面三个随机数random1+random2+random3,即客户端生成的随机数,服务器发送来的随机数已经生成的预主秘钥,计算生成主秘钥(master key)

#9 客户端向服务器端发送Finished消息,将前面的握手消息生成摘要再用协商好的秘钥加密,这是客户端发出的第一条加密消息。

服务端接收后会用秘钥解密,能解出来说明前面协商出来的秘钥是一致的。

#10 (可选)如果启用了Session Ticket,服务器端会对会话生成一个票据,然后向客户端发送New Session Ticket消息,通过该消息发送生成的票据到客户端

#11 服务器端切换到密方式,并向客户端发送Change Cipher Spec 消息,通知客户端可以开始使用加密方式发送报文。

#12 服务器端向客户端发送Finished消息。服务端也会将握手过程的消息生成摘要再用秘钥加密,这是服务端发出的第一条加密消息。

客户端接收后会用秘钥解密,能解出来说明协商的秘钥是一致的。

#13 (可选)客户端收到服务器端的票据,则将其存储起来,以便于下一次使用

3.2 双向认证的握手过程

#1 客户端向服务器端发送Client Hello消息。这个消息主要包含以下内容:TLS版本、用于生成主秘钥的随机数random1、压缩方式、支持的加密套件、Session ID。如果希望启用Session Ticket,则还会携带一个空的Session Ticket扩展

#2 服务器端向客户端回应Server Hello消息。这个消息主要包括服务器使用的TLS版本、用于生成主秘钥的随机数random2、根据客户端提供的加密套件中选择一个自己支持的加密算法用于后续加密和生成摘要、Session ID(如果没有创建会话存在内存,并产生一个Session ID),如果希望启用Session Ticket,则还会携带一个空的Session Ticket扩展

#3 服务器向客户端发送Certificate消息,即发送自己的证书(里面有公钥),用于客户端进行服务器身份认证

#4 如果使用的是RSA作为秘钥交换算法(即公钥加密,私钥解密),则无需此步骤,这个步骤针对的是DH类的秘钥交换算法。服务器向客户端发送Server Key Exchange消息,服务器生成一个随机数y和素数p,以及生成数g,计算出b = g ^ y mod p, 然后将g,p,b值作为消息额外参数发送给客户端

#5 这是一个可选步骤,如果TLS要求双向认证,即除了客户端要求对服务器进行身份认证之外,服务器也要求对客户端进行身份认证,则服务器需要向客户端发送Certificate Request消息

#6 服务器向客户端发送Server Hello Done,表示服务器端已经发送完了Server Hello消息,完成了协商过程。

#7 客户端收到服务器端的发送证书的消息,则会向服务器发送Client Certificate消息,将客户端的证书发送给服务器;如果没有证书,则内容为0

#8 客户端收到服务器端的证书后,先从CA校验证书的合法性,如果证书不是可信的CA机构颁发或者证书的域名与实际域名不相符合或者证书已经过期,就会向访问者显示一个警告,是否继续通信

#9 客户端发送Client Key Exchange消息。如果使用的RSA作为秘钥交换算法,则从证书中获取服务器的公钥,然后再生成一个随机数random3,再使用公钥对随机值random3进行非对称加密,

生成预主秘钥(pre-master key); 如果使用的是DH类型秘钥交换算法,则根据服务器端发送过来的g,p参数计算a,然后将计算得到的a发送给服务器端

#10 客户端向服务器端发送Certificate Verify消息,证明自己发送给服务器端的证书是拥有私钥的,所以需要使用私钥对一段数据发送给服务器验证,服务器会通过公钥进行解密

说白了就是生成摘要信息,然后进行数字签名。

#11 客户端切换到加密方式,并向服务器发送Change Cipher Spec 消息,通知服务器端可以开始使用加密方式发送报文。客户端使用上面三个随机数random1+random2+random3,即客户端生成的随机数,服务器发送来的随机数已经生成的预主秘钥,计算生成主秘钥(master key)

#12 客户端向服务器端发送Finished消息,将前面的握手消息生成摘要再用协商好的秘钥加密,这是客户端发出的第一条加密消息。

服务端接收后会用秘钥解密,能解出来说明前面协商出来的秘钥是一致的。

#13 (可选)如果启用了Session Ticket,服务器端会对会话生成一个票据,然后向客户端发送New Session Ticket消息,通过该消息发送生成的票据到客户端

#14 服务器端切换到密方式,并向客户端发送Change Cipher Spec 消息,通知客户端可以开始使用加密方式发送报文。

#15 服务器端向客户端发送Finished消息。服务端也会将握手过程的消息生成摘要再用秘钥加密,这是服务端发出的第一条加密消息。

客户端接收后会用秘钥解密,能解出来说明协商的秘钥是一致的。

#16 (可选)如果启用了Session Ticket,服务器端会对会话生成一个票据,然后向客户端发送New Session Ticket消息,通过该消息发送生成的票据到客户端

3.3 短握手过程(会话恢复)

3.3.1 基于Session ID的会话恢复流程

#1 客户端再次请求相同的网站,客户端向服务器端发送Client Hello消息。这个消息主要包含以下内容:TLS版本、用于生成主秘钥的随机数random1、压缩方式、支持的加密套件、Session ID

#2 服务器接受到该请求后,检查Session Cache中是否存在能够匹配Session ID的会话。如果没有或者不可恢复,则进行完整的握手协议,同时生成一个新的Session ID,返回给客户端的消息主要包括服务器使用的TLS版本、用于生成主秘钥的随机数random2、根据客户端提供的加密套件中选择一个自己支持的

#3 如果服务器端可以恢复会话,则直接发送Change Cipher Spec和Finished消息。即切换到密码模式,通知客户端可以开始使用加密方式发送报文。并且使用之前握手过程中的消息形成摘要并发送

#4 客户端也直接向服务器端发送Change Cipher Spec和Finished消息,表示会话恢复成功。

3.3.2 基于Session Ticket的会话恢复

#1 客户端存储的有票据,如果希望恢复的话,则在发送Client Hello消息的时候,需要包含一个非空的Session Ticket 扩展

#2 服务器端收到客户端的回复连接的请求,获取非空的Session Ticket,并且对Session Ticket进行解密校验。如果可以恢复在Server Hello消息中包含一个非空的Session Ticket扩展

#3不需要想客户端发送Certificate消息和Server Key Exchange消息。但是服务器需要发送一个New Session Ticket 子消息来更新票据,因为Ticket票据也是有期限的

#4如果服务器端可以恢复会话,则直接发送Change Cipher Spec和Finished消息。即切换到密码模式,通知客户端可以开始使用加密方式发送报文。并且使用之前握手过程中的消息形成摘要并发送

#5客户端也直接向服务器端发送Change Cipher Spec和Finished消息,表示会话恢复成功

四 会话恢复

4.1什么是会话,什么是会话恢复?

我们知道客户端和服务器端握手成功,建立一个完整的TLS连接,只要客户端和服务器端不主动关闭连接,HTTPS的应用层数据就一直受TLS连接保护,在整个连接过程就可以看作是一次会话。一旦客户端和服务器端关闭连接,那么客户端下次访问HTTPS网站的时候就要进行一次新的连接,会话关闭。

握手协议完成后,服务器端会在内存内保存会话信息,包括如下部分:

#1 会话标识符(session identifier): 每一个会话都有唯一的标识

#2 证书(certificate): 对端的证书

#3 压缩算法(compression method):一般不启用

#4 密码套件(cipher spec):客户端和服务端协商出来的密码套件

#5 主秘钥(master secret):每一个会话都会保存一个主秘钥

#6 会话可恢复标识(is resumable): 标识某个会话是否可以恢复

通过服务器保存的会话信息,最终可以生成TLS记录层协议所需要的加密参数

每次断开连接都需要重新连接,会带来网络性能问题,那么有没有一种机制可以恢复先前用过的TLS连接呢,或者说能否恢复先前的TLS会话呢?状态TLS协议中,我么可以使用会话恢复机制。

会话恢复有两种形式:一是基于Session ID的会话恢复;另外一种是基于Session Ticket的会话恢复。

4.2 基于Session ID的会话恢复

4.2.1完整握手中的会话处理

#1 客户端向服务器发送Client Hello消息,其中传递的Session ID值为空

#2 服务器端检查客户端的Session ID值,如果该值为空,则进行完整的握手,生成一个新的Session ID,该值通过服务器端的Server Hello消息传递给客户端

#3 客户端收到这个服务器端发送的Session ID,保存在客户端的内存中

#4 会话结束,服务器将会话保存在Session Cache中,key是Session ID, value就是会话信息

4.2.2基于Session ID的会话恢复流程

#1 客户端再次请求相同的网站,如果该网站对应的Session ID不为空,则Client Hello附带这个值

#2 服务器受到该请求后,检查Session Cache中是否能够匹配键值为Session ID的会话,如果没有或者不可恢复会话,则进行完整的握手协议,同时生成一个新的Session ID返回给客户端

#3 服务器如果能够恢复本次连接,则直接发送Change Chpher Spec和Finished消息,不进行密码协商,因为主秘钥在会话中

#4 最终客户端也发送Change Cipher Spec和Finished子消息,表示会话恢复成功

4.2.3优缺点:

优点:

#1 减少了网络延迟,完整的握手协议需要2个RTT,而简短握手只需要一次

#2 减少了客户端和服务器端的负载,握手协议耗时的操作在于密码的运算,尤其是密码的协商需要消耗大量的CPU运算,而简单的握手并不需要进行秘钥协商

缺点:

#1 服务器存储会话信息,可能会占用大量内存,所以需考虑会话的生命有效期

#2 TLS协议只是规定Session Cache的存储方式,秘钥考虑如何实现

#3 没有考虑多个主机共享Session Cache的情况

4.3 基于Session Ticket的会话恢复

解决了Session ID会话恢复存在的问题,是一种更好的会话恢复方式.

4.3.1 应用场景

如果遇到以下场景使用Session Ticket是比较合适的:

#1 Session ID存储在服务器,对于大型HTTPS网站来说,占用的内存量非常大,是一个很大的开销

#2 HTTPS网站希望会话生命周期更长一点

#3 HTTPS网站希望会话可以跨主机访问,Session ID会话恢复显示做不到

#4 有些服务器没有太多的内存用于存储会话信息,比如嵌入式服务器

4.3.2基于Session Ticket进行完整的握手

#1 对于第一次新的连接,如果期望服务器支持Session Ticket会话恢复,则在客户端Client Hello消息中包括一个空的Session Ticket 扩展

#2 如果服务器支持Session Ticket会话恢复,服务器的Server Hello消息中也包括一个Session Ticket 扩展

#3 服务器对会话信息进行加密保护,生成一个票据(ticket),然后New Session Ticket子消息中发送该票据,New Session Ticket是握手协议中一个独立子消息

#4 客户端收到New Session Ticket子消息后,将票据存储起来,以便下一次使用

4.3.3基于Session Ticket进行短握手

#1 客户端存储的有Session Ticket,如果希望会话恢复,则客户端在发送子消息Client Hello的时候包括一个非空的Session Ticket扩展

#2 服务器端在收到非空的Session Ticket之后,对Session Ticket进行解密校验,如果可以恢复,在Server Hello消息中发送一个空Session Ticket 扩展

#3 由于是简短握手,所以Certificate和Server Key Exchange等子消息不需要发送,接下发送一个New Session Ticket子消息更新ticket, ticket也是有期限的

#4 客户端和服务器端接着校验Finished子消息,表示简单握手完成,顺利完成会话恢复

4.3.4服务器不支持Session Ticket的交互流程

客户端发送了非空的Session Ticket 扩展后,服务器可以选择不支持会话恢复,也不生成新的票据,所以可以在服务器Server Hello子消息中不响应Session Ticket的扩展,也不发送NewSessionTicket子消息

4.3.5服务器校验票据失败的流程

客户端如果发送了非空的Session Ticket之后,服务器校验失败后,可以重新生成新的票据, 该流程和基于Session Ticket的完整握手流程差不多,只是不发送New Session Ticket消息

五 TLS 秘钥交换算法

现在常见的秘钥交换算法有两类:RSA 和 DH系列

RSA我们知道就是如果是加密,就是公钥加密,私钥解密;如果是签名,则是私钥加密,公钥解密。但是有一个问题,如果服务器私钥丢失了或者被别人盗走了,怎么办? 那么也是不安全的。

DH算法,是Diffie-Hellman算法的缩写,它是利用指数和取模的方式进行秘钥交换。我们只以DHE和ECDHE为例子。

Ephemeral Diffie-Hellman(临时 迪夫-赫尔曼)秘钥交换是一种构造完备的算法,支持前向保密,缺点执行缓慢。

#1 服务器端,生成一个随机值Y,以及生成数g和素数p,用Y作为指数,计算b = g ^ Y mod p ,将结果发送b和生成数g和素数p作为额外参数发送到客户端,Y自己保存

#2 客户端A生成1个随机值X,使用X作为指数,根据服务器端的额外参数:生成数g和素数p,计算 a = g^ X mod p。客户端把a发送到服务器端,然后X自己保存;

#3 客户端收到b后计算 key1 = b ^ X  mod p

#4 服务器收到a后计算 key2 =  a ^ Y mod p

根据数学定理: key1 = ((g^Y mod p)^X) mod p = g^XY mod p ; key2 =  ((g^X mod p)^Y) mod p = g^YX mod p;因为 g^XY = g^YX,所以key1 = key2,故秘钥交换成功。传输的只是p,g,g^X mod p,g^Y mod p, 假设截获四个参数,是反向推不出来X和Y的。原理就是离散对数。我们发现服务器的私钥是没有参与进来的。

ECDHE (Elliptical Curve Diffie-Hellman Empheral) 临时的椭圆曲线迪夫-赫尔曼算法。它比DHE速度更快,安全性更高,秘钥交换建立在椭圆曲线算法加密的基础上的。流程如下:

#1 客户端A 随机生成 a, 计算 F(x,y) = a * Q(x,y), 然后将F(x,y)发送至服务器B。

#2 客户端B 随机生成 b, 计算 F(x,y) = b * Q(x,y), 然后将F(x,y)发送至客户端A。

#3 客户端计算key1(x,y) = a * (b * Q(x,y))

#4 服务器计算key2(x,y) = b * (a * Q(x,y))

所以key1=key2,取key的x向量作为秘钥(预主秘钥)

所以ECDHE和DHE一样,私钥不参与密码交换,即使私钥外泄,加密报文也无法破解

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

莫言静好、

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值