目录
[HTTPS 的工作过程探究](#HTTPS 的工作过程探究)
https 也属于应用层的协议,并且位于 http 之上,由于 http 通信时数据是明文传送的,因此很容易造成数据泄露或者被篡改的结果,因此引入了 https,https 是在 http 基础上加了加密层的安全通信协议,通过 SSL/TLS 协议对传输数据加密并验证服务器身份,防止信息被窃听或篡改!

相关概念
什么是加密
加密就是把 明文 (要传输的信息) 进行一系列变换,生成 密文。
解密就是把 密文 再进行一系列变换,还原成 明文。
在这个加密和解密的过程中,往往需要一个或者多个中间的数据,辅助进行这个过程,这样的数据称为 密钥。
为什么要加密
比如用户要在浏览器中下载一个千千动听软件,发起了 http 请求,从千千动听服务器上获取下载链接,但是用户发出去的所有报文都是要经过运营商路由器的,如果是明文传输,那么中间设备就能直接能看到下载链接是 www.tiantiandongting.com,就可以对数据进行侦听或者篡改,把下载链接篡改成 www.qq.com,用户想下载天天动听,最后却下载了个qq!

不止运营商可以劫持,各种中间人包括黑客都能劫持用户的报文,因此明文传送数据是非常不安全的,因此需要对数据进行各种方案的加密!
常见加密方式
对称加密
-
采用单钥密码系统的加密方法,同一个密钥可以同时用作信息的加密和解密,这种加密方法称为对称加密,也称为单密钥加密,特征:加密和解密所用的密钥是相同的
-
常见对称加密算法(了解):DES、3DES、AES、TDEA、Blowfish、RC2等
-
特点:算法公开、计算量小、加密速度快、加密效率高
对称加密其实就是通过同一个"密钥",把明文加密成密文,并且也能把密文解密成明文。
举一个简单的数学例子:
int a = 10,我们要将 a 变量 发送给对方,直接发送不安全,需要加密,于是 int b = 20,b 就是密钥,我们采用的加密方式是给 a 按位异或 b,int temp = a ^ b,将 temp 发送给对方,对方收到 temp 后,使用同一个密钥 b 进行解密,temp ^ b = (a ^ b) ^ b = a ^ b ^ b = a,于是就解密成功,得到了原始数据!因此对称加密就是加密和解密使用的是同一个密钥!
非对称加密
-
需要两个密钥来进行加密和解密,这两个密钥是 公开密钥 (public key,简称公钥)和私有密钥(private key,简称私钥)。
-
常见非对称加密算法(了解):RSA、DSA、ECDSA
-
特点:算法强度复杂、安全性依赖于算法与密钥,但是由于其算法复杂,而使得加密解密速度没有对称加密解密的速度快。
非对称加密要用到两个密钥,一个叫做"公钥",一个叫做"私钥"。公钥和私钥是配对的。最大的缺点就是 运算速度非常慢,比对称加密要慢很多。
-
通过公钥对明文加密,变成密文
-
通过私钥对密文解密,变成明文
也可以反着用
-
通过私钥对明文加密,变成密文
-
通过公钥对密文解密,变成明文
非对称加密的数学原理比较复杂,涉及到一些数论相关的知识。这里举一个简单的生活上的例子。
A 要给 B 一些重要的文件,但是 B 可能不在。于是 A 和 B 提前做出约定:
B 说:我桌子上有个盒子,然后我给你一把锁,你把文件放盒子里用锁锁上,然后我回头拿着钥匙来开锁取文件。
在这个场景中,这把锁就相当于公钥,钥匙就是私钥。公钥给谁都行(不怕泄露),但是私钥只有 B 自己持有。持有私钥的人才能解密。
数据摘要/数据指纹
数据摘要(数据指纹),其基本原理是利用单向散列函数(Hash函数)对信息进行运算,生成一串固定长度的数据摘要。数据指纹并不是一种加密机制,但可以用来判断数据有没有被篡改。
摘要常见算法:有MD5、SHA1、SHA256、SHA512等,算法把无限的映射成有限,因此可能会有碰撞(两个不同的信息,算出的摘要相同,但是概率非常低)。
摘要特征:和加密算法的区别是,摘要严格意义不是加密,因为没有解密,只不过从摘要很难反推原信息,通常用来进行数据对比。

如图所示,只要原始数据发生了一点点变化,使用同一个散列函数得到的散列值就可能差别非常大,客户端发数据给服务器的时候携带上原始数据、散列函数和散列值,服务器收到了之后,对原始数据使用散列函数计算出散列值,和报文携带的散列值对比是否相等,这样服务器就能识别客户端传来的数据有没有被篡改!
数据摘要有啥应用场景呢?这里举两个具体的例子:
场景一:百度网盘的妙传功能
可能有成千上万的用户要将本地的《功夫》电影上传到百度网盘,但有了数据摘要,实际只有第一个人上传时候需要真正将文件传输到网盘内部,剩下的所有人传递时发现要上传的电影形成的数据摘要在网盘内部已经存在了,就不需要再传了,百度网盘内部只需要保存一份该资源即可,这就是"妙传"功能!所以百度网盘做的更多的工作其实是"搜索"!
场景二:数据库密码的保存工作

HTTPS 的工作过程探究
方案一:只使用对称加密
如果通信双方都各自持有同一个密钥X,且没有别人知道,这两方的通信安全当然是可以被保证的(除非密钥被破解),引入对称加密之后,即使数据被截获,由于黑客不知道密钥是啥,因此就无法进行解密,也就不知道请求的真实内容是啥了。
但事情没这么简单。服务器同一时刻其实是给很多客户端提供服务的。这么多客户端,每个人用的秘钥都必须是不同的(如果是相同那密钥就太容易扩散了,黑客就能也拿到了)。因此服务器就需要维护每个客户端和每个密钥之间的关联关系,这也是个很麻烦的事情

理想的做法是客户端和服务器在建立连接的时候,就协商确定密钥是多少,而如果直接将密钥明文传送,那么黑客就直接获得密钥了,密钥的存在就没有意义了,因为黑客也能解密!因此还要再对密钥进行加密,此时就变成了鸡生蛋、蛋生鸡的问题了,就无穷无尽了~
方案二:只使用非对称加密
服务器端生成一对公钥和私钥,正式发数据通信前,客户端先发起 http 请求,服务器响应 http 应答时,将公钥p传递客户端!
客户端 到 服务器:
客户端拿到公钥之后,从今往后往服务器发送消息时,都使用公钥p对原始数据加密,而这个世界上只有服务器持有私钥s,因此只有服务器能够解密!目前来看从客户端到服务器貌似是安全的!

服务器 到 客户端:
服务器给客户端发送数据,也要对数据进行加密,只能使用私钥加密!因为如果使用公钥加密,客户端是没有私钥的,是无法解密的!使用私钥加密后,将加密数据发送到网络中,此时被中间人拿到了,公钥是可以被中间人获取的,因此中间人直接使用公钥解密了,造成数据被侦听或者篡改!
该方案的两个问题:
-
只有一个通信方向上是安全的!
-
非对称加密运算速度非常慢!
方案三:双方都使用非对称加密
开始时,客户端和浏览器各自持有一对公钥和私钥,正式发送数据前,先进行公钥的交换!然后客户端就持有了服务器的公钥,服务器就持有了客户端的公钥。
从此往后客户端向服务器发送数据时,使用服务器的公钥s对数据加密,这个世界上只有服务器持有私钥s'能对加密数据解密,因此从客户端到服务器是安全的!
从此往后服务器向客户端发送数据时,使用客户端的公钥c对数据加密,这个世界上只有客户端持有私钥c'能对加密数据解密,因此从服务器到客户端是安全的!

该方案的两个问题:
-
其实也不是安全的
-
非对称加密运算速度非常慢!
方案四:非对称加密+对称加密
服务器先生成一对公钥s和私钥s',然后将公钥 s 交给客户端,客户端在自己本地形成对称密钥x,这个对称密钥只有客户端自己知道,然后使用公钥 s 对对称密钥进行加密,将密文数据 XXXX 发送给服务器,因为只有服务器持有私钥s',中间人无法解密,服务器使用私钥s'解密,就得到了客户端形成的对称密钥X,从此往后双方通信使用对称加密即可!

这种方案下对称密钥X只有客户端和服务器双方知道,中间人是不知道的,因此中间人截获数据也没有任何意义!
由于对称加密的效率比非对称加密高很多,因此只是在开始阶段协商密钥的时候使用非对称加密,后续的传输仍然使用对称加密,解决了安全通信的效率问题!
虽然上面已经比较接近答案了,但是依旧有安全问题,方案2,方案3,方案4都存在一个问题,如果最开始,中间人就已经开始攻击了呢?
中间人攻击
在最开始非对称加密时,服务器将自己的公钥s传递给客户端,此时中间人直接截获了公钥s,然后提前在自己内部生成了一对公钥m和私钥m',然后直接将服务器的公钥s替换成自己的公钥m,发送给了客户端,客户端收到之后,并不知道公钥已经被替换了,依旧使用公钥m对自己的对称密钥x进行加密,形成密文数据 xxxxx,发送给服务器,密文数据依旧先被中间人获取!中间人直接使用私钥m'进行解密,直接就得到了 对称密钥 x,然后使用之前截获到的服务器公钥 s 对 x 加密,得到加密数据 yyyyyy,发送给服务器,服务器使用 私钥 s' 进行解密,得到了 对称密钥x,从此往后双方使用 x 对称加密通信,但客户端和服务器双方都不知道,中间人也是知道 对称密钥 x 的,所有的加密数据对中间人来说都可以随便解密!!

方案2-方案4的问题本质就是:客户端无法识别服务器发来的公钥 s 是否是合法的,因此只要解决了这个问题,方案四就是正确答案了!
方案五:非对称加密+对称加密+证书认证
数据签名
上文介绍了数据摘要/数据指纹,用签名者的私钥 Q' 对散列值加密,得到的数据就叫做数据签名!将数据签名和原始数据直接拼接到一起,就形成了携带数据签名的新数据!!
如何验证原始数据是否被篡改了呢?
直接从新数据中提取出原始数据和数据签名,对原始数据使用相同的散列函数计算出散列值,然后用签名者的公钥 Q 对签名数据进行解密,得到散列值,对比两个散列值是否相等,相等说明原始数据没有被篡改,否则原始数据发生了篡改!

那要是有中间者对数据进行了篡改了呢?得到的散列值肯定发生了变化,但是中间者用自己的密钥m进行加密,然后接收者用m'进行解密呢?最终两个散列值也是相等的呀??
这种情况是不可能发生的!因为接收数据方都必须内置式的使用签名者的公钥 Q 进行解密,他们是不认其他公钥的,也不会其他公钥解密的!而这个世界上只有签名者持有私钥Q',也就意味着只有签名者有对数据进行签名的能力,这是一种权力,谁持有大家都公认的私钥对应的公钥,谁就能签名的能力!而在 https 通信中,签名者就是CA机构,CA机构签发的数字身份凭证就是CA证书!
CA证书
CA机构(Certificate Authority)即证书授权中心,是网络安全中负责签发和管理数字证书的受信任第三方权威机构**,**核心职能就是验证网络实体身份,颁发包含公钥和身份信息的数字证书,确保证书真实性与完整性,支撑 HTTPS 加密、电子签名等安全服务!CA顶层机构包括下面授权的子机构都是具有证书授权和签发的权利的!
服务端在使用HTTPS前,需要向CA机构申领一份数字证书,数字证书里含有证书申请者信息、公钥信息(该公钥就是服务器自己的公钥s,将来要发送给客户端的)等。服务器把证书传输给浏览器,浏览器从证书里获取公钥就行了,证书就如身份证,证明服务端公钥的权威性!

具体过程如下:
-
服务器在内部形成一对公钥 S 和私钥 S',申请数据签名证书者(比如公司项目负责人)向CA机构提交 公钥、域名、申请者等一系列信息!
-
CA机构有自己的一对公钥 A 和私钥 A',服务器提交的一系列信息就是原始数据,对原始数据散列,对散列值使用 A' 加密形成数据摘要,然后和原始数据拼接在一起,就形成了数据签名证书
-
将数据签名证书颁发给申请者,申请者将该证书!
-
服务器发回浏览器客户端的http响应正文就不只是一个公钥 S 了,而是携带数据签名的证书!!
-
浏览器客户端收到后要对证书进行验证,验证方法就是上文讲解数据签名时的做法,先提取出原始数据和数据签名部分,然后对数签名部分使用公钥 A(所有的浏览器一般都要内置CA机构或者其授权的子机构的公钥) 进行解密,对原始数据做哈希散列,对比两个结果是否相等,不相等直接将报文丢弃!
-
如果相等,浏览器客户端再和 server 开辟对称密钥协商的过程!

因此有了证书认证,客户端就能够识别 server 发来的公钥 s 有没有被篡改过了!!
细节问题
1. 中间人对证书篡改了怎么办?
中间人只要对证书进行了篡改,浏览器客户端通过公钥A解密出的数据摘要和原始数据不相等,直接就能判断出证书被篡改了,直接丢弃!
2. 中间人使用自己的私钥对证书的原始数据重新哈希、加密了怎么办?
中间人可以使用自己的私钥对证书的原始数据重新哈希,并加密,但是没用的!浏览器客户端提前内置了CA机构的公钥A,浏览器只认公钥A,被重新哈希加密的数据浏览器也解不了密,没有任何意义的!!
3. 中间人也去CA机构申请了真正的CA证书,直接替换掉服务器发给客户端的证书怎么办?
中间人确实可以去CA机构也申请一份CA证书,但是证书中除了公钥信息外,还有域名信息,客户端本来请求的是 www.qq.com,结果最终浏览器返回的是 www.baidu.com,客户端直接就通过域名识别出来是有问题的!其次,中间人并不想让自己的信息直接被暴露了,因此,一般中间人不会主动去申请CA证书的!
4. 为啥还要对数据摘要加密,直接使用数据摘要不行吗?
如果只对原始数据进行哈希,形成散列值,和原始数据拼接形成证书,那么中间人直接篡改原始数据,并重新哈希计算结果,最终将证书中的原始数据和散列值都替换了,发送给客户端,客户端压根不知道这些数据都发生了变化!
5.为啥不直接对原始数据加密,而是先形成数据摘要,再进行加密?
有可能原始数据比较长,先形成数据摘要,可以缩小签名密文的长度,加快数字签名的验证签名的运算速度!
总结
HTTPS 工作过程中涉及到的密钥有三组。
第一组(非对称加密): 用于校验证书是否被篡改。服务器持有私钥(私钥在形成CSR文件与申请证书时获得),客户端持有公钥(操作系统包含了可信任的 CA 认证机构有哪些,同时持有对应的公钥)。服务器在客户端请求时,返回携带签名的证书。客户端通过这个公钥进行证书验证,保证证书的合法性,进一步保证证书中携带的服务端公钥权威性。
第二组(非对称加密): 用于协商生成对称加密的密钥。客户端用收到的CA证书中的公钥(是可被信任的)给随机生成的对称加密的密钥加密,传输给服务器,服务器通过私钥解密获取到对称加密密钥。
第三组(对称加密): 客户端和服务器后续传输的数据都通过这个对称密钥加密解密。
其实一切的关键都是围绕这个对称加密的密钥。其他的机制都是辅助这个密钥工作的。
-
第二组非对称加密的密钥是为了让客户端把这个对称密钥传给服务器。
-
第一组非对称加密的密钥是为了让客户端拿到第二组非对称加密的公钥。