前言
之前我们已经给大家介绍了HTTP协议以及它的Cookie,Session等概念,谈论到了HTTP的局限性就是安全性存在严重不足,虽然我们有着Session与Cookie为传输信息的安全做了一个补偿,但是在实际中,仍然存在较大的风险。
尤其是我们以POST方式进行信息传输时,我们的信息虽然存储在正文,但是仍然可以被各种软件所获取,而获取到的内容,是可以直接看到我们的正文的。因为HTTP协议的内容,都是按照文本的方式进行铭文传输的。
而所谓的HTTPS,就是在HTTP协议的基础上,再加了一个加密层。
那么今天我们就继续来学习一下HTTPS原理,看我们的HTTPS是如何解决这个安全问题的。
HTTPS协议概念理解
什么是加密解密
加密就是把 明文 (要传输的信息)进行一系列的变换,生成密文。
解密就是把密文 再进行一些列的变换,还原成明文
在这个加密和解密的过程中,往往需要一个或多个中间的数据,辅助进行这个过程,这样的数据我们称为密匙
我们为什么要进行加密呢
大家听说过运营商劫持吗?
就是当我们在浏览器中点击一个下载链接,比如说是下载QQ音乐。正常的来说,我们的下载效果应该是点击下载链接后,浏览器就会开始给我们下载QQ音乐。但如果我们的通过网络传输的数据包,经过运营商的网络设备(路由器,交换机等),那么运营商的网络设备就可以解析出我们传输的内容,并进行篡改。
所以就会强制让我们下载应用宝啊,或者其他运营商想让你下载的软件。
HTTP的内容都是明文传输的,明文数据会经过路由器、WiFi热点、通信服务运营商、代理服务器等多个物理节点,如果信息在传输过程中被劫持,传输的内容就完全暴露了。劫持者可以篡改传输的信息且不被双方察觉,这就是中间人攻击,所以我们才需要对信息进行加密。
并且不止运营商可以劫持,其他的黑客也可以用类似的手段来进行劫持,用来窃取用户的私密信息,或者篡改内容。
所以我们需要对传输的数据进行加密。
常见的加密方式
我们主要有两种加密方式:对称加密与非对称加密
对称加密
对称加密采用单匙密码系统的方法,同一个密匙可以同时用作信息的加密与解密,这种加密方法称为对称加密,也被称为单密匙加密。他的最主要特征就是加密和解密所用的密匙是相同的
常见的对称加密的算法有(了解一下就行):DES,3DES,AES,TDEA等。
特点:算法公开,计算量小,加密速度快,加密效率高。
对称加密之所以叫对称加密,是因为它的加密与解密是通过同一把密匙,通过这个密匙,可以把明文加密成密文,也可以把密文解密成明文。
非对称加密
需要有两个密匙来进行加密与解密,这两个密匙,一个是公开的密匙,简称公匙 ,另外一个是私有密匙,简称私匙。
常见非对称算法有:(仅了解)RSA,DSA,ECDSA等。
特点是:算法强度高,安全性依赖于算法与密匙,但是由于其算法复杂,使得其加密速度没有对称加密解密快。
为什么要用两把密匙呢?对称加密与非对称加密有什么区别呢?
首先,对称加密需要通信双方都知道那个唯一的密匙,这是他们两个加密解密的前提条件。
而非对称加密由于有两个密匙,所以加密解密的方法多种多样。
我们既可以通过公匙对明文进行加密变成密文,随后用私匙将密文解密成明文。
也可以先通过密匙将明文加密为密文,然后加密文解密为明文。
非对称加密的数学原理比较复杂,涉及到一些到数论相关的知识忙着哩举一个最简单的生活上的例子:
A要给B一些重要文件,但是B可能不在,于是A和B提前作出约定:
B说:我桌子上有一个盒子,然后我给你一把锁,你把文件放盒子里用锁锁上,然后我回头拿着钥匙开锁取文件。
在这个场景中,这把锁就相当于公匙,钥匙就是私匙,公匙给谁都可以,随便一个人都可以去锁上,但是私匙只有B自己持有,持有私匙的人才能进行解密操作。
数据摘要与数字签名
数据摘要是什么呢?
数据摘要 ,也常被称为哈希值 或数字指纹 ,是一段数据(比如一个文件、一段文字、一部电影)经过一种特殊数学函数计算后,得到的一串固定长度的、唯一的"身份证号码"。
数字指纹并不是一种加密机制,但可以用来判断数据有没有被篡改。
本质上是对一个大文件,以哈希类算法的方式提取出一个固定长度的摘要,且保证,如果大文件中哪怕一个字节被改了,那么同样算法得出的结果绝对不同。
这个一般用于检验文件有无被改过,两边用同一算法对同一文件取摘要对比结果即可。
数据摘要的核心特性(为什么它有用?)
产生数据摘要的数学函数叫哈希函数。一个优秀的哈希函数必须具备以下三个特点:
-
确定性
-
含义 :相同的输入 ,无论计算多少次,永远产生相同的输出。
-
例子 :字符串 "Hello" 的SHA-256摘要永远是
185f8db32271...
。你今天算、明天算、在北京算、在纽约算,结果都一样。
-
-
极快的计算速度
-
含义:从原始数据计算出摘要的速度非常快。
-
例子:计算一个1GB文件的摘要可能在秒级内完成。
-
-
单向性(不可逆)
-
含义 :这是最重要的特性!无法通过摘要(输出)反推出原始数据(输入)。这个过程是单向的。
-
例子 :你看到摘要
185f8db32271...
,你无法知道原始数据是 "Hello" 还是别的什么。就像你无法从一盘菜的香味完美还原出它的完整食谱。
-
-
雪崩效应
-
含义 :原始数据哪怕只做一个微小的修改 (比如改变一个比特位),产生的摘要也会发生巨大的、无法预测的变化,新的摘要和旧的摘要看起来完全不相干。
-
例子:
-
"Hello" 的摘要:
185f8db32271fe...
-
"Hella" 的摘要:
b4c3e...
(完全不同!)
-
-
-
抗碰撞性
- 含义:很难找到两个不同的原始数据,但它们计算出的摘要却相同。对于安全的哈希算法(如SHA-256),发生这种情况的概率低到在现实中可以忽略不计。
常见的数据摘要算法
-
MD5 : 产生128位摘要。现已不安全,可以被人工制造碰撞,不再用于安全用途,但仍可用于校验文件完整性(比如检查文件下载是否出错)。
-
SHA-1 : 产生160位摘要。同样已被破解,各大公司和技术团体已弃用。
-
SHA-256 : 属于SHA-2家族,产生256位摘要。这是目前最广泛使用和信任的标准算法,广泛应用于SSL/TLS证书、区块链(比特币)等领域。
-
SHA-3: 新一代标准,设计上与SHA-2不同,提供了另一种选择。
数据摘要的实际应用
-
验证数据完整性
-
场景:从网上下载一个大型软件或系统镜像(如Windows安装盘ISO)。
-
用法 :官方网站通常会提供该文件的SHA-256摘要。你下载完文件后,可以用自己的工具计算文件的摘要,然后与官方的对比。
-
结果 :如果两个摘要完全一致 ,证明文件100%完整,没有在下载过程中损坏,也未被黑客篡改。不一致则说明文件有问题。
-
-
密码存储
-
场景 :你在网站注册账号,输入密码
myPassword123
。 -
用法 :安全的网站绝不会 明文存储你的密码。它只会存储你的密码的摘要,比如
SHA256("myPassword123")
。 -
结果:当你下次登录时,网站对你输入的密码再次计算摘要,并与数据库里存储的摘要对比。相同则登录成功。这样即使数据库泄露,黑客拿到的也只是一串串摘要,极难反推出你的原始密码。
-
-
数字签名和SSL证书(HTTPS的核心)
- 数字签名并不是直接对一大段数据签名,而是先对数据计算摘要,再对这份摘要进行签名。这样既安全又高效。(这个后面我们会进一步讲数字签名,证书)
HTTPS的前四个方案
我们刚刚给大家讲了HTTPS的两个加密方式,对称加密与非对称,那么我们就有几种方案可以进行信息的通信呢?
只使用对称加密
首先我们来试试第一方案:只使用对称加密
如果通信双方都各自持有同一个密钥K,且没有别人知道,这两方的通信安全当然是可以被保证的(除非密钥被破解)

