之前生成证书那篇文章中总结了很多 X.509 的知识点,这次再通过 HTTPS 来看看 PKI 机制的一个完整应用。
加密算法方面的验证,或者公式什么的,太过复杂、繁琐,我看不懂,也不想弄懂,我只关心整套流程是怎么在发挥作用。
为什么使用 HTTPS
安全,安全,安全
HTTP 协议的天生缺陷:
- 窃听 -> 需要对通信内容进行加密
- 篡改 -> 需要对通信内容进行校验
- 冒充 -> 需要一个可信赖的身份认证体系
有了 HTTPS 之后,再冒充只能搞相近的域名做钓鱼了。
答案就是 TLS(HTTP + TLS = HTTPS)。
TLS
Version | PublishTime | Status |
---|---|---|
SSL 1.0 | - | unpublished |
SSL 2.0 | 1995 | RFC6176 (Deprecated in 2011) |
SSL 3.0 | 1996 | RFC7568 (Deprecated in 2015) |
TLS 1.0 | 1999 | RFC2246 |
TLS 1.1 | 2006 | RFC4346 |
TLS 1.2 | 2008 | RFC5246 |
TLS 1.3 | 2018 | RFC8446 |
SSL 协议由网景公司开发,后来被 IETF 标准化,正式名称叫做 TLS,目前应用最广泛的应该还是 TLS 1.2。
注释:SSL/TLS 可以认为是同一个协议,不过版本不相同。
SSH 本来是一个非常成功的网络通信协议,也被应用来给一些应用层协议提供安全、透明的网络通道,但是其传输层和应用层过于耦合,必须要有 SSH 服务器支持才行。
因此借鉴 SSH 的网络传输层设计思路,TLS 被开发出来,用来封装 TCP/UDP 包,不会影响应用层数据,所以被广泛地与各种应用层协议结合使用,HTTPS、SMTP 中的 STARTTLS 就是其中的代表。
之前说的 PKI 机制可以解决证书可行的问题。
非对称加密计算量太大,就只用非对称加密来协商会话密钥,然后使用会话密钥来做对称加密。
公钥加密
数字证书
非对称加密
- 对称加密使用同一个密钥,有很多种优秀的加密算法可以保证只要密钥不泄露,几乎无法解密。
- 非对称加密相当于使用两个不同的密钥:公钥、私钥。
- 根据公钥几乎无法计算出私钥。
- 一般使用公钥加密,私钥解密。
- 非对称加密设计非常复杂的数据计算,所以加密解密成本非常高。相比较而言,对称加密的加密解密成本几乎可以忽略。
PKI 与证书链
可以看看前面发的 生成证书那篇文章。
虽然由于政治、
HTTPS 全过程
这里只看加密通信的部分,SYN、ACK 就跳过了。
方法
- 打开 WireShark,应用
tls
过滤 curl https://www.markjour.com/
- 找到 IP 之后,修改过滤规则为
ip.addr == 121.42.82.115 and not tcp.len == 0
- 停止网络监听,对那一串网络包逐条查看
总结
主要思想是利用非对称加密实现一个安全的数据交换通道,两端生成相同的密钥,用于对称加密。
重点就是前面这一段应用非对称加密算法的握手协议,也就是一个密钥交换过程,这一阶段巧妙地在明文通信基础上保证了通讯安全。
PS:由于这个阶段还是明文通信,如果直接交换对称加密密钥,就相当于没有加密,只能非对称 + 信任链来解决这个问题。
- 客户端发起 TLS 握手 Handshake Protocol: Client Hello
版本信息,支持的加密套件列表 cipher suite,支持的压缩算法列表 compression method,支持的 TLS 拓展 extensions,随机数 randomC 等。 - 服务器响应 TLS 握手
- Handshake Protocol: Server Hello
服务器端会从客户端支持的那些个列表中各选一种。
也会返回一个随机数 randomS - Handshake Protocol: Certificate
证书链,用于向客户端验明正身,以及后面的密钥交换 - Handshake Protocol: Server Key Exchange
- Handshake Protocol: Server Hello Done
- Handshake Protocol: Server Hello
- 客户端校验证书并实现证书协商
- Handshake Protocol: Client Key Exchange
生成一个随机数 PremasterSecret,使用服务器公钥加密,发给服务器
重点:三个随机数,生成一个会话密钥
randomC + randomS + PremasterSecret -> SessionKey
- Change Cipher Spec Protocol: Change Cipher Spec
通知服务器协商完成,以后就使用 SessionKey 通信 - Handshake Protocol: Encrypted Handshake Message
将之前通信使用的数据,使用协商好的密钥和算法加密,发送给服务器,核对通信是否正常
- Handshake Protocol: Client Key Exchange
- 服务器确认
- Change Cipher Spec Protocol: Change Cipher Spec
服务器使用私钥解密拿到客户端发送过来的 PremasterSecret,然后使用相同的方法生成 SessionKey
使用 SessionKey 解密客户端发送过来的加密信息,检查是否正确无误 - Handshake Protocol: Encrypted Handshake Message
服务器同样也加密一段数据给客户端
- Change Cipher Spec Protocol: Change Cipher Spec
- 客户端校验数据没有问题之后,就开始和服务器进行应用层通信
双向认证
即服务器需要验证客户端身份
- 客户端 Hello 之后,服务器需要在 Hello Done 之前发一个 Certificate Request
- 客户端校验服务器证书之后,应该向服务器端发出自己的证书
- 服务器对客户端证书进行校验
<未整理完成>
加密套件
- 认证算法
- 密钥交换算法
- 对称加密算法
- 哈希算法(或者说信息摘要算法)
验证证书
- 计算是否正确
- 证书是否吊销
- 是否在有效期
- 域名是否匹配
TLS 拓展
SNI
这个拓展非常关键,为什么呢?
对于 Web 服务来说,80 端口可能绑定了 3 个域名,他们是不同的网站,承载着不同的业务,他们的证书很可能不相同,
但是客户端 Hello 过来的时候没有指定域名,服务器不知道应该按照那个网站的证书来处理。
RFC4366 为 TLS 添加了一批拓展,包括一个叫做 Server Name Indication,简称 SNI,的拓展,解决了这个问题。
下面是 WireShark 的抓包数据,关于 SNI 这一部分:
0000 00 00 00 15 00 13 00 00 10 77 77 77 2e 6d 61 72 .........www.mar
0010 6b 6a 6f 75 72 2e 63 6f 6d kjour.com
Type: 00 00 server_name
Length: 00 15 21
Server Name list length: 00 13 19
Server Name Type: 00
Server Name length: 00 10 16
Server Name: 77 77 77 2e 6d 61 72 6b 6a 6f 75 72 2e 63 6f 6d
www.markjour.com
据说 IE6、IE7 不支持 SNI,影响就是:如果服务器上绑定了多个域名,浏览器就可能得不到响应(TLS 连接都失败了)。
参考资料与拓展阅读
- HTTPS 协议详解(四):TLS/SSL 握手过程
- 阮一峰,数字签名是什么?
- 阮一峰,RSA 算法原理(一)
- 阮一峰,RSA 算法原理(二)
- 阮一峰,SSL/TLS 协议运行机制的概述
- 阮一峰,图解 SSL/TLS 协议
- Differences between the terms “pre-master secret”, “master secret”, “private key”, and “shared secret”?
- RFC 5246: TLS 1.2
- https://en.wikipedia.org/wiki/Transport_Layer_Security
- 微信公众号, Java 技术栈, 面试官:HTTPS 是如何保证传输安全的?又被问了!
- 微信公众号, IT 服务圈儿,用公司电脑访问奇怪的网站,被抓到了