前面我们已经了解HTTP协议,HTTP基于明文传输,客户端与服务器之间所有请求响应数据都是裸文直接在网络上传输。数据在经过路由器、代理服务器时很容易被窃听、篡改,账号密码、会话信息等敏感数据存在泄露风险,因此诞生了HTTPS。
一、加密与解密
在学习https协议之前,我们先要了解一组概念,叫做加密与解密
加密就是把明文 (要传输的信息) 进行一系列变换,生成密文。
解密就是把密文 再进行一系列变换,还原成明文。
在这个加密和解密的过程中,往往需要一个或者多个中间的数据,辅助进行这个过程,这样的数据称为密钥。
1.1 为什么要对数据做加密
对数据加密是为了将明文转换为密文,避免数据在传输、存储过程中被窃取、篡改,限制未授权人员查看敏感信息,例如常见的运营商劫持会擅自篡改未加密的网络流量,植入广告、跳转恶意页面,而加密(如 HTTPS)可让传输内容变为密文,运营商无法读取、修改数据,能有效抵御此类风险,保护个人隐私与企业核心资料,同时满足网络安全、个人信息保护相关法规合规要求,降低数据泄露带来的损失。
1.2 常见的加密方式
对称加密
对称加密采用单钥密码系统的加密方法,同一个密钥可以同时用于信息的加密和解密,也叫单密钥加密,核心特征是加密和解密所用的密钥是相同的。
常见算法:DES、3DES、AES、TDEA、Blowfish、RC2 等
特点:算法公开、计算量小、加密速度快、加密效率高
核心原理:通过同一个 "密钥",把明文加密成密文,也能把密文解密成明文。
非对称加密
非对称加密需要两个密钥完成加密解密:公钥(公开密钥 public key)、私钥(私有密钥 private key),公钥与私钥成对配对。
常见算法 RSA、DSA、ECDSA(了解)
特点:算法逻辑复杂,安全性高。但其加密解密速度慢,远慢于对称加密。
非对称加密有两种使用方式:
方式一(加密通信)
使用公钥加密明文得到密文,再用私钥解密密文得到明文。使用私钥进行解密,能进行解密的人非常少。
这种方式适用于需要保证数据机密性的场景。发送方使用接收方的公钥对数据进行加密,由于公钥是公开的,任何人都可以获取,但只有持有对应私钥的接收方才能解开密文。即使密文在传输过程中被第三方截获,由于第三方没有私钥,也无法还原出明文内容。典型应用包括 HTTPS 握手过程中的密钥交换、电子邮件加密传输等。
方式二(数字签名,反向使用)
使用私钥加密明文得到密文,再用公钥解密密文得到明文。这种方式只有持有私钥的人才能对数据进行加密。
这种方式与方式一正好相反,私钥加密、公钥解密,其核心目的不再是保证机密性,而是验证数据的完整性和来源真实性。由于私钥只有发送方自己持有,用私钥加密后的数据,任何持有公钥的人都能解开验证,从而确认这份数据确实来自私钥持有者,且内容在传输过程中没有被篡改。典型应用包括数字签名、软件发布时的完整性校验、身份认证等场景。
1.3 数据摘要
数字指纹 (数据摘要),其基本原理是利用单向散列函数 (Hash 函数) 对信息进行运算,生成一串固定长度的数字摘要。数据摘要有个典型特征:两份完全相同的数据,用同一个散列函数计算,只要其中一份数据发生微小改动,哪怕只修改一个比特位,最终生成的数据摘要都会截然不同。所以数字摘要虽然并不是一种加密机制,但可以用来判断数据有没有被篡改。
摘要常见算法:有 MD5、SHA1、SHA256、SHA512 等,算法把无限的映射成有限,因此可能会有碰撞(两个不同的信息,算出的摘要相同,但是概率非常低)
摘要特征:和加密算法的区别是,摘要严格意义不是加密,因为没有解密,只不过从摘要很难反推原信息,通常用来进行数据对比。
数据摘要应用案例
案例一:网盘的秒传机制
数据摘要最典型的落地场景就是网盘的秒传机制。用户甲先把视频《战狼》上传到百度云盘。云盘服务器接收文件后,使用散列(Hash)算法对完整文件计算,生成唯一的数据摘要,同时把原始文件保存在服务器存储池中,并记录该摘要与文件的对应关系。
李四本地也拥有一份完全一样的《战狼》文件,现在李四想要把这份文件上传到自己的网盘账户。李四的网盘客户端,就会在本地使用和服务器完全相同的散列算法,对本地的《战狼》文件运算,生成数据摘要。然后将这个摘要传递到百度云盘。百度云盘服务器拿到这部分摘要,去存储记录中做匹配搜索。不需要上传完整文件数据。
如果搜索到数据库中已经存在该摘要,代表服务器已经保存过这份完全相同的文件。服务器不需要接收文件本体,直接在李四的账户下创建文件索引,关联到已经存在的那份原始文件。对李四来说,文件瞬间就 "上传完成",也就是秒传。如果数据库找不到对应摘要,说明服务器没有这份文件,此时才会真正接收李四客户端上传的完整文件,计算摘要并存入服务器。
案例二:数据库中的用户密码存储
在网站后台存储用户密码,不推荐直接在数据库存放明文密码(例如直接保存123456到数据库中),一旦数据库泄露,所有用户的原始密码会直接暴露。所以当用户进行注册操作时,需要把用户提交的密码通过散列算法形成数据摘要,再保存到数据库中。下一次用户要进行登录操作时,将用户本次输入的密码再通过散列算法形成数据摘要。再将本次形成的数据摘要与数据库中保存的数据摘要进行比对,如果完全相同,则说明用户输入的密码正确;如果不同,说明用户输入的密码不正确。
1.4 数据签名
当我们对数据摘要进行加密,得到的就是数据签名。
二、HTTPS是什么
HTTPS并不是全新协议,它是HTTP + TLS/SSL的组合。