并且由于我们使用的是对称加密,整个加密与解密的过程十分迅速,但是这个具有一个很致命的缺点
对称加密的前提是通信双方必须拥有相同的密钥。那么问题来了:在第一次通信中,如何把这个密钥安全地告诉对方?
想象一下,你要和一个陌生人通过明信片通信,但你们约定好以后都用一种密码写信。你首先得把密码本寄给他吧?但如果你把密码本直接用明信片寄过去,邮递员(攻击者)不就能看到密码本了吗?这就是"密钥分发"困境。
但是如果直接把密钥明文传输,那么黑客也就能获得密钥了,此时后续的加密操作就形同虚设了.
因此密钥的传输也必须加密传输**!
但是要想对密钥进行对称加密,就仍然需要先协商确定一个"密钥的密钥".这就成了"先有鸡还是先有蛋"的问题了.此时密钥的传输再用对称加密就行不通了.
只使用非对称加密
我们说一个非对称加密,需要一个公匙K,以及一个私匙X,公匙无论泄不泄露,都无所谓,但是私匙绝对不能泄露。
鉴于非对称加密的机制,如果服务器先把公钥以明文方式传输给浏览器,之后浏览器向服务器传数据前都先用这个公钥加密好再传,从客户端到服务器信道似乎是安全的(有安全问题*)**,因为只有服务器有相应的私钥能解开公钥加密的数据。

