前言
HTTPS 是什么
HTTP 协议内容都是按照文本的方式明文传输的. 这就导致在传输过程中出现⼀些被篡改的情况. HTTPS 也是⼀个应用层协议, 是在 HTTP 协议的基础上引入了⼀个加密层SSL/TLS, 负责对HTTP进行握手协商和数据的加密解密.
https>https://i-blog.csdnimg.cn/direct/4eff9fdb208442acbd7a2a3b0282d4d4.png" width="993" />
此时交给传输层的数据都是经过加密的, 数据被抓包后攻击者也看不到实际的数据. 只有客户端和服务端能够通过SSL/TLS进行数据解密
我们之前提到过尽管POST比GET隐私性更好, 但是他们都是不安全的, 因为报文是以明文传递的.
一篇文章让你彻底弄懂SSL/TLS协议 - 知乎
什么是"加密"
加密就是把明文(要传输的信息)进行一系列变换, 生成密文. 解密就是把密文再进行一系列变换, 还原成明文. 在这个加密和解密的过程中, 往往需要一个或者多个中间的数据, 辅助进行这个过程, 这样的数据称为密钥.
为什么要加密
以"运营商劫持"举例:
未被劫持的效果, 点击下载按钮, 就会弹出天天动听的下载链接.
https>https://i-blog.csdnimg.cn/direct/9a2388e8e3e14cb38621c66b01293537.png" width="935" />
已被劫持的效果, 点击下载按钮, 就会弹出 QQ 浏览器的下载链接
https>https://i-blog.csdnimg.cn/direct/7cb55b25156543a5b67fe122121feed6.png" width="925" />
由于我们通过网络传输的任何的数据包都会经过运营商的网络设备(路由器, 交换机等), 那么运营商的网络设备就可以解析出你传输的数据内容, 并进行篡改.
点击 "下载按钮", 其实就是在给服务器发送了⼀个 HTTP 请求, 获取到的 HTTP 响应其实就包含了该 APP 的下载链接. 运营商劫持之后, 就发现这个请求是要下载天天动听, 那么就自动的把交给用户的响应给篡改成 "QQ浏览器" 的下载地址了.
https>https://i-blog.csdnimg.cn/direct/fd39cb2f4d5d4d7caf516c431a0a8097.png" width="1193" />
不止运营商可以劫持, 其他的黑客也可以用类似的手段进行劫持, 来窃取用户隐私信息, 或者篡改内容.
所以: 因为http的内容是明文传输的, 明文数据会经过路由器, wifi热点, 通信服务运营商, 代理服务器等多个物理节点, 如果信息在传输过程中被劫持, 传输的内容就完全暴露了. 劫持者还可以篡改传输的信息且不被双方察觉, 这就是中间人攻击, 所以我们才需要对信息进行加密.
成为中间人很简单, 比方说一些公开场合的免费wifi, 连接wifi的人对外进行的网络请求都会经过该路由器, 如果数据没有被加密, 那么他的数据就能被劫持使用.
常见的加密方式
对称加密
采用单密钥密码系统的加密方法, 同⼀个密钥可以同时用作信息的加密和解密, 这种加密方法称为对称加密.
- 特征: 加密和解密所用的密钥是相同的
- 常见对称加密算法: DES、3DES、AES、TDEA、Blowfish、RC2等
- 特点:算法公开、计算量小、加密速度快、加密效率⾼
对称加密其实就是通过同⼀个 "密钥" , 把明文加密成密文, 并且也能把密文解密成明文.
https>https://i-blog.csdnimg.cn/direct/e329fe4434fe4e32abd78e3310dc0cb2.png" width="1278" />
非对称加密
需要两个密钥来进⾏加密和解密, 这两个密钥是公开密钥(public key, 简称公钥)和私有密钥 (private key, 简称私钥).
公钥和私钥是配对的:
- 通过公钥对明文加密, 变成密文
- 通过私钥对密文解密, 变成明文
https>https://i-blog.csdnimg.cn/direct/127497d9532447378349ac1338207a35.png" width="1226" />
常见非对称加密算法: RSA, DSA, ECDSA.
特点: 算法强度复杂(大整数分解质因子困难)、安全性依赖于算法与密钥, 但是由于其算法复杂, 而使得加密解密速度没有对称加密解密的速度快, 最大的缺点就是运算速度非常慢.
数据摘要 && 数据指纹
数据摘要=数字指纹, 其基本原理是利用单向散列函数(Hash函数)对信息进行运算, 生成⼀串固定长度的数字摘要.
常见的Hash算法有: MD5、SHA1、SHA256、SHA512等,算法把无限的映射成有限, 因此可能会有碰撞(两个不同的信息, 算出的摘要相同, 但是概率非常低)
摘要特征:和加密算法的区别是, 摘要严格意义不是加密, 因为没有解密, 只不过从摘要很难反推原信息, 因此通常用来进行数据对比, 比如
场景: 文件下载时, 服务器通常会提供文件的哈希值(例如 MD5 或 SHA256). 下载后, 用户可以自己计算下载文件的哈希值, 并与服务器提供的值进行对比, 验证文件是否完整、未被篡改
数字签名
数字签名是数据摘要的一个重要应用, 它通过对数据摘要进行加密, 确保数据的完整性和真实性.
https>https://i-blog.csdnimg.cn/direct/a92436b86a304c68a2b834682dddad11.png" width="880" />
场景:在 电子邮件和 文档签名中, 通常会对整个文档或消息内容通过Hash算法生成数据摘要, 然后用发送方的私钥进行加密, 生成数字签名(因为只有发送方才有私钥, 私钥加密能标识其唯一性). 接收方使用发送方的公钥解密签名并验证数据摘要, 从而确认消息未被篡改且确实来自于指定的发送者
一. 为什么摘要内容在网络传输的时候⼀定要加密形成签名?
常见的摘要算法有: MD5 和 SHA 系列
以 MD5 为例, 我们不需要研究具体的计算签名的过程, 只需要了解 MD5 的特点:
- 定长: 无论多长的字符串, 计算出来的 MD5 值都是固定长度 (16字节版本或者32字节版本)
- 分散: 源字符串只要改变⼀点点, 最终得到的 MD5 值都会差别很大.
- 不可逆: 通过源字符串生成 MD5 很容易, 但是通过 MD5 还原成原串理论上是不可能的.
正因为 MD5 有这样的特性, 我们可以认为如果两个字符串的 MD5 值相同, 则认为这两个字符串相同.
二. 为什么签名不直接加密, 而是要先Hash形成摘要?
缩小签名密文的长度, 加快数字签名的验证签名的运算速度
其应用在CA证书的密钥协商之中, 下面再说.
HTTPS 的工作过程探究
既然要保证数据安全, 就需要进行"加密". 网络传输中不再直接传输明文了, 而是加密之后的 "密文".加密的方式有很多, 但是整体可以分成两⼤类: 对称加密 和 非对称加密.
为了解释HTTPS的工作过程, 采用循序渐进的方式进行引入:
方案1 - 只使用对称加密
如果通信双⽅都各自持有同⼀个密钥X, 且没有别人知道, 这两房的通信安全当然是可以被保证的(除非密钥被破解), 因为引入对称加密之后, 即使数据被截获, 由于黑客不知道密钥, 因此就无法进行解密, 也就不知道请求的真实内容是啥了.
https>https://i-blog.csdnimg.cn/direct/c8dfa0e420a24f5885634c6b4a061a75.png" width="1203" />
但事情没这么简单. 服务器同⼀时刻其实是给很多客户端提供服务的.
首先, 每个人要用的秘钥都必须是不同的 (如果是相同那密钥就太容易扩散了, 黑客就也能拿到了), 但是只是简单地让通信双方事先协商密钥, 然后内置密钥, 最后让服务器维护每一个客户端的密钥是不现实的, 假如服务器要维护100w个密钥, 成本太高.
那能否在客户端发出请求时, 服务器动态生成一个密钥然后返回给客户端? 这种交换方式显然也是不行的, 因为密钥本身是明文传输的, 是可以被截获的. 如果需要对密钥加密传输, 那就进入死循环.
方案 2 - 都只使用非对称加密
客户端拥有公钥PK1与对应的私钥SK1, 服务端拥有公钥PK2与对应的私钥SK2.
首先, 客户端和服务端交换公钥, 公钥本来就是公开的, 所以中间人是可以截获公钥的.
https>https://i-blog.csdnimg.cn/direct/2402d51877cc48f389ad7435d2684034.png" width="1203" />
然后, 客户端和服务端的通信就使用对方的公钥加密, 自己的私钥解密, 即使中间人截获密文, 因为其没有可以解密的私钥, 依然无法破解密文:
https>https://i-blog.csdnimg.cn/direct/62727882a62d49ea99528a8ae950480a.png" width="1220" />
但这样有两个缺点:
- 加密解密效率太低.
- 依然存在安全问题
先来说安全问题是什么? 图解释很清楚, 中间在第一步公钥协商的时候就已经开始干涉, 并将中间人的公钥假冒给Client和Server, 因为公钥其实就是一串数据, 彼此都不确定它到底是什么.(这也是后面引入CA证书的原因)
https>https://i-blog.csdnimg.cn/direct/5d76b43eaafe4f4fb61cd8ae3fcdcb4b.png" width="1779" />
后面就要引入CA证书解决这个问题, 下面先来解决效率问题.
方案 3 - 非对称加密 + 对称加密
现在就开始解决效率问题了, 其实关键是引入了密钥协商的过程, 往后的通信使用对称加密的方式, 而对称加密的密钥则通过非对称加密进行协商.
https>https://i-blog.csdnimg.cn/direct/d63dd84084d941cc848d682c52555252.png" width="1401" />这依然是存在安全问题的, 同样的, 中间人在公钥交换的时候就开始假冒一方, 比如在Server->Client传递PK2时将自己的PK3传给Client, Client无法分辨这是不是真正的SERver公钥, 只能相信. 于是Client拿着PK3加密C, 被中间人用SK3解密从而得到了对称密钥C.
https>https://i-blog.csdnimg.cn/direct/8b96677bcbf34c0599489739d0b53150.png" width="1301" />
问题本质出在哪里了呢?客户端无法确定收到的公钥的合法性!
引入证书
我们之前都或多或少见过证书, 比如我们访问网页有时候会出现类似的弹窗:
https>https://i-blog.csdnimg.cn/direct/da071ae8321946809340b01039d52de6.png" width="780" />
CA认证
在使用HTTPS前, , 如果服务端要建立一个网站, 首先我们需要给网站申请一个数字证书, 数字证书里含有证书申请者信息、公钥信息等. CA机构就是能颁发证书的权威机构. 服务器把证书传输给浏览器, 浏览器从证书里获取公钥就行了, 证书就如身份证, 证明服务端公钥的权威性.
下面具体解释CA为什么能解决安全问题:
https>https://i-blog.csdnimg.cn/direct/e3f7f6698cbd413586d6245f44d0e18c.png" width="937" />
1. 申请证书
服务器(或用户)需要向 CA 申请证书, 服务器管理员需要提交自己的个人信息, 通过CSR生成器生成生成一个 CSR(证书签名请求)
https>https://i-blog.csdnimg.cn/direct/8d8dcea0fe184d08a10ba7a233749d1e.png" width="1590" />CSR 包含, 如下所示, 其中技术层面最重要的就是服务器的公钥, 然后公钥就保存在CSR文件中日后审核通过后, 就一直充当服务器的公钥, 发送给客户端,
- 服务器的公钥(Public Key)
- 组织信息(公司名称、域名等)
- 其他标识信息(国家、城市、邮箱等)
服务端维不维护公钥都行, 但是服务器一定要自己维护起来私钥.
然后服务器管理员将 CSR 提交给 CA 进行审核.
2. 审核信息
CA 对申请者进行身份验证, 确保其拥有该域名或组织.
审核方式:
- 域名验证:CA 发送验证邮件或 DNS 记录要求申请者配置, 以确认对该域名的控制权
- 组织验证:CA 需要验证企业信息, 如工商注册信息
- 扩展验证:最严格的验证方式, CA 可能要求提供公司文件、电话确认等信息
这里不过多关心
3. 签发证书
审核通过后, CA 使用 CA 的私钥对 CSR 进行 数字签名, 生成最终的 SSL 证书.
https>https://i-blog.csdnimg.cn/direct/4ef81af7d310461ca7987d900e51a5c3.png" width="636" />
证书包含两部分:
1. CA 的数字签名
首先我们要明确CA也是有自己的私钥和公钥的, 分别是为了完成签名和验证的.
a. CA将服务器的明文INFO数据通过HASH函数生成数据摘要
b. 然后用CA自己的私钥 对数据摘要进行加密, 并作为证书的第一部分.
https>https://i-blog.csdnimg.cn/direct/6f0dc91a8de94ee688d423a6b6f53506.png" width="1294" />
2. 证书的剩余部分就是服务器的明文INFO, 包含:
- 签发机构
- 证书有效期(所以证书的申请短时间内只需要申请一次, 过期再申请即可)
- 其他扩展字段(如密钥用途、证书链信息等)
- 服务器的域名
- 申请者
- 服务器的公钥
https>https://i-blog.csdnimg.cn/direct/08179696f9984bb7a175c0e63a78fd90.png" width="652" />
所以综上, 证书 = 企业的明文数据 + 签名.
然后 CA 将签发的证书返回给申请者(服务器), 服务器将证书安装到 Web 服务器.
4. 返回证书 和 验证证书
浏览器内部都会内置一批受信任的 CA 或 CA授权机构 的证书.
https>https://i-blog.csdnimg.cn/direct/0fa23996947447fb9280d434b93889b4.png" width="2225" />理论上来说只需要一个CA的证书就可以, 但这样安全性和可管理性都很差, 所以就需要有证书链, 证书链 = 服务器证书 + 中间 CA 证书 + 根 CA 证书. ([ 根 CA 证书 ] → [ 中间 CA 证书 ] → [ 服务器证书(www.google.com)])
中间 CA 证书是服务器证书的直接签发者, 它自己也是由更高级的 CA(可能是根 CA)颁发的
当浏览器访问一个 HTTPS 网站时:
1. 服务器发送自己的证书(www.google.com
)
2. 浏览器检查该证书的签发者: 如果是中间 CA, 则继续检查中间 CA 的证书
3. 浏览器继续检查证书链, 直到找到根 CA.
所以客户端就可以开始验证证书了:
当客户端(浏览器)访问 HTTPS 网站时, 服务器发送证书给客户端, 客户端验证证书: 如果验证成功, 客户端信任该证书, 继续进行 密钥协商 过程.
客户端验证的过程:
1. 判定证书的有效期是否过期
2. 判定证书的发布机构是否受信任(操作系统中已内置的受信任的证书发布机构).
3. 验证证书是否被篡改(签名的逆过程):
- 客户端先对服务器信息通过Hash函数生成数据摘要(右侧)
- 然后将数字签名部分利用CA的公钥去解密, 得到之前CA签名时(左侧)生成的数据摘要
- 两个数据摘要进行对比, 如果相同则验证成功.
https>https://i-blog.csdnimg.cn/direct/21c39deeb60b46aeaba4524319319926.png" width="1191" />
为什么这样做能保证Client收到的密钥的合法性? 如果中间人篡改证书的内容呢?
这分为三种情况:
1. 中间人篡改服务器信息(明文数据)
中间人篡改了明文数据, 就只能用CA的私钥重新生成一个数字签名, 这是无法做到的
2, 中间人篡改签名(密文数据)
只修改签名没有意义, 因为一般都是要修改明文数据.
3. 中间人同时篡改两个数据
因为对修改后的数据重新生成数字签名只有CA能做到, 客户端也只用CA的公钥解密. 这就意味着无法对现有的证书动手, 中间人如果想骗过浏览器, 就需要用一个真的证书将服务端的证书完全替换掉. 这样做是可以骗过客户端的, 但是这样做:
- 就暴露了中间人的身份.
- 只是暂时骗过客户端, 因为证书中有服务器的域名信息(唯一的), 所以客户端依然可以通过对比目标服务器的域名和证书中的域名来判断.
6. 密钥协商
在证书验证通过后, 客户端和服务器协商会话密钥(对称密钥)即可.
方案 5 - 非对称加密 + 对称加密 + 证书认证
因此通过证书认证就解决了Client无法判断收到的密钥合法性的问题, 因此这就是最终的HTTPS的方案:
https>https://i-blog.csdnimg.cn/direct/15e5ab81e8004389aa0febf908300320.png" width="1846" />
总结
HTTPS 工作过程中涉及到的密钥有三组.
第⼀组 CA的密钥对 (非对称加密): 用于校验证书是否被篡改. CA持有自己的私钥用于证书的数字签名, 客户端持有CA公钥(操作系统包含了可信任的 CA 认证机构有哪些, 同时持有对应的公钥). 服务器在客户端请求时, 返回携带CA签名的证书. 客户端通过CA公钥进行证书验证, 保证证书的合法性, 进⼀步保证证书中携带的服务端公钥权威性.
第⼆组 服务器的密钥对(非对称加密): 用于协商生成对称加密的密钥. 客户端用收到的CA证书中的服务器公钥(是可被信任的)给随机生成的对称加密的密钥加密, 传输给服务器, 服务器通过自己的私钥解密获取到对称加密密钥.
第三组 (对称加密): 客户端和服务器后续传输的数据都通过这个对称密钥加密解密.
其实⼀切的关键都是围绕这个对称加密的密钥. 其他的机制都是辅助这个密钥⼯作的.
第⼀组非对称加密的密钥是为了让客户端拿到第二组非对称加密的公钥.
第⼆组非对称加密的密钥是为了让客户端把这个对称密钥传给服务器.