当客户端使用https协议向服务器端传输http请求时,会先经过SSL或TLS对明文信息进行加密操作,然后加密后的数据到达服务器之后,再由服务器端的TSL进行解密,然后得到解密后的明文数据。这样一来,数据在网络传输过程中,即便经过路由设备或链路被抓包拦截,攻击者也无法获取到账号密码等敏感信息。
三、HTTP的工作过程
方案一:只使用对称加密
由于数据是再客户端进行加密,所以就需要有一个客户端密钥。但是服务器端如何拿到这个密钥呢?如果直接以http 请求的形式传输,就会被中间人获取。所以方案一只使用对称加密是不具备可行性的!
方案二:只使用非对称加密
假设服务器端有一对公私钥。鉴于非对称加密的机制,如果服务器先把公钥以明文方式传输给浏览器,之后浏览器向服务器传数据前都先用这个公钥加密好再传,从客户端到服务器信道似乎是安全的 (其实有安全问题),因为只有服务器有相应的私钥能解开公钥加密的数据。
但是服务器到浏览器的这条路怎么保障安全?
如果服务器用它的私钥加密数据传给浏览器,那么浏览器用公钥可以解密它,而这个公钥是一开始通过明文传输给浏览器的,若这个公钥被中间人劫持到了,那他也能用该公钥解密服务器传来的信息了。
所以只使用非对称加密,只有浏览器端到服务器单向的数据是安全的(貌似是安全的,但其实存在安全问题),服务器端向浏览器进行数据传输是不安全的。其次整个过程中只使用非对称加密,通信速度非常慢。
方案三:双方都使用非对称加密
客户端和服务器端都有自己的一对公钥和私钥。当客户端与服务器端要进行数据传输前,客户端先将自己的公钥发送给服务器端,服务器端接收到之后再把自己的公钥发送给客户端。这样双方都收到了对方的公钥。接着客户端使用自己的私钥对明文进行加密处理,然后发送给服务器端,服务器端接收到密文之后,使用客户端的公钥对密文进行解密,就能获取到客户端发过来的信息了。服务器端发送数据给客户端时也类似上述逻辑。
但是这种方案也是不安全的,并且双方都使用非对称加密,通信速度也非常慢。
方案四:非对称加密+对称加密
服务端具有非对称公钥S和私钥S'。首先客户端发起https请求,获取服务端公钥S。然后客户端在本地生成对称密钥C,通过公钥S加密,发送给服务器。由于中间的网络设备没有私钥,即使截获了数据,也无法还原出内部的原文,也就无法获取到对称密钥 。
服务器通过私钥S' 解密,还原出客户端发送的对称密钥 C。并且使用这个对称密钥加密给客户端返回的响应数据。
后续客户端和服务器的通信都只用对称密钥C来进行对称加密即可。由于该密钥只有客户端和服务器两个主机知道,其他主机 / 设备不知道密钥即使截获数据也没有意义。
由于对称加密的效率比非对称加密高很多,因此只是在开始阶段协商密钥的时候使用非对称加密,后续的传输仍然使用对称加密。
但是方案2/3/4都存在一个共同的安全问题------中间人攻击
四、中间人攻击
Man‑in‑the‑MiddleAttack,简称 "MITM 攻击"(中间人攻击)
确实,在方案 2/3/4 中,客户端获取到公钥 S 之后,对客户端形成的对称密钥 X 用服务端给客户端的公钥 S 进行加密,中间人即使窃取到了数据,此时中间人确实无法解出客户端形成的密钥 X,因为只有服务器有私钥 S'。
但是中间人的攻击,如果在最开始握手协商的时候就进行了,那就不一定了。假设中间人具有非对称加密算法的公钥M,私钥M'。当客户端向服务器发起请求时,服务器明文传送公钥S给客户端。此时再数据传送过程中,中间人劫持了数据报文,提取公钥S并保存好,然后将被劫持报文中的公钥S替换成为自己的公钥 M,并将伪造报文发给客户端。
客户端收到报文,提取公钥M (客户端当然并不知道公钥被更换过了),自己形成对称密钥X,用公钥M加密 X,并形成报文发送给服务器。这个报文被中间人劫持后,直接用自己的私钥M' 进行解密,得到通信秘钥X,再用曾经保存的服务端公钥S加密后,将报文推送给服务器。
服务器拿到报文,用自己的私钥S' 解密,得到通信秘钥X。双方开始采用X进行对称加密,进行通信,但是这一切都在中间人的掌握中。后续中间人可以劫持数据,进行窃听甚至修改数据。
上面的中间人攻击方案,同样适用于方案 2,方案 3。
那为什么会出现这种问题呢?
原因在于,客户端无法甄别自己收到的含有公钥的数据报文,就是目标服务器发送过来的!
五、CA证书与签名
我们可以对一份原始数据进行散列化,得到散列值。然后使用签名者的私钥对散列值进行加密,得到数据签名。再将数据签名与数据结合起来,得到数字签名的数据。当我们需要验证数据是否被篡改过时,可以提取数字签名的数据中签名,并使用公钥进行解密,得到原始散列值。然后我们对数据使用同样的散列算法进行散列化得到新散列值。然后对比新旧散列值,如果新散列值与原始散列值相等,说明签名有效。