如图,我们先申请获取公钥,此后公钥就会被发回客户端,此后我们就能通过在客户端进行公钥加密,在服务端进行私钥解密来进行信息交流。
但是服务器到浏览器的这条路怎么保障安全?
如果服务器用它的私钥加密数据传给浏览器,那么浏览器用公钥可以解密它,而这个公钥是一开始通过明文传输给浏览器的,若这个公钥被中间人劫持到了,那他也能用该公钥解密服务器传来的信息了。
并且,由于非对称加密算法(如RSA、ECC)的核心数学运算(如大数质因数分解、椭圆曲线离散对数)非常复杂且耗时, 通信速度极慢,用户体验无法接受。
所以这个只能看似可以,但实际上肯定不会用这种方式。
双方都使用非对称加密
-
服务端 拥有公钥 S 与对应的私钥 S',客户端拥有公钥 C 与对应的私钥 C'
-
交换公钥:客户端和服务器首先互相交换自己的公钥。
-
客户端加密 :客户端要发送消息时,用服务器的公钥加密数据。这样,只有拥有对应私钥的服务器才能解密。
-
服务器加密 :服务器要回复消息时,用客户端的公钥加密数据。这样,只有拥有对应私钥的客户端才能解密。
这个方案确实解决了保密性和身份认证问题,甚至提供了客户端的不可否认性。
尽管在理论上安全,但将其用于所有网站访问(如浏览新闻、看视频)是不现实的。
和之前分析的一样,非对称加密速度慢。现在双向的所有通信都承受这种性能开销,而不仅仅是服务器到客户端。服务器的计算压力更大,客户端的体验也会变得非常卡顿。加载一个现代网页需要数百次请求响应,每次都要进行非对称加密解密,速度是无法接受的。
并且其还有一个更加致命的问题,那就是密钥管理和分发
密匙与公匙的问题不在于服务器,而在于客户端(亿万普通用户)。
-
服务器管理密钥相对简单:一个网站只有一对(或几对)密钥,其公钥通过SSL证书分发。
-
客户端管理密钥极其困难:
-
生成与存储:要求每个互联网用户都生成并安全地保管自己的公私钥对,这对绝大多数非技术用户来说门槛太高。私钥丢失意味着无法登录任何使用此方案的网站。
-
公钥分发:用户如何向网站注册自己的公钥?想象一下,你在每个网站注册时,不仅要输入用户名密码,还要上传一个复杂的公钥文件。网站需要为海量用户存储和管理海量的公钥,这是一个巨大的工程和安全隐患。
-
设备同步:你的密钥对保存在你的电脑上。当你换用手机、平板或者另一台电脑时,如何安全地将私钥迁移过去?这几乎无法实现无缝体验。
-
所以,这个方案也会被我们否定掉。
非对称加密加上对称加密
这个方案是如何工作的呢?
-
首先服务端需要先具有非对称公钥 S 和私钥 S'
-
客户端发起 https 请求,获取服务端公钥 S
-
客户端在本地生成对称密钥 C, 通过公钥 S 加密, 发送给服务器.
-
由于中间的网络设备没有私钥, 即使截获了数据, 也无法还原出内部的原文, 也就无法获取到对称密钥(但其实仍然存在漏洞,没有真正安全的方式)
-
服务器通过私钥 S'解密, 还原出客户端发送的对称密钥 C。并且使用这个对称密钥加密给客户端返回的响应数据.
-
后续客户端和服务器的通信都只用对称加密即可. 由于该密钥只有客户端和服务器两个主机知道, 其他主机/设备不知道密钥即使截获数据也没有意义。
由于对称加密的效率比非对称加密的效率高很多,所以我们在开始阶段协商密匙的时候使用非对称加密,后面的信息传输就只使用对称加密。如此一来,就能解决我们的效率问题。

