https 原理与相关知识点
概述
Http 是明文传输的通信协议, 存在着一些风险:
- 窃听(eavesdropping): 第三方可以获知通信内容
- 篡改(tampering): 第三方可以修改通信内容
- 冒充(pretending): 第三方可以冒充他人身份参与通信
SSL/TLS 协议是为了解决这三种风险而设计的:
- 所有信息都是加密传播,第三方无法窃听。
- 具有校验机制,一旦被篡改,通信双方会立刻发现。
- 配备身份证书,防止身份被冒充。
SSL/TLS 原理
SSL/TLS 协议的基本思路就是采用非对称加密, 客户端向服务器获取公钥, 然后使用公钥加密信息, 服务器收到密文后, 使用私钥进行解密.
- 如何保证公钥不被篡改
将公钥放在数字证书中. 只要证书是可信的, 公钥就是可信的.
- 公钥加密量计算太大, 如何减少耗时
每一次对话(session), 在客户端和服务端之间都会生成一个"对话密钥"(session key), 这是一个对称加密的过程, 运算过程会比较快, 服务器公钥只用于加密对话密钥, 这样就减少了加密运算的消耗时间.
因此, SSL/TLS 的加密过程基本如下:
- 客户端向服务器索要并验证公钥
- 双方协商生成对话密钥
- 使用对话密钥进行加密通信.
上面过程的前两部, 又称为"握手阶段(handshake)"
握手阶段概览
基本运行过程
SSL/TLS 协议的基本思路就是采用非对称加密, 客户端向服务器获取公钥, 然后使用公钥加密信息, 服务器收到密文后, 使用私钥进行解密.
- 如何保证公钥不被篡改
将公钥放在数字证书中. 只要证书是可信的, 公钥就是可信的.
- 公钥加密量计算太大, 如何减少耗时
每一次对话(session), 在客户端和服务端之间都会生成一个"对话密钥"(session key), 这是一个对称加密的过程, 运算过程会比较快, 服务器公钥只用于加密对话密钥, 这样就减少了加密运算的消耗时间.
因此, SSL/TLS 的加密过程基本如下:
- 客户端向服务器索要并验证公钥
- 双方协商生成对话密钥
- 使用对话密钥进行加密通信.
上面过程的前两部, 又称为"握手阶段(handshake)"
握手阶段的详细过程
客户端发出请求(ClientHello)
客户端发起ClientHello
请求, 提供如下信息:
(1) 支持的协议版本,比如TLS 1.0版。
(2) 一个客户端生成的随机数A,稍后用于生成"对话密钥"。
(3) 支持的加密方法,比如RSA公钥加密。
(4) 支持的压缩方法。
这里客户端发送的信息不包括服务器的域名, 也就是说理论上服务器只能包含一个网站, 否则就不知道应该向客户端提供哪一个网站的数字证书, 这也是为什么服务器通常只能有一张数字证书.
对于虚拟主机的用户来说,这当然很不方便。2006 年,TLS 协议加入了一个Server Name Indication
扩展,允许客户端向服务器提供它所请求的域名。
此时客户端拥有密钥A
服务器回应(SeverHello)
服务器收到客户端请求, 返回ServerHello
:
(1) 确认使用的加密通信协议版本,比如TLS 1.0版本。如果浏览器与服务器支持的版本不一致,服务器关闭加密通信。
(2) 一个服务器生成的随机数B,稍后用于生成"对话密钥".
(3) 确认使用的加密方法,比如RSA公钥加密.
(4) 服务器证书(包含服务器的公钥信息).
除了上面这些信息, 如果服务器需要确认客户端的身份, 就要包含一项请求, 要求客户端提供"客户端证书", 比如金融机构只允许r认证客户连接入网络, 就会向真是客户提供 USB 密钥, 里面就包含了一张客户端证书.
此时服务端拥有密钥 A, B
客户端回应
客户端收到服务器回应以后, 会验证证书的有效性, 大致步骤如下:
- 验证证书的有效期(起止时间)
- 验证证书域名
- 验证证书吊销状态
- 验证证书颁发机构, 如果颁发机构是中间证书, 再验证中间证书的
有效期/颁发机构/吊销状态
. 一直验证到最后一层证书, 如果最后一层证书是在操作系统或浏览器内置, 那么就是可信的, 否则就是自签名证书(层层验证机制)
以上验证步骤, 需要全部通过. 否则就会显示警告.
如果证书没有问题, 就会取出公钥进行加密, 然后向服务器发送以下信息:
(1) 一个随机数C。该随机数用服务器公钥加密,防止被窃听。
(2) 编码改变通知,表示随后的信息都将用双方商定的加密方法和密钥发送。
(3) 客户端握手结束通知,表示客户端的握手阶段已经结束。这一项同时也是前面发送的所有内容的hash值,用来供服务器校验。
此时客户端拥有密钥A, B, 以及一个随机数C
第一项的随机数, 是整个握手阶段出现的第三个随机数, 又称"pre-master key". 有了这个, 客户端和服务器就同时有了三个随机数, 接着使用实现商定的加密方法, 各自生成本次所用的一个"会话密钥"
关于随机数
不管是客户端还是服务器,都需要随机数,这样生成的密钥才不会每次都一样。由于 SSL 协议中证书是静态的,因此十分有必要引入一种随机因素来保证协商出来的密钥的随机性。对于 RSA 密钥交换算法来说,pre-master-key 本身就是一个随机数,再加上 hello 消息中的随机,三个随机数通过一个密钥导出器最终导出一个对称密钥。
pre master 的存在是因为 SSL 协议不信任每个主机都能产生完全随机的随机数,如果随机数不随机,那么 pre master secret 就有可能被猜出来,那么仅使用 pre master secret 作为密钥就不合适了,因此必须引入新的随机因素,那么客户端和服务器加上 pre master secret 三个随机数一同生成的密钥就不容易被猜出了,一个伪随机可能完全不随机,可是是三个伪随机就十分接近随机了,每增加一个自由度,随机性增加的可不是一。
此外,如果前一步,服务器要求客户端证书,客户端会在这一步发送证书及相关信息。
服务器的最后响应
服务器收到客户端的第三个随机数, 用自己的私钥解密, 然后计算生成本次会话所用的会话密钥, 然后向客户端发送以下信息:
(1)编码改变通知,表示随后的信息都将用双方商定的加密方法和密钥发送。
(2)服务器握手结束通知,表示服务器的握手阶段已经结束。这一项同时也是前面发送的所有内容的hash值,用来供客户端校验。
至此, 整个握手阶段全部结束. 接下来, 客户端与服务端进入加密通信, 就完全是使用普通的 HTTP 协议, 只不过用"会话密钥"加密内容.
至此, 服务端拥有密钥A, B, 以及随机数C. A, B 是固定的, 随机数C是随着当前的请求生成的
中间人攻击
中间人攻击过程如下:
- 服务器向客户端发送 公钥 。
- 攻击者截获公钥,保留在自己手上。
- 然后攻击者自己生成一个 伪造的公钥 ,发给客户端。
- 客户端收到伪造的公钥后,生成加密 hash 值发给服务器。
- 攻击者获得加密 hash 值,用自己的私钥解密获得传输密钥。
- 同时生成假的加密 hash 值,发给服务器。
- 服务器用私钥解密获得假秘钥。
- 服务器用加秘钥加密传输信息
这样, 在服务器和客户端都不会发生异常的情况下, 欺骗了浏览器, 得到了密钥X. 更根本的原因在于浏览器无法确认自己收到的公钥是不是网站自己的.
防范方法:
服务端在发送浏览器的公钥中加入CA证书,浏览器可以验证CA证书的有效性
数字证书
网站在使用HTTPS前, 需要向CA机构申领一份数字证书, 数字证书里面含有证书持有者信息, 公钥等信息. 服务器把证书传输给浏览器, 浏览器从证书里面获取公钥就可以了, 证书就是服务器的身份证. 证明该公钥对应该网站.
这里的关键问题在于: "证书本身的传输过程中, 如何防止被篡改?", 即如何证明证书本身的真实性? 这就是数字签名技术发挥作用的时候了.
数字签名
数字签名的制作和验证过程如下:
数字签名的制作过程:
- CA拥有非对称加密的私钥和公钥
- CS对证书的明文信息进行hash
- 对hash后的值用私钥进行签名, 得到数字签名
明文和数字签名共同组成了数字证书, 这样一份数字证书就可以颁发给网站了.
浏览器验证过程:
- 拿到证书, 得到明文T, 数字签名S
- 用CS机构的公钥对S解密(浏览器信任的机构, 所以浏览器保有其公钥), 得到S'
- 用证书里面的hash算法对明文T进行hash得到T'
- 比较S'是否等于T', 为真则表示证书可信(没有被篡改)
吊销检查
目前写进国际标准的吊销状态检查协议有两种: 1.CRL, 2. OCSP
CRL 是一份全量的文件, 记录了被此 CRL 限制的证书中所有被吊销证书的序列号. 通过匹配当前证书序列号, 与 CRL 中序列号, 来判断.
有点绕, 反正就说, 所有打上了这个 URL 的 CRL 的证书, 只要其中一个被吊销, 那么下次 CRL 更新时, 均会查询匹配到. 那么可不可以认为一个中间颁发机构颁发的证书的 CRL 列表只有一个? 不可以! 因为数量可能太多, 厂商完全可以将同一个中间证书颁发的最终证书, 分不同批打不同的 CRL. 而 OCSP 是 TCP 服务, 通过请求证书序列号, 服务器告知当前序列号是否在被吊销名单.
有的证书内置了 CRL+OCSP, 有点只内置了 OCSP, 还有的早起证书只内置了 CRL, 但只内置 CRL 的证书是不被新型浏览器信任了.
吊销状态检查, 是同步的还是异步的?
同步的. 如果异步检查, 有可能会导致浏览器发送数据给了未验证的主机后, 过了一段时间才检查出来证书已吊销. 所以, 必须同步
签发者
证书的签发者, 通过以下步骤获得
-
服务器证书, 如果包含了证书链, 浏览器会尝试匹配(根据当前证书的"签发者公钥"匹配链中的后续证书的"公钥"), 如果匹配失败, 走 2.
-
证书中如果有声明
签发者 URL
, 浏览器尝试下载. 并通过公钥匹配(同 1), 如果匹配失败, 走 3 -
操作系统或客户端浏览器内置证书公钥匹配, 如果匹配失败, 则返回
ERR_CERT_AUTORITY_INVALID
. -
附加项: 如果任何一级证书, 被声明了
oID
, 则会被浏览器显示成EV
(绿色地址栏带上公司名称).