数据签名的签名权限仅属于签名方。由于只有签名者持有可对散列摘要进行加密的私钥,故而只有签名者能够生成合法的数据签名。而这里的签名者我们称之为CA机构。
5.1 CA证书
服务端在使用HTTPS之前,需要向CA 机构(数字证书认证机构)申领一份数字证书,这份证书就叫做CA证书。证书里包含证书申请者信息、服务端的公钥信息等内容。在通信握手阶段,服务器会把这份数字证书传输给浏览器,浏览器从证书中提取服务端的公钥使用。
数字证书的作用类似身份证,用来证明服务端公钥的权威性,防止公钥被中间人篡改、替换,避免中间人攻击。
数字证书包含两部分内容,一是明文信息,二是签名。这里的明文信息就相当于前面所说的原始数据,而为了防止明文信息被篡改,于是添加了签名。
当我们要对CA证书进行验证时,首先先将明文信息和签名分离,然后使用CA公钥对签名进行解密得到摘要A,再在本地将明文信息进行散列化得到摘要B,如果摘要A=摘要B则说明证书是有效的,也就是明文信息没有被篡改过。

服务器端生成自身公私钥对,构造不含私钥的证书请求文件CSR并提交至CA证书机构完成证书申请。CA机构会对申请者身份信息进行合法性审核,然后提取证书明文信息并计算其哈希摘要,利用CA自身私钥对该摘要执行签名运算,生成具备法律效力的数字证书并下发至服务器。
客户端获取服务器传输的数字证书后,调用CA公钥对证书签名进行解密以获取原始摘要,同时对证书明文信息重新计算哈希摘要,完成摘要比对校验,同步核验证书域名、有效期限及吊销状态。
当全部校验项通过后,客户端就能信任证书中封装的服务器公钥,进而完成后续会话密钥协商流程,建立安全通信链路。
由于客户端是从证书中提取出的公钥,也就是说,只要证书是合法的,那么公钥就是合法的、可信的,这样就能解决中间人攻击的问题。
而所有的浏览器(客户端),一般都会内置可信的CA机构或其授权的子机构的公钥。如果缺少这套预置根公钥体系,客户端就没办法完成对CA签名的解密与证书合法性验证。
5.2 最终实现方案
方案5-非对称加密 + 对称加密 + 证书认证
在客户端和服务器刚一建立连接的时候,服务器会给客户端返回一个证书,证书包含了之前服务端的公钥,也包含了网站的身份信息。接着客户端会对该证书进行合法性校验,验证通过后提取证书内的服务端公钥。
然后客户端会生成随机会话密钥,使用服务端公钥对会话密钥进行非对称加密并发送至服务端,服务端利用自身私钥解密得到会话密钥。在后续的通信过程中,通信双方都采用客户端提供的会话密钥并通过对称加密的方式对业务数据进行加密传输。这样在后续数据的传输中,传输速率就大大提高了。