中间人攻击
我们在现在的https协议中,最长使用的就是我们刚刚说的第四种方案,也就是对称加上非对称加密的方式。
但是这个方式,就是完美的最佳的方式了吗?
并不是这样的,世界上没有绝对安全的加密方式。
我们的第四种方案看似很安全,实际上还是存在漏洞。
客户端获取到公钥 S 之后,对客户端形成的对称秘钥 K 用服务端给客户端的公钥 S 进行加密,中间人即使窃取到了数据,此时中间人确实无法解出客户端形成的密钥 K,因为只有服务器有私钥 S'
但是中间人的攻击,如果在最开始握手协商的时候就进行了,那就不一定了,你凭什么保证你一开始服务端送你的公匙S就一定是服务端给你的?
-
服务器具有非对称加密算法的公钥 S,私钥 S'
-
中间人具有非对称加密算法的公钥 M,私钥 M'
-
客户端向服务器发起请求,服务器明文传送公钥 S 给客户端
-
中间人劫持数据报文,提取公钥 S 并保存好,然后将被劫持报文中的公钥 S 替换成为自己的公钥 M,并将伪造报文发给客户端
-
客户端收到报文,提取公钥 M(自己当然不知道公钥被更换过了),自己形成对称秘钥 X,用公钥 M 加密 X,形成报文发送给服务器
-
中间人劫持后,直接用自己的私钥 M'进行解密,得到通信秘钥 X,再用曾经保存的服务端公钥 S 加密后,将报文推送给服务器
-
服务器拿到报文,用自己的私钥 S'解密,得到通信秘钥 X
-
双方开始采用 X 进行对称加密,进行通信。但是一切都在中间人的掌握中,劫持数据,进行窃听甚至修改,都是可以的
上面的攻击方案,同样适用于方案 2,方案 3,这个就是我们所说的中间人攻击。
那么问题本质出在哪里了呢?
:客户端无法确定收到的含有公钥的数据报文,就是⽬标服务器发送过来的!
CA证书与签名
刚才我们讲到,即使使用了非对称加密,依然无法完全避免中间人攻击。其核心漏洞在于:
客户端(浏览器)无法确认收到的公钥,到底是不是来自真正的目标服务器,还是来自一个伪装的中间人。
这就好比在一个漆黑的房间里,有人对你喊:"我是张三,我的电话号码是138...!" 你无法确定说话的人是不是真张三,还是李四在冒充张三。
为了解决这个"身份认证"的根本问题,我们需要一个在黑暗中所有人都信任的权威公证人 。这个公证人就是证书颁发机构(CA) ,它颁发的"数字身份证"就是CA证书 (通常指SSL/TLS证书)。CA证书的出现,就是为了给网站的公钥提供一个可信的、防篡改的"担保"。
我们之前在上面讲过数字摘要的概念,大家还记得吗?
我们的CA证书就运用的是这个原理,在此之前,我们首先要知道CA的组成部分。
那么,我们的CA证书是怎么样组成的呢?
块一:明文信息(所有人都可以查看)
这部分信息是未加密的,任何拿到证书的人都能直接读取。主要包括:
-
主题(Subject):描述了证书持有者的信息。
-
最重要的一项:通用名称(CN) - 通常就是网站的域名 ,例如
www.google.com
。这是验证"这个证书是给谁的"最关键的依据。 -
可能还包含:组织名称(O)、所在地(L)等。
-
-
公钥信息(Public Key) :这是证书的核心资产,即该网站用于非对称加密的公钥。在HTTPS握手时,客户端就是用这个公钥来加密预备主密钥的。
-
签发者(Issuer) :指明是哪个证书颁发机构(CA) 签发了这张证书,例如 "DigiCert Inc" 或 "Let's Encrypt"。
-
有效期(Validity):证书的生效日期和过期日期。证书不是永久有效的,必须在有效期内使用。
-
序列号(Serial Number):由CA分配的唯一编号,用于管理证书。
块二:数字签名(防伪核心)
这是CA证书的灵魂,是防止篡改和伪造的关键。它不是一段独立的文字,而是一个加密后的结果。
这个签名是如何生成的?(由CA在签发时完成)
-
计算摘要(指纹) :CA使用一个密码学哈希函数(如SHA-256),对证书的所有明文信息 (就是上面"块一"里的全部内容)进行计算,生成一个固定长度的、唯一的字符串,叫做摘要 或指纹。
- 简单理解:就像给明文信息做了一个独一无二的"指纹"。
-
用CA私钥加密摘要 :CA使用它自己严格保密的私钥,对这个"指纹"(摘要)进行加密。
- 简单理解:CA用它的"私章"在这个"指纹"上盖了一个加密的印。
-
得到数字签名 :加密后的结果,就是数字签名。CA将这个签名附加在证书的明文信息之后,共同组成完整的证书文件。

