前言
HTTPS 常用的密钥交换算法有两种,分别是 RSA 和 ECDHE 算法。
其中,RSA 是比较传统的密钥交换算法,它不具备前向安全的性质,因此现在已很少服务器使用。而 ECDHE 算法具有前向安全,所以被广泛使用。
注:之所以说使用RSA算法进行密钥交换不具备前向安全性质,是因为一旦服务器的RSA私钥泄漏,那么不仅此次通讯内容会被破解,以前的所有通讯内容也会被破解,只要泄漏一次就会被一锅端。
因此,下面文章内容介绍的也是ECDHE密钥交换流程,而RSA密钥交换就不做介绍了。
流程
1)第一次握手
客户端首先发送一个「Client Hello」消息给服务端,消息里面包含客户端使用的 TLS 版本号、支持的密码套件列表、一个客户端生成的随机数(暂时记作R1 ,这个随机数后面会用到),以及其它信息。
2)第二次握手
服务端收到客户端的「打招呼」,同样也要回礼,会返回「Server Hello」消息,消息里面包含有服务器确认的 TLS 版本号、一个服务端生成的随机数(暂时记作R2 ,这个随机数后面会用到),然后从客户端的密码套件列表选择了一个合适的密码套件。
接着,服务端为了证明自己的身份,发送「Certificate」消息,会把自己的经过CA机构签名的证书也发给客户端。
因为服务端选择了 ECDHE 密钥协商算法,所以服务端接着会生成 ECDHE 算法的私钥A2 、底数G 、模数P ,然后根据这三个数计算出服务端的ECDHE的公钥 Y2 = G ^ A2 % P
私钥A2 服务器自己保存,然后把公钥Y2 、底数G 、模数P 经服务器的RSA私钥签名后发送给客户端,此消息称为「Server Key Exchange」消息。
随后,就是「Server Hello Done」消息,服务端跟客户端表明:“这些就是我提供的信息,打招呼完毕”
3)第三次握手
客户端收到了服务端的证书后,自然要校验证书是否合法。使用证书所属CA机构的公钥验证证书的签名,如果通过,则使用证书指定的摘要算法计算证书内容的hash值,如果计算出来的hash值,和证书内包含的hash值一致,则证明证书内容没有被篡改过;然后再检查当前访问的网站域名,是否和证书里的域名匹配,如果匹配,则证书校验通过。
接着,客户端也会生成一个客户端的 ECDHE 私钥A1 ,然后计算出ECDHE的客户端公钥 Y1 = G ^ A1 % P ,然后把ECDHE公钥Y1 经服务器的RSA公钥(这个RSA公钥是包含在证书里的)加密后发送给服务端,此消息称为「Client Key Exchange」消息。
至此,客户端 和 服务端 已经得到的东西有: 客户端: ECDHE私钥A1 、服务端的ECDHE公钥Y2 、底数G 、模数P 、客户端随机数R1 、服务端随机数R2 服务端: ECDHE私钥A2 、客户端的ECDHE公钥Y1 、底数G 、模数P 、客户端随机数R1 、服务端随机数R2
客户端通过A1 、Y2 计算出预备主密钥preMaster1 服务端通过A2 、Y1 计算出预备主密钥preMaster2
根据ECDHE算法的特性,preMaster1 和 preMaster2 的值是一样的。有了预备主密钥,客户端和服务端就可以把预备主密钥、随机数R1 、随机数R2 丢给 PRF 函数,计算出主密钥(Master Secret)了。
这里的“PRF ”就是伪随机数函数,它基于密码套件里指定的摘要算法来再一次强化“Master Secret”的随机性。
主密钥有 48 字节,但它也不是最终用于通信的会话密钥,还会再用 PRF 扩展出更多的密钥,比如客户端发送用的会话密钥(client_write_key)、服务器发送用的会话密钥(server_write_key)等等,避免只用一个密钥带来的安全隐患。
有了主密钥和派生的会话密钥,握手就快结束了。客户端发一个「Change Cipher Spec」,然后再发一个「Finished」消息,把之前所有发送的数据做个摘要,再加密一下,让服务器做个验证。
意思就是告诉服务器:“后面都改用对称算法加密通信了啊,用的就是打招呼时说的 AES,加密对不对还得你测一下。”
4)第四次握手
服务器也是同样的操作,发送「Change Cipher Spec」和「Finished」消息,双方都验证加密解密 OK,握手正式结束,后面就收发被加密的 HTTP 请求和响应了。
要注意的地方
- HTTPS只有在密钥交换的时候才会使用非对称加密,交换结束后是使用对称加密方式(通常是AES)通讯的。原因是对称加密的性能要远远好于非对称加密。
- 加密算法保证的是消息的机密性;摘要算法保证的是消息的完整性(不被别人篡改);数字签名算法保证的是消息发送者的身份真实性。
参考资料
|