> For the complete documentation index, see [llms.txt](https://jun-wang.gitbook.io/learnjava/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://jun-wang.gitbook.io/learnjava/ji-shu-xue-xi/ji-suan-ji-wang-luo/https-xie-yi-ru-men.md).

# HTTPS协议入门

## 1. HTTPS出现的背景

虽然HTPP协议很优秀并且方便，但是不得不正视HTTP协议存在的一些问题：

* 通信使用明文（不加密），内容可能会被窃听；
* 不验证通信双方的身份，因此有可能遭遇伪装；
* 无法证明报文的完整性，所以有可能已遭篡改；

这些问题不仅在HTTP协议上出现，其他未加密的协议中也会存在这类问题。

由于这些问题的存在，HTTPS协议就应运而生，HTTPS，超文本传输安全协议，是和SSL（Secure Socket Layer，安全套接层）或者TLS（Transport Layer Security，安全传输层协议）组合使用的，通常HTTP直接和TCP通信，当使用SSL时，则演变成先和SSL通信，再由SSL和TCP通信了。

所以说HTTPS并非是应用层的一种新协议，只是HTTP通信接口部分用SSL和TLS协议代替，简言之，HTTPS就是身披SSL协议这层外壳的HTTP。SSL是独立于HTTP的协议，所以不光是HTTP，其他应用层协议SMTP，Telnet等协议均可以配合SSL协议使用。可以说SSL是当今世界上应用最为广泛的网络安全技术。

## 2. HTTPS的三大功能

上面提到了HTPP协议的不足，下面说一下HTTPS是如何解决这三个问题的。

### 2.1 通信使用明文（不加密），内容可能会被窃听

在网络上传输信息，本身就是可以被他人截获的，比如通过抓包工具，第三者就可以在同局域网的一台主机，或者路由器或者互联网的任何地方都可能被截获数据。HTPP使用明文传输，相当于你传输的数据完全暴露在了网络上。

HTTPS传输数据的时候会对通信进行加密，使用SSL建立安全线路之后，就可以在这条线路上进行HTTP通信了。相当于单独建立了一条安全信道。

除了HTTPS这种对整个通信线路进行加密外，解决这个问题还可以对http的报文体加密，这就要求通信双方都具有加密解密的能力，由于这种方式并没有对整个通信线路加密，报文内容还是有被篡改的风险。

### 2.2 不验证通信双方的身份，因此有可能遭遇伪装

HTTP协议中的请求和响应不会对通信双方进行确认，也就是说存在“服务器是否就是发送请求中URI真正的主机，返回的响应是否是真的返回到实际提出请求的客户端”等类似问题。并且，由于不存在通信双方的处理步骤，任何人都可以发起请求。可能会出现DOS攻击等问题。

HTTPS中SSL就可以确认通信方，它提供了一种被称为证书的手段，证书由值得信赖的第三方机构颁发，用以证明服务器和客户端是实际存在的，另外伪造证书从技术角度说是异常困难的一件事，所以只要能确认通信方持有的证书就可以判断通信方的真实意图。

### 2.3 无法证明报文的完整性，所以有可能已遭篡改

HTTP协议无法确认客户端发出的请求和服务端接收到的请求是相同的，同样，也无法确认服务端发送的响应和客户端接收的响应是相同的。很容易出现中间人攻击。

虽然HTTP协议可以使用md5等信息摘要算法保证数据完整性，但是MD5本身都可能被篡改，也就无法保证其安全性。SSL提供了摘要功能。可以保证数据的完整性。

从HTTPS的功能来看，可以总结为：HTTP+加密+认证+完整性保护=HTTPS。

## 3. HTTPS的混合加密机制

首先先来谈谈两种加密方法：

### 3.1 共享密钥加密

也被叫做对称密钥加密，加密和解密使用相同的密钥，但是在通信的时候需要把密钥也一并发送，这样有可能被别人截获；所以使用共享密钥加密需要考虑两个问题：

* 如何安全的发送密钥？
* 如何安全的保管接收到的密钥？

### 3.2 公开密钥加密

公开密钥加密很好的解决了共享密钥加密的困难，公开密钥加密也叫非对称密钥加密，加密和解密使用不同的密钥，服务器提供公开密钥，客户端使用公开密钥对数据进行加密，然后服务器使用私有密钥对密文进行解密，这样就保证密文不会被破解。

### 3.3 混合密钥加密

使用公开密钥加密方式传输数据比较慢，所以HTTPS结合了两者的优点，使用混合加密机制，首先在交换密钥的时候使用公开密钥加密方式，确认连接后，传输数据使用共享密钥加密方式。这个流程大致为：

1. 服务端B发给客户端A自己的公钥C；
2. 客户端A通过公钥C对后面要使用对称加密的私钥D进行加密发送给服务端B；
3. 服务端B拿到加密后的私钥D使用自己非对称加密的私钥对其解密，拿到私钥D；
4. 后续通信就可以使用私钥D加密解密的方式来传输报文了。

遗憾的是公开密钥加密还是存在一些问题，那就是无法证明收到的公钥就是原本预想的那台服务器发行的公开密钥呢？或许在传输途中真正的公钥已经被攻击者替换掉了。

为了解决上面的问题，可以使用由数字证书认证机构（CA）和其相关机关颁发的公开密钥证书。

### 3.4 数字证书认证

我们来介绍一下数字证书认证机构的业务流程：

1. 首先，服务器的运营人员向数字证书认证机构提出公开密钥的申请。数字证书认证机构再确认申请者的身份之后，会对已申请的公开密钥做数字签名，然后分配这个已签名的公开密钥，并将该公开密钥放入公钥证书后绑定在一起。
2. 服务器会将这份由数字证书认证机构颁发的公钥证书发送给客户端，以进行公开密钥加密方式通信。公钥证书也可以叫做数字证书。
3. 客户端接收到数字证书后，可以使用数字证书认证机构的公开密钥，对那张证书上的数字签名进行验证，一旦验证通过，客户端便可以明确两件事：一、认证服务器公开密钥的是真实有效的数字证书认证机构。二、服务器的公开密钥是真的。

此处认证机关的公开密钥必须安全的移交给客户端。如何安全的移交是一件很困难的事，因此，多数浏览器开发商发布版本时，会事先在内部植入常用认证机关的公开密钥。

## 4. HTTPS通信过程

![](/files/-M89ERBlwdEUlKZNfSGw)

1. 客户端发送Client Hello报文开始SSL通信。报文中包含客户端支持的SSL的版本、加密组件（Cipher Suite）列表（所使用的加密算法及密钥长度等）；
2. 服务器发送Server Hello报文作为应答。可客户端一样，在报文中包含SSL协议版本以及加密组件。服务器的加密组件内容是从接收到的客户端加密组件内筛选出来的；
3. 服务器发送Certificate报文。报文中包含公开密钥证书；
4. 最后服务器发送Server Hello Done报文通知客户端，最初阶段的SSL握手协商部分结束；
5. SSL第一次握手结束后，客户端以Client Key Exchange报文作为回应。报文中包含通信加密中使用的一种被称为Pre-master secret的随机密码串。该报文已用步骤3中的公钥进行加密；
6. 客户端继续发送Change Cipher Spec报文。提示服务器在此报文之后的通信采用Pre-master secret密钥加密；
7. 客户端发送finished报文。该报文包含连接至今全部报文的整体校验值。这次握手协商是否能够成功，要以服务器是否能够解密该报文作为判定标准；
8. 服务器发送Change Cipher Spec报文；
9. 服务器发送Finished报文；
10. 服务器和客户端的finished报文交换完毕之后，SSL连接就算建立完成。当然，通信会受到SSL的保护，从此处开始进行应用层协议的通信，即发送HTTP请求。
11. 应用层协议通信，即发送HTTP响应；
12. 最后由客户端断开连接。断开连接时，发送close\_notify报文。上图做了一些省略，这步之后再发送TCP FIN报文来关闭与TCP的通信。

在以上流程中，应用层发送数据时会附加一种叫做MAC（Message Authentication Code）的报文摘要。MAC能够查知报文是否遭到篡改，从而保护报文的完整性。

## 5. SSL和TLS

HTTPS使用SSL（Secure Socket Layer）和TLS（Transport Layer Security）这两个协议。

SSL技术最初是由浏览器开发商网景通信公司率先倡导的，开发过SSL3.0之前的版本。目前主导权已转移到IETF（Internet Engineering Task Force,Internet工程任务组）的手中。IETF以SSL3.0为基准，后又制定了TLS1.0、TLS1.1和TLS1.2。

**TSL是以SSL为原型开发的协议，有时会统一称该协议为SSL**。

当前主流的版本是SSL3.0和TLS1.0。由于SSL1.0协议在设计之初被发现出了问题，就没有实际投入使用。SSL2.0也被发现存在问题，所以很多浏览器直接废除了该协议版本。

## 5. HTTPS使用场景

当使用HTTPS时，通信会变慢，导致通信变慢的原因有两个：

* 一是网络负载，当使用HTTPS进行通信时，网络负载比HTTP要高2-100倍。
* 二是由于HTTPS每次通信都要加解密，对CPU的消耗也很大。所以一般只有在传输机密信息时使用HTTPS，比如用户密码，银行信息等。

再有就是使用HTTPS需要支付购买证书的费用，一些机构考虑到这点也可能优先选择HTTP协议。

> 参考：
>
> 《图解HTTP》