这个数字签名是CA机构用自己的私匙加密后的一种产物,需要通过公匙来进行解密获取数字前面。
虽然公匙很容易被获取,也就代表着我们的数字签名容易被人直接知晓,但是他人也无法修改我们的数字签名,因为中间人替换的数字签名必然要加密,而这个加密不可能用CA机构自己持有的私匙。由于非对称加密的特性,倘若中间人用自己的私匙进行加密,此时发送给客户端,客户端只会使用CA机构发出来的公匙进行解密,导致解密失败,于是就能得知我们的数据被人篡改过。
可能有同学会好奇,你凭什么使用的CA机构的公匙就一定是CA机构的?这是因为你的浏览器(如Chrome、Firefox、Safari)或您的操作系统(Windows、macOS、Linux)在出厂时,就内置了一个名为 "信任根证书存储" 的列表。
-
这个列表里是什么?
-
里面包含了全球几十个到上百个公认最权威的根证书颁发机构 的自签名证书。
-
所谓自签名证书 ,就是CA给自己颁发的证书,里面包含了该CA的名称 和其自身的公钥 ,并用它自己的私钥进行了签名。
-
这些根证书在软件(浏览器、操作系统)出厂前就已经被预先安装和配置好了。
-
-
这个列表由谁维护?
-
由浏览器厂商(如Google、Apple、Mozilla)或操作系统厂商(如Microsoft)严格维护。
-
他们有一套极其严格的审核流程,来决定将哪些CA加入信任列表。一个CA要想被纳入,必须通过安全、审计、运营能力等多方面的苛刻审查。
-
-
它如何工作?
-
当您的浏览器收到一个网站证书(比如来自
bank.com
)时,它会沿着证书链向上验证,直到找到签发这个证书的根CA。 -
然后,浏览器会检查这个根CA的证书是否存在于自己本地的**"信任根证书存储"** 中。
-
如果存在,浏览器就信任这个根CA的公钥,并用它来验证整个证书链。
-
如果不存在,浏览器就会弹出严重警告,提示您连接不安全。
-
如果中间人不能攻破我们的数字签名,那么他对我们证书中其他的明文信息的修改就会直接不攻而破。
因为数字签名的有确定性,相同的数据通过同一个哈希算法得出的数字摘要一定是一样的。同一个道理,如果你更改了正文部分的任意数据信息,那么客户端自己通过该哈希函数算出的数字摘要结果就会不同,从而得知被篡改了。
所以我们就保证了证书中正文的安全性。而证书中的正文,就包含了我们的服务端的公匙,所以我们就可以保证用户端获取的服务端公匙一定就是真的。
至此,客户端就可以生成自己的对称密匙,并通过服务端的公匙进行加密,这个内容只有服务端的私匙可以进行解密,所以就可以确保我们的服务端获取到对称密匙,从此,我们的服务端与客户端就可以通过对称密匙进行对称加密了!!!!


