SSL/TLS 加密传输的原理
SSL、TLS 是什么,两者有什么关系?
TLS,Transport Layer Security 和 SSL,Secure Sockets Layer 是一种建立并使用安全通信信道的协议。TLS 是 SSL 升级版。目前网络上提到的 SSL,大部分指加密通信的协议,本质上指的是 SSL 和 TLS 两种协议。因此,也常常有人将两者合并起来写做 SSL/TLS。
下面是它们的迭代历程:
- SSL 1.0 – 1990 年开始开发,因为安全原因未发布。
- SSL 2.0 – 1995 年发布,2011 年停止维护,存在安全问题。
- SSL 3.0 – 1996 年发布,2015 年停止维护,存在已知安全问题。
- TLS 1.0 – 1999 年发布,计划于 2020 年停止维护。
- TLS 1.1 – 2006 年发布,计划于 2020 年停止维护。
- TLS 1.2 – 2008 年发布。
- TLS 1.3 – 2018 年发布。
可以查看 rfc6101 和 rfc5246 来了解 SSL 和 TLS 协议的详情。需要注意的是,那会让你掉不少头发。
SSL/TLS 加密传输的原理是什么?
在讲 SSL/TLS 之前,需要简单讲一讲对称加密和非对称加密,然后在引出 SSL/TLS。
对称加密
对称加密使用同一个密钥完成加密和解密操作,通信双方都需要拥有此密钥。

举个最简单的对称加密的例子,现有密钥 x,需要发送的信息为 m,加密的方法是用密钥做异或操作,加密后的内容为 m^x。对方收到信息后,在次使用 x 进行异或,即 m^x^x=m 这样就收到了原始信息了。这种方法太过简单不够安全。比如在通信中常常开始和结束的消息是固定的,由此窃听者就能猜测出传输的消息 m,进而破获密钥。即使这个例子不够安全,但是已经体现出了对称解密的本质。使用同一个密钥来完成加解密。
通常密钥的长度为几百字节,比如 256 字节,但是要发送的信息往往很长,加密过程是把原文分成和密钥等长的段来分别进行的。成熟的对称加密算法对数据做多轮加密,而且会做字节的移动等操作。解密时做逆操作即可。这样做的目的是为了防止绕开密钥破解出信息来。
对称加密的难点在如何让通信双方都拥有密钥。一种方法是提前在通信双方的机器上部署密钥,这只适用于固定的某些机器之前进行通信。另外一种方法是使用非对称加密技术来传输密钥。非对称加密,是下一节的内容。
非对称加密
非对称加密算法的代表位 RSA 算法,RSA 是三个发明人的首字母缩写。非对称加密中用于加密和解密的密钥是不同的。

在非对称解密中,存在两个密钥——公钥和私钥,其中公钥是公开的,它可以通过明文传输。但是使用公钥加密后的加密文档必须使用私钥进行解密。私钥必须要保密,如果私钥被窃取了,非对称解密的安全性就不能保证的。
SSL/TLS 加密的部分原理
- server 端有非对称加密的公钥 public key 和私钥 private key
- server 将公钥 public key 发送给 client
- client 生成一个用于对称加密的密钥 key,使用 server 端发来的公钥 public key 加密
- client 将加密后的对称加密密钥 key 发送给 server 端
- server 使用自己的私钥 private key 解密,此时 server 端也有了 client 端生成的对称加密密钥
- client 和 server 使用对称加密进行通信
下面是一个原理图,图中是以 HTTPs 来说明的,但换成其他协议同样适用。
什么是中间人攻击?
上面提到的 SSL/TLS 加密通信足够安全吗?不安全。
和 www.baidu.com 通信时,如果保证对方就是 www.baidu.com 呢?考虑在解析 www.baidu.com 的时候,DNS 请求的流量被篡改了,返回的 IP 是骗子的服务器的 IP。此时网址虽然显示的是 www.baidu.com,但此时你却连接到骗子的服务器上。你输入的信息都传到了骗子那里去了。就算传输的内容是加密过的,那也无济于事,因为此时确实是和骗子在通信。
骗子可以在你和 www.baidu.com 之间互相转发数据,并在窥探你发送的数据,此时你完全无法察觉。
这种攻击手段就叫做中间人攻击,它在不知不觉中获取或者篡改了你的数据。即使使用了加密技术,加密的也是和中间人之间的通信信道。

