一. 什么是HTTPS?
在网络传输过程中, 存在着运营商劫持和一些黑客入侵这样的危险, 在之前只有HTTP的明文传输数据环境下, 这样的问题是有些泛滥的, 这种情况下就不清楚在中间传输过程中就被哪一服务器将数据篡改了, 所以在后来就引入了HTTPS.
HTTPS (全称: Hyper Text Transfer Protocol over Secure Socket Layer), 就是 HTTP + 安全层(SSL), 是以安全为目标的 HTTP 通道, 简单讲就是 HTT P的安全版本, 即 HTTP 下加入 SSL 层, HTTPS 的安全基础是 SSL.
HTTPS 和 HTTP 一样, 都是应用层协议, HTTPS 相比于 HTTP 多了一个加密的功能, 就是在 HTTP 基础上引入了SSL/TLS 加密机制, 该功能作用不是防止数据被窥察, 而是为了防止数据被篡改, HTTP 是明文传输, HTTPS 是密文传输, HTTPS 可以更好地保护数据的传输.
如何理解这里的安全?
我们要知道安全这个概念只是相对而言, 要知道 “道高一尺, 魔高一丈”, 不管安全措施如何完善, 相信总是有更厉害的大佬有针对攻击办法, 但我们认为, 网络传输中, 只要黑客解密的成本超过了数据本身的价值, 就认为是安全的了.
这里有几个专有名词需要了解一下
明文: 传输的原始数据.
密文: 原始数据被加密后的数据.
密钥: 可以将明文转换成密文, 也可以将密文转换为明文的 “钥匙”.
二. HTTPS中的加密机制(SSL/TLS)
HTTPS 引入的加密层, 称为 SSL 或 TLS, 在 SSL 中加密的机制主要有两种:
- 对称加密
- 非对称加密
但 SSL/TLS 部分其实并不是只在 HTTPS 中使用, 在其他的场景中也会用到(比如 SSH 协议, JDBC 等).
1. HTTP的安全问题
HTTP 是明文传输的, 当有黑客或者运营商从中作梗, 就可以直接篡改客户端和服务器之间传输的数据, 此时就没有什么安全性可言, 客户端和服务器拿到什么样的数据完全就是黑客说了算了.
也就是说, 只要网络上的数据是明文传输的, 都是存在被劫持, 被篡改的风险的, 所以为了能够改善这种问题, 就引入了加密, HTTPS 就应运而生了.
2. 对称加密
对称加密就是客户端和服务器使用相同的密钥对密文进行加密与解密, 密钥就可以认为是一串数字/字符串, 加密就是把明文 (HTTPS 中就是针对 HTTP 的各种 header 和 body) 和密钥字符串进行一系列的数学变换.
a(明文) + key = b(密文), 这是加密的过程
b(密文) + key = a(明文), 这是解密的过程
要注意, 这里密文传输安全的前提是黑客并不知道密钥是什么, 这就要求不同的客户端使用的是不同的密钥才行, 因为如果不同客户端使用的是相同的密钥, 那么黑客只需要自己启动一个客户端就能拿到密钥, 成本不高, 就没什么安全可言了.
所以, 不同的客户端需要有不同的密钥, 这个密钥要么由服务器生成, 要么由客户端生成, 假设我们这里是由客户端生成密钥, 客户端生成密钥后就需要在传输数据之前需要先将密钥发送给服务器, 即如下过程:
这样不同的客户端就使用了不同的对称密钥来对数据进行加密, 那么当客户端生成对称密钥后, 先将对称密钥传输到服务器, 服务器拿到密钥后再进行业务数据的传输, 之后就使用从客户端拿到的密钥进行数据的加密和解密了.
但此时还是有问题的, 一开始密钥传输的安全问题如何得到保障呢? 在此时的场景下, 密钥刚刚生成, 也就是服务器还不知道密钥是什么, 所以这次密钥的传输还是只能使用明文传输, 很容易就被黑客拦截获取了, 这样的加密也就形同虚设了, 所以就引入了下面的 “非对称加密”.
3. 非对称加密
为了让密钥安全的传输到服务器, 就需要对密钥也进行加密.
对于非对称加密, 它拥有两个密钥, 一个公钥和一个私钥, 其中公钥 “人人” 都能获取到, 而私钥是构造私钥的 “人” 才知道.
相当于我们现实生活中的锁与钥匙, 而这个锁就相当于公钥, 钥匙就相当于私钥.
其中公钥是用来加密的, 而私钥是用来解密的.
明文 + 公钥 = 密文
密文 + 私钥 = 明文
此时, 就可以使用非对称加密了, 首先客户端会向服务器询问服务器的公钥是什么, 然后服务器会向客户端发送一个公钥, 客户端收到公钥后会使用这个公钥对客户端构造的对称密钥进行加密, 然后会把加密后的对称密钥传输给服务器, 服务器使用私钥解密得到客户端的对称密钥, 之后的业务数据就可以使用这个对称密钥进行加密和解密了(对称加密).
要注意, 非对称加密只是用来传输对称密钥的, 一旦对称密钥到达服务器之后, 后序的传输都是使用对称密钥来加密和解密了.
有的小伙伴可能有疑问, 为什么有了非对称加密, 还要继续使用对称加密呢?
这是因为使用对称加密传输速度是比较快的, 而非对称加密速度就慢很多了, 实际场景会要求尽可能提高整体的速度, 使用对称加密显然更合适.
4. 中间人问题
有了上面的非对称加密, 数据传输的安全其实还是存在问题的, 可能会存在 “中间人” 问题, 这个中间人对于服务器会伪装成 "客户端"的身份, 对于客户端, 中间人就会伪装成 “服务器”;
当服务器发送自己的公钥给客户端时, 中间人也会生成一对公钥与私钥, 中间人就把服务器的公钥换成自己的公钥, 然后客户端使用中间人的公钥加密对称密钥, 然后发送给服务器, 此时中间人就可以再次拦截, 使用自己的私钥获得对称密钥, 获得密钥后中间人会将密钥使用服务器的公钥再加密发送给服务器.
此时的数据传输就又成了 “透明” 的了, 在之后的对称加密传输过程中, 中间人已经知道了对称密钥, 就可以将客户端请求/服务器响应的密文数据解密得到原始数据, 中间人就可以针对原始数据进行篡改, 然后再加密发送, 这样这位中间人就神不知鬼不觉就拿到到了客户端和服务器之间传输的数据, 可以进行查看和篡改.
5. 证书
中间人问题的解决方案是引入一个第三方工信机构, 现在的服务器 (网站) 一般在设立之初, 就需要去专门的认证机构, 申请证书, 服务器先提供资质证明给工信机构, 工信机构通过审核后, 会给服务器发送一个证书, 该证书不是普通的证书, 里面含有一些校验机制 (校验的过程类似 TCP/UDP 的校验和), 然后服务器会把自己的公钥放入证书中, 客户端也不再询问公钥, 而是询问服务器证书, 得到证书后会去查该证书是否合法, 如果合法才会使用服务器证书中的公钥去进行对密文请求与密钥的加密, 并发送给服务器, 如果不合法浏览器就会弹窗警告.
这个过程就类似于我们使用的身份证来证明身份, 派出所就是第三方的认证机构, 身份证是无法被其他地方生成或者篡改的, 其他人就可以通过身份证来辨识我们的身份.
那么客户端是如何对证书进行验证的呢?
实际上, 操作系统是会内置一些工信机构的信息(包含工信机构的公钥)的.
首先我们需要知道证书上面会有一个特定的字段, 叫做证书的签名, 这个签名是一个被加密的字符串, 是通过对证书中所有的属性, 计算出来的一个校验和(签名), 再由颁布证书的工信机构使用它的私钥对这个签名进行加密.
证书中是由很多字段构成的(明文的), 比如:
字段1: 证书的过期时间
字段2: 颁布证书的机构名
字段3: 服务器的url
字段4: 服务器自己的公钥
字段5: 加密后的签名
还有很多字段: …
客户端对证书的校验过程如下:
- 判断证书的有效期是否过期
- 判定证书的发布机构是否受信任(操作系统已经内置了受信任的证书发布机构)
- 得到初始的签名, 客户端使用系统中内置的工信机构的公钥, 针对证书中的加密签名进行解密得到了初始签名(这个签名是权威机构算出来的, 设为sum1).
- 计算现在的签名, 客户端使用同样的签名计算算法, 基于证书中的属性重新计算, 得到sum2.
- 比较两个签名是否相同, 如果相同(sum1 == sum2), 说明证书中的数据都是未被篡改的原始数据, 如果签名不同(sum1 != sum2), 说明证书的数据被篡改过, 客户端的浏览器就会弹框报错.
此时, 黑客即使把证书中服务器的公钥篡改替换成自己的公钥, 然后黑客再针对证书中的各个属性, 重新计算签名, 下一步, 黑客就需要把签名重新加密, 这里黑客就无能为力了, 因为想要加密, 黑客就必须知道工信机构的私钥, 显然, 黑客是无法知道的, 证书的关键, 不是让黑客 “看不到”, 而是让黑客 “改不了”.
所以, 此时来看加入证书后的加密过程, 其实是涉及到5把🔐的, 即工信机构的公钥和私钥, 服务器自己的公钥和私钥, 还有对称密钥.