HTTPS的整体过程

阶段一:TCP连接建立
-
步骤1: Client Hello
- 浏览器向服务器的443端口发起TCP连接,并发送
Client Hello
消息,其中包含:自己支持的TLS版本、支持的密码套件列表、以及一个客户端随机数。
- 浏览器向服务器的443端口发起TCP连接,并发送
阶段二:TLS握手(核心身份验证与密钥交换)
-
步骤2: Server Hello
- 服务器回应
Server Hello
消息,内容包括:双方协商一致的TLS版本、选定的密码套件、一个服务器随机数 ,以及至关重要的SSL证书。此证书包含服务器的公钥。
- 服务器回应
-
步骤3: 客户端验证证书
-
浏览器验证SSL证书的真实性:
-
颁发机构是否可信?(检查内置的信任根证书库)
-
证书是否过期?
-
证书中的域名是否与当前访问的域名一致?
-
证书的数字签名是否有效?(用CA的公钥验证签名,确保证书未被篡改)
-
-
验证失败则终止连接,并显示警告。
-
-
步骤4: 生成并加密预备主密钥
-
验证通过后,客户端生成第三个随机数,称为 预备主密钥。
-
客户端使用服务器的公钥加密这个预备主密钥。
-
-
步骤5: 发送加密的预备主密钥
- 客户端将加密后的预备主密钥发送给服务器。
-
步骤6: 服务器解密预备主密钥
-
服务器使用自己的私钥解密,得到预备主密钥。
-
此时,客户端和服务器都拥有了三个相同的要素:客户端随机数、服务器随机数和预备主密钥。
-
-
步骤7: 双方生成会话密钥
- 客户端和服务器分别 使用相同的密钥派生算法,将上述三个随机数进行计算,生成完全相同的主密钥 ,进而生成本次会话使用的对称会话密钥。
-
步骤8: 握手完成
- 双方交换一条
Finished
消息,用刚生成的会话密钥加密,确认握手过程安全无误。至此,安全通道建立。
- 双方交换一条
阶段三:加密通信
-
步骤9 & 10: 对称加密通信
-
此后,所有的HTTP请求和响应(如网页内容、登录密码、API数据)都会在发送前,用会话密钥进行加密。
-
接收方收到密文后,用同一把会话密钥解密。
-
这个阶段使用对称加密(如AES),因为其速度极快,适合处理大量数据。
-
总结
HTTPS 工作过程中涉及到的密钥有三组.
第一组(非对称加密): 用于校验证书是否被篡改. 服务器持有私钥(私钥在形成 CSR 文件与申请证书时获得), 客户端持有公钥(操作系统包含了可信任的 CA 认证机构有哪些, 同时持有对应的公钥). 服务器在客户端请求时,返回携带签名的证书. 客户端通过这个公钥进行证书验证, 保证证书的合法性,进一步保证证书中携带的服务端公钥权威性。
第⼆组(非对称加密): 用于协商生成对称加密的密钥. 客户端用收到的 CA 证书中的公钥(是可被信任的)给随机生成的对称加密的密钥加密, 传输给服务器, 服务器通过私钥解密获取到对称加密密钥.
第三组(对称加密): 客户端和服务器后续传输的数据都通过这个对称密钥加密解密.
其实一切的关键都是围绕这个对称加密的密钥. 其他的机制都是辅助这个密钥工作的.
- 第⼆组非对称加密的密钥是为了让客户端把这个对称密钥传给服务器.
- 第一组非对称加密的密钥是为了让客户端拿到第⼆组非对称加密的公钥.