什么是数字证书,有什么用?
数字证书本质上是公钥+签名,签名用来保证接收到的公钥确实是目标服务器发送过来的。举个例子,你收到了署名为小明的信,你如何保证这封就是小明寄给你呢?但假如这封信上面有一个小明的签名,此签名其他人万万无法模仿和伪造,如此你就能确信此信是由小明寄给你的了。
使用 SSL/TLS 通信是,客户端会收到服务器发送过来的数字证书,这个证书里面包含公钥和签名,其内容看起来像是这样的:
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
ed:a5:67:69:4c:8f:52:c6
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=CN, ST=BeiJing, L=Haidian, O=Earth, OU=China, CN=XiaoMing
Validity
Not Before: Nov 24 07:31:29 2021 GMT
Not After : Dec 24 07:31:29 2021 GMT
Subject: C=CN, ST=BeiJing, L=Haidian, O=Earth, OU=China, CN=XiaoMing
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
00:de:b0:18:3a:71:96:27:90:2d:85:58:4c:74:52:
20:48:b9:58:45:ed:e4:ea:c9:f0:32:ae:76:41:e8:
96:47:29:61:d6:61:df:04:af:d9:a9:28:8e:f4:fe:
aa:6c:6a:60:8d:e2:37:43:a1:db:3c:6a:cb:19:b2:
7d:3c:b1:b4:ae:93:a3:40:5a:21:56:c5:de:a5:ac:
dc:f2:8c:3e:c1:b7:d3:94:7d:ad:e3:aa:c7:e6:b7:
92:93:11:7c:f3:49:a6:ef:ef:f8:b5:b8:a2:8c:2e:
00:07:8f:87:5c:84:68:9a:e3:78:28:fe:5c:7a:f5:
98:11:72:13:87:f8:2f:10:4b:00:a0:0c:f2:e8:2c:
40:4e:97:8c:24:a9:46:9a:e7:ed:0c:90:41:6d:5e:
68:b5:d4:9e:cc:1d:fd:2a:9e:af:cb:78:54:c0:9d:
1e:5e:01:8d:f2:b5:79:aa:35:f7:b0:4a:b2:fc:7c:
ef:b2:42:1b:f8:d7:08:3c:6d:1d:2d:c6:b5:75:d9:
4b:2e:46:61:03:fa:2f:e2:02:d9:9b:a4:04:5f:ba:
d6:3e:07:76:f3:de:86:86:8b:3e:52:e3:69:1c:9e:
4c:ac:8a:60:d0:b0:30:b5:b3:34:70:b2:cc:78:dc:
fd:f4:f3:ad:e4:a3:ad:e4:dc:22:e5:de:4e:66:6a:
e4:6b
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Subject Key Identifier:
71:9A:E3:A1:70:70:E0:1E:88:1F:33:54:7F:96:3D:A1:6E:2A:4A:43
X509v3 Authority Key Identifier:
keyid:71:9A:E3:A1:70:70:E0:1E:88:1F:33:54:7F:96:3D:A1:6E:2A:4A:43
X509v3 Basic Constraints:
CA:TRUE
Signature Algorithm: sha256WithRSAEncryption
a1:26:89:9c:51:e9:72:48:e7:30:bf:e7:9c:e7:3e:64:fc:c8:
70:80:0f:19:43:4a:45:d1:b1:0f:64:f6:4e:97:6f:fe:56:6c:
61:60:7d:f5:73:d1:e0:6a:af:9a:f2:d4:b4:a3:c9:45:e1:07:
f4:8e:04:1c:9b:0a:de:ff:15:3f:72:c0:32:b4:6a:0d:64:1a:
e5:20:20:5f:5e:e1:41:01:b2:5e:70:46:68:35:fc:3c:7a:9c:
5b:34:ff:92:4c:62:07:0f:4c:be:95:55:07:5d:8c:18:9a:e6:
b5:6f:75:b5:ef:c0:57:5f:93:e1:35:45:b6:0f:cf:c2:a8:e7:
e0:56:a0:a2:68:3d:6b:0c:36:af:72:3b:32:ad:c6:ed:3f:b2:
8d:fb:9d:07:77:80:71:0a:7a:c1:47:f7:91:2e:1c:cc:05:b2:
b8:0e:df:a2:0a:c7:55:e9:be:a4:b0:4f:2a:47:39:51:1c:70:
eb:c1:23:52:4d:23:f4:7b:d1:8c:51:c5:99:0f:c0:26:95:f1:
a9:78:2c:1c:16:f4:f4:89:2a:b8:45:b2:e5:b2:05:aa:5a:30:
83:42:ce:c3:3d:de:58:cc:c5:6e:cc:50:4f:2e:5f:40:b2:94:
c5:36:7c:1c:fd:92:23:b9:c7:90:16:a6:8b:b0:a7:57:0a:d3:
87:7a:d1:a5
这个签名是基于公钥使用某种算法生成的,假如中间人出于你和 www.baidu.com 之间,它想要攻击,就必须伪造 www.baidu.com 的证书,将证书中的公钥换成自己的,但是这签名它无法伪造,因为如果伪造了,你(客户端)是能够察觉到的。
数字证书的生成过程
要想得到证书,需要去数字证书认证机构(Certificate Authority, CA)申请,CA 核实了申请者身份后,会给申请者颁发一个数字证书。该数字证书中包含申请者的国家、地区、主机域名等信息。同时 CA 会在该数字证书上签名,证明这个数字证书真的是自己颁发出去的。
这个签名是任何人无法伪造的,每个 CA 都有属于自己的一个公钥和私钥对,公钥是完全公开的,私钥绝对保密。CA 使用使用某种哈希算法对申请者的公钥+其他信息取哈希值,并使用自己的私钥对哈希值进行加密,将此加密内容作为签名。
如何验证证书的真伪?
客户端收到证书后,使用 CA 的公钥对数字签名进行解密,这可以得到原哈希值 hash1。另外,客户端使用同样的 hash 算法计算证书中的公钥+其他信息的哈希值 hash2。客户端比较 hash1 和 hash2 是否相同。如果相同,那说明此数字证书的签名确实是 CA 的签名。如果是旁人的签名,那么解密出来的两个 hash 一定不相同。
因为 CA 的私钥是绝对保密的,攻击者是不可能有 CA 的私钥的,所以它不可能伪造出 CA 的签名。
那么 CA 的公钥从何而来呢?数字证书中包含 CA 的信息和序列号,而全球 CA 的数量是有限的,多数操作系统和浏览器已经内置了 CA 的公钥。CA 的密钥只有 CA 知道,需要高度保密,如果泄漏了,所有签名的证书都不安全了。
数字证书如何防止中间人攻击?
在通信的时候,服务器把证书发给客户端,客户端收到以后需要检验此证书的真实性。如果证书是假的,说明对方不值得信赖。因为如果证书是假的,说明服务器的拥有者没有得到 CA 的认可,为什么没有得到认可?因为它是骗子。他没有办法提供有效的身份证明,以说明自己是该域名的拥有者。

客户端收到数字证书之后,如果检查到证书是真的,则从中取出公钥,基于之前提到的方法来加密通信。
自签名证书如何工作的?
找 CA 生成一个数字证书虽然不一定需要花钱,但是很麻烦。我们可以成立一个 CA,然后使用这个 CA 来做对证书做签名。随后,让客户端信任自己成立的这个 CA。自己成立一个 CA,本质上是创建对称加密的公私钥对,然后使用自己的私钥给自己签名,这种证书也叫做根证书。
将这个 CA 的证书,加入到客户端信任的 CA 列表中,这样使用此 CA 生成的其他的证书发送到客户端后,客户端可以使用 CA 的证书来识别签名的真伪。另外也可以直接使用根证书来通信。
对于 Web 用于,客户端来自天南海北的各种设备,预装你自己生成的根证书可操作性太。不过,对于服务端和客户端均受控的情况,使用这种自签名的证书也可以实现可靠的加密通信。但是
有的政府网站需要让你安装数字证书,其原因就是这些政府机构不方便去 CA 申请证书,因此使用了自签名的证书。