一文弄懂RSA算法中的TLS握手流程
部分内容来源:小林coding
前置知识
TLS和HTTPS有什么关系?
TLS 协议是 HTTPS 实现安全通信的基础,有了 TLS 协议,才能在安全的通信环境里发送 HTTP 报文,实现 HTTPS 协议。
简单来说,TLS 是保障 HTTPS 通信安全的核心技术
为什么需要TLS协议?
明文传输的风险
HTTP 由于是明文传输,所谓的明文,就是说客户端与服务端通信的信息都是肉眼可见的,随意使用一个抓包工具都可以截获通信的内容。
所以安全上存在以下三个风险:
- 窃听风险,比如通信链路上可以获取通信内容,用户号容易没。
- 篡改风险,比如强制植入垃圾广告,视觉污染,用户眼容易瞎。
- 冒充风险,比如冒充淘宝网站,用户钱容易没。
HTTPS 在 HTTP 与 TCP 层之间加入了 TLS 协议,来解决上述的风险
TLS 协议是如何解决 HTTP 的风险的呢
- 信息加密:HTTP 交互信息是被加密的,第三方就无法被窃取;
- 校验机制:校验信息传输过程中是否有被第三方篡改过,如果被篡改过,则会有警告提示;
- 身份证书:证明淘宝是真的淘宝网;
TLS握手过程
有了 TLS 协议,能保证 HTTP 通信是安全的了,那么在进行 HTTP 通信前,需要先进行 TLS 握手。TLS 的握手过程,如下图:
上图简要概述了TLS的握手过程,其中每一个「框」都是一个记录(record),记录是TLS收发数据的基本单位,类似于TCP里的segment。
多个记录可以组合成一个TCP包发送,所以通常经过「四个消息」(双方来回发送四次信息)就可以完成TLS握手,也就是需要2个RTT的时延(等两个《一来一回》的时间),然后就可以在安全的通信环境里发送HTTP报文,实现HTTPS协议。
人话:一般来说,双方来回发送 4 次消息,也就是等 2 个 “一来一回” 的时间,就能完成 TLS 握手,确认好身份和暗号,之后就能在安全的环境里互相发消息了,这就是 HTTPS 协议
所以可以发现,HTTPS是应用层协议,需要先完成TCP连接建立,然后走TLS握手过程后,才能建立通信安全的连接。
事实上,不同的密钥交换算法,TLS的握手过程可能会有一些区别。
这里先简单介绍下密钥交换算法,因为考虑到性能的问题,所以双方在加密应用信息时使用的是对称加密密钥,而对称加密密钥是不能被泄漏的,为了保证对称加密密钥的安全性,所以使用非对称加密的方式来保护对称加密密钥的协商,这个工作就是密钥交换算法负责的
HTTPS是什么协议?
应用层协议
先建立连接还是先TLS握手?
HTTPS是应用层协议,需要先完成TCP连接建立,然后走TLS握手过程后,才能建立通信安全的连接
RSA算法握手流程
简单说一下RSA算法的流程
传统的 TLS 握手基本都是使用 RSA 算法来实现密钥交换的,在将 TLS 证书部署服务端时,证书文件其实就是服务端的公钥,会在 TLS 握手阶段传递给客户端,而服务端的私钥则一直留在服务端,一定要确保私钥不能被窃取。
在 RSA 密钥协商算法中,客户端会生成随机密钥,并使用服务端的公钥加密后再传给服务端
根据非对称加密算法,公钥加密的消息仅能通过私钥解密(我们用服务端的公钥加密所以服务端用自己的私钥解密),这样服务端解密后,双方就得到了相同的密钥,再用它加密应用消息。
TLS第一次握手
客户端首先会发一个「Client Hello」消息,字面意思我们也能理解到,这是跟服务器「打招呼」
客户端和服务端打招呼
消息里面有三个重要的东西
1.客户端使用的TLS版本号
2.支持的密码套件列表
3.生成的随机数(Client Random),这个随机数会被服务端保留,它是生成对称加密密钥的材料之一
TLS第二次握手
当服务端收到客户端的「Client Hello」消息后会做三件事情
1.确认TLS版本号是否支持
2.从密码套件列表中选择一个密码套件
3.生成随机数(Server Random)。
接着,返回「Server Hello」消息,消息里面有服务器确认的TLS版本号,也给出了随机数(Server Random),然后从客户端的密码套件列表选择了一个合适的密码套件。
可以看到,服务端选择的密码套件是“Cipher Suite: TLS_RSA_WITH_AES_128_GCM_SHA256”。
这个密码套件看起来真让人头晕,好一大串,但是其实它是有固定格式和规范的。
基本的形式是「密钥交换算法 + 签名算法 + 对称加密算法 + 摘要算法」
一般WITH单词前面有两个单词,第一个单词是约定密钥交换的算法,第二个单词是约定证书的验证算法。
比如刚才的密码套件的意思就是:
由于WITH单词只有一个RSA,则说明握手时密钥交换算法和签名算法都是使用RSA;
握手后的通信使用AES对称算法,密钥长度128位,分组模式是GCM;
摘要算法SHA256用于消息认证和产生随机数;
就前面这两个客户端和服务端相互「打招呼」的过程,客户端和服务端就已确认了TLS版本和使用的密码套件,而且你可能发现客户端和服务端都会各自生成一个随机数,并且还会把随机数传递给对方。
那这个随机数有啥用呢?
其实这两个随机数是后续作为生成「会话密钥」的条件,所谓的会话密钥就是数据传输时,所使用的对称加密密钥。
然后,服务端为了证明自己的身份,会发送「Server Certificate」给客户端,这个消息里含有数字证书。
随后,服务端发了「Server Hello Done」消息,目的是告诉客户端,我已经把该给你的东西都给你了,本次打招呼完毕。
客户端验证证书
数字证书和 CA 机构
在说校验数字证书是否可信的过程前,我们先来看看数字证书是什么,一个数字证书通常包含了:
- 公钥;
- 持有者信息;
- 证书认证机构(CA)的信息;
- CA 对这份文件的数字签名及使用的算法;
- 证书有效期;
- 还有一些其他额外信息;
数字证书的目的是什么?
那数字证书的目的是用来认证公钥持有者的身份,以防止第三方进行冒充。说简单些,证书就是用来告诉客户端,该服务端是否是合法的,因为只有证书合法才代表服务端身份是可信的。
我们用证书来认证公钥持有者的身份(服务端的身份),那证书又是怎么来的?又该怎么认证证书呢?
证书是怎么来的?
为了让服务端的公钥被大家信任,服务端的证书都是由 CA(Certificate Authority,证书认证机构)签名的,CA 就是网络世界里的公安局、公证中心,具有极高的可信度,所以由它来给各个公钥签名,信任的一方签发的证书,那必然证书也是被信任的。
之所以要签名,是因为签名的作用可以避免中间人在获取证书时对证书内容的篡改
数字证书签发和验证流程
CA 签发证书的过程
如上图左边部分:
1.首先 CA 会把持有者的公钥、用途、颁发者、有效时间等信息打成一个包,然后对这些信息进行 Hash 计算,得到一个 Hash 值;
2.然后 CA 会使用自己的私钥将该 Hash 值加密,生成 Certificate Signature,也就是 CA 对证书 做了签名;
3.最后将 Certificate Signature 添加在文件证书上,形成数字证书;
客户端校验服务端的数字证书的过程
如上图右边部分:
1.首先客户端会使用同样的 Hash 算法获取该证书的 Hash 值 H1;
2.通常浏览器和操作系统中集成了 CA 的公钥信息,浏览器收到证书后可以使用 CA 的公钥解密证书 Certificate Signature的内容,得到一个 Hash 值 H2 ;
3.最后比较 H1 和 H2,如果值相同,则为可信赖的证书,否则则认为证书不可信
TLS第三次握手
客户端验证完证书后,认为可信则继续往下走。
接着,客户端就会生成一个新的随机数 (pre-master),用服务器的 RSA 公钥加密该随机数,通过「Client Key Exchange」消息传给服务端
服务端收到后,用 RSA 私钥解密,得到客户端发来的随机数 (pre-master)。
至此,客户端和服务端双方都共享了三个随机数
分别是
Client Random
Server Random
pre-master
于是,双方根据已经得到的三个随机数,生成会话密钥(Master Secret)
它是对称密钥(私钥加密私钥解密),用于对后续的 HTTP 请求 / 响应的数据加解密。
生成完「会话密钥」后,然后客户端发一个「Change Cipher Spec」,告诉服务端开始使用加密方式发送消息
然后,客户端再发一个「Encrypted Handshake Message (Finished)」消息,
把之前所有发送的数据做个摘要,再用会话密钥(master secret)加密一下,让服务器做个验证,验证加密通信「是否可用」和「之前握手信息是否有被中途篡改过]
可以发现,「Change Cipher Spec」之前传输的 TLS 握手数据都是明文,之后都是对称密钥加密的密文
TLS第四次握手
服务器也是同样的操作,发「Change Cipher Spec」和「Encrypted Handshake Message」消息,如果双方都验证加密和解密没问题,那么握手正式完成。
最后,就用「会话密钥」加解密 HTTP 请求和响应了
RSA算法的缺陷-不能向前保密
什么是向前保密
定义:也叫前向安全性,是密码学中的一个概念 它指的是在加密系统中,即使攻击者获取了当前的长期密钥(如服务器的私钥等),也无法解密在此之前已经传输并加密过的通信数据 也就是说,过去的通信记录因为使用了临时的、一次性的密钥进行加密,所以即使长期密钥泄露,这些过去的通信内容仍然是安全的、无法被破解的
作用:向前保密能够为通信双方提供更强的安全保障,尤其是在长期密钥可能存在被泄露风险的情况下,确保历史通信数据的保密性和完整性,保护用户过去通信的隐私和数据安全
使用 RSA 密钥协商算法的最大问题是不支持前向保密
主要是因为使用了长期密钥
因为客户端传递随机数(用于生成对称加密密钥的条件之一)给服务端时使用的是公钥加密的,服务端收到后,会用私钥解密得到随机数
所以一旦服务端的私钥泄漏了,我们就可以解析出我们的随机数
甚至可以破解3个随机数结合生成的密钥
因为它是对称密钥(私钥加密私钥解密),这样过去被第三方截获的所有 TLS 通讯密文都会被破解
摘要是怎么保证信息没有被篡改的?
我们对当前信息进行Hash运算得到摘要H2,然后摘要通过私钥加密传过去
对面的也对信息进行Hash运算得到摘要H1,然后通过公钥解密摘要H2
如果H1==H2说明信息没被篡改
简单说一下RSA的握手流程
TLS第一次握手-【client Hello】
客户端:
【client Hello】向服务端打招呼
支持的TLS版本号
支持的密码套件
生成随机数
TLS第二次握手-【server Hello】
服务端:
判断TLS版本号是否支持
选一个密码套件
生成随机数
然后,服务端为了证明自己的身份,会发送「Server Certificate」给客户端,这个消息里含有数字证书。
客户端验证证书(验证服务端身份)
CA对证书进行Hash运算,然后用私钥将该 Hash 值加密,生成 Certificate Signature,也就是 CA 对证书做了签名,最后将 Certificate Signature 添加在文件证书上,形成数字证书
客户端对证书用同样的算法进行Hash运算得到Hash值H1
然后用CA的公钥解密签名Signature,得到Hash值H2
我们比较H1和H2,值相同就是可信赖,不同就是不可信赖
TLS第三次握手(客户端加密,服务端解密)
客户端就会生成一个新的随机数 (pre-master),用服务器的 RSA 公钥加密该随机数,通过「Client Key Exchange」消息传给服务端
服务端收到后,用 RSA 私钥解密,得到客户端发来的随机数 (pre-master)。
至此,客户端和服务端双方都共享了三个随机数
分别是
Client Random
Server Random
pre-master
于是,双方根据已经得到的三个随机数,生成会话密钥(Master Secret)
它是对称密钥(私钥加密私钥解密)
然后客户端还要做两步
发一个「Change Cipher Spec」,告诉服务端开始使用加密方式发送消息
发一个「Encrypted Handshake Message (Finished)」消息,把之前所有发送的数据做个摘要,再用会话密钥(master secret)加密一下,让服务器做个验证,验证加密通信「是否可用」和「之前握手信息是否有被中途篡改过]
TLS第四次握手(服务端加密,客户端解密)
服务器也是同样的操作,发「Change Cipher Spec」和「Encrypted Handshake Message」消息,如果双方都验证加密和解密没问题,那么握手正式完成。
最后,就用「会话密钥」加解密 HTTP 请求和响应了