HTTPS解析¶
Wireshark解密HTTPS流量¶
未解密前:

https经过一系列的精心设计,将不法分子拒之门外,而我们如果想要尝试分析https报文,却也变得困难重重。想要解密https报文,最重要的是获取对称加密的密钥,也就是Pre-master secret。而这个密钥由客户端生成,使用服务端公钥加密,如果想要得知该密钥,要么直接让客户端告诉我们,要么就得得知服务端的私钥,用私钥解密该密钥,这就衍生出两种分析https报文的方法。
wireshark支持两种方式来解密SSL/TLS报文:
- 通过网站的私钥
- 通过浏览器的将 TLS 对称加密秘保存在外部文件中,以供 wireshark 加解密
服务器私钥解密¶
如果得知了服务器私钥,那么解密https报文则简单多了,客户端在密钥协商阶段发送到密钥能够直接通过服务端私钥解密,wireshark同样也提供了该方式解密的入口。

The RSA private key file can only be used in the following circumstances:
- The cipher suite selected by the server is not using (EC)DHE.
- The protocol version is SSLv3, (D)TLS 1.0-1.2. It does not work with TLS 1.3.
- The private key matches the server certificate. It does not work with the client certificate, nor the Certificate Authority (CA) certificate.
- The session has not been resumed. The handshake must include the ClientKeyExchange handshake message.
通过Pre-master secret解密¶
- 环境变量导出pre-master secret
对于使用openssl作为tls连接库的大多数程序,都可以通过SSLKEYLOGFILE环境变量导出secret。
- gdb导出pre-master secret
gdb是进程动态调试工具,可以分析运行中进程的详细情况,自然也可以用来获取客户端在tls密钥交换过程中产生的pre-master secret,具体的实施方法可以参考这篇文章:使用gdb从openssl应用程序中导出pre-master key。
- python程序导出pre-master secret
对于python3.8及以上版本,想要导出secret,只需要配置SSLKEYLOGFILE环境变量即可。
而python3.8以下版本,则需要通过修改代码的方式导出secret,具体方法参考该仓库:joernheissler/SslMasterKey: Retrieve the Master Key and Client Random from an ssl.SSLSocket (github.com)。
wireshark提供了通过pre-master secret解密https流量的入口,在如下窗口指定pre-master secret所在文件后,便能够自动将https流量从密文变为明文。

步骤总结(Maos):
# 1. 向~/.bashrc 或 ~/.zshrc写入SSLKEYLOGFILE环境变量,配置权限为644
SSLKEYLOGFILE=xxx/keylogfile.txt
# 2. 配置wireshark
# 3. 关闭浏览器
# 4. 测试logfile是否生效,使用如下命令:
curl https://www.qq.com 或 open /Applications/Google\ Chrome.app

可以看到log文件中已存储密钥

此时wireshark已成功解密https流量
参考:wireshark分析https报文 - frankming - 博客园
参考wireshark官方:TLS - Wireshark Wiki
TLS/SSL协议¶
SSL(Secure Sockets Layer)和 TLS(Transport Layer Security)都是为网络通信提供安全和数据完整性的加密协议。
SSL 是由网景公司在1990年代早期开发。TLS是其后续版本,由互联网工程任务组(IETF)开发。虽然两者在技术上有所不同,但它们的目标和功能基本相同,因此通常一起讨论,并且术语 “SSL/TLS” 常常被用来表示两者。
SSL/TLS 协议主要有两个目的:一是确保数据在传输过程中的隐私,二是确保数据在传输过程中的完整性。这是通过在数据传输开始时进行一次“握手”来实现的,以便服务器和客户端可以就如何加密数据进行协商,并可选地验证对方的身份。
在握手过程中,服务器和客户端会协商一个密钥,然后使用这个密钥对传输的数据进行加密和解密。这样,即使数据在传输过程中被拦截,也无法读取其内容,除非拦截者知道密钥。
此外,SSL/TLS 还可以使用数字证书来验证服务器(或在某些情况下,客户端)的身份。这是通过将服务器的公钥和一些身份信息打包到一个由受信任的第三方(称为证书颁发机构)签名的证书中来实现的。客户端可以验证证书的签名,以确保它是与服务器通信,而不是与冒充服务器的攻击者通信。
总的来说,SSL/TLS是一种重要的安全协议,用于保护网络通信不被窃听或篡改。

密钥协商¶
网络通信中,对称加解密采用动态秘钥,也叫作会话秘钥,秘钥的特点如下:
- 会话秘钥用途:加解密通信业务数据。
- 会话秘钥来源:是通过秘钥协商算法协商而来,且只有通信双方的客户端和服务端知晓。
- 会话秘钥生命周期:会话秘钥,顾名思义,仅用于该会话,会话建立时,协商而来的**动态**秘钥,无需存储,会话一旦结束,那么这个会话秘钥也就失去其存在的价值。因此,会话秘钥,仅存在于内存,极大保证通信的安全性。
常见秘钥协商算法:
- RSA秘钥协商算法
- DH秘钥协商算法
- ECDH秘钥协商算法
RSA秘钥协商算法¶
客户端向服务端发送连接请求后,服务端将其公钥返回给客户端,客户端生成一个会话秘钥,使用服务端提供的公钥对会话秘钥进行加密,在服务端使用私钥对其进行解密。此时,客户端和服务端均知晓会话秘钥。通信双方可以使用协商的这个会话秘钥进行业务数据对称加解密通信。

特点
- 每次连接请求,都会产生一个动态的会话秘钥。
- 协商流程简单。
缺点
- 会话秘钥由客户端决定。如果客户端生成会话秘钥时,生成的秘钥较简单,那么攻击者可以想到暴力破解,不会去直接破解RSA加密算法的私钥,而是直接暴力破解会话秘钥,反解出明文。
- 一旦服务端的私钥被泄漏,那么之前攻击者保存下来的密文,都可以通过服务端的私钥解密出会话秘钥,再使用会话秘钥解密通信数据。这就**不能提供前向安全性**。
Note
需要注意的是,客户端生成会话密钥这一过程是由浏览器内核生成的,所以除非攻击者能hook到浏览器内核生成该密钥的逻辑,否则不可能逆向分析出生成算法,该算法在TLS 1.3中已完全移除,TLS 1.2中不建议使用
DH密钥协商算法¶
Diffie-Hellman密钥交换算法(DH算法)是一种用于在两个通信方之间安全地协商共享密钥的方法。它解决了如何在公共信道上安全地传输密钥的问题,使得即使密钥被截获,攻击者也无法轻易破解
算法原理¶
按照惯例,以Alice和Bob这两个密码学中的网红为角色,述阐DH算法的流程。
假设Alice需要与Bob协商一个秘钥(秘钥本质上就是一个比特序列,从计算的角度看就是一个大数)。
1)首先Alice与Bob共享一个素数p以及该素数p的本原根g(geneator),当然这里有2⩽g⩽p−1。这两个数是可以不经过加密地由一方发送到另一方,至于谁发送给并不重要,其结果只要保证双方都得知p和g即可。

2)然后Alice产生一个私有的随机数A,满足1⩽A⩽p−1,然后计算gA mod p=Ya,将结果Ya通过公网发送给Bob;与此同时,Bob也产生一个私有的随机数B,满足1⩽B⩽p−1,计算gB mod p=Yb,将结果Yb通过公网发送给Alice。

3)此时Alice知道的信息有p,g,A,Ya,其中数字A是Alice私有的,只有她自己知道,别人不可能知道,其他三个信息都是别人有可能知道的;Bob知道的信息有p,g,B,Yb,其中数字B是Bob私有的,只有他自己知道,别人不可能知道,其他都是别人有可能知道的。
到目前为止,Alice和Bob之间的秘钥协商结束。
Alice通过计算Ka=(Yb)A mod p得到秘钥Ka,同理,Bob通过计算Kb=(Ya)B mod p得到秘钥Kb,此时可以证明,必然满足Ka=Kb。因此双方经过协商后得到了相同的秘钥,达成秘钥协商的目的。
更严密地考虑,A和B不应该选择p−1,也就是说只能在集合{1,2,3,...,p−2}中选择。这是因为如果选择p−1,那么由费马小定理可知,情况就退化成了gp−1≡1(modp)的情况,对秘钥协商的机密性构成威胁。
所以总结起来,整个流程串起来大概就是这样:

那么窃听者Eve能否破解秘钥呢?首先要知道Eve能够得知哪些信息,显然Eve能够窃听到的信息只能有p,g,Ya,Yb,现在的问题是Eve能够通过以上信息计算出Ka或者Kb吗?要计算Ka或者Kb需要知道A或者B。
以计算A为例,Eve能根据条件gAmodp=Ya计算出A吗?实际上当p是大质数的时候,这是相当困难的,这就是离散对数问题。实际上在论文发表的当时,计算该问题的最有效的算法的时间复杂度大约是O(√p)。也正是求解该问题在计算上的困难程度保证了DH算法的安全性。如果能够找到对数时间复杂度的算法,那么该算法即容易被攻破。
Note
由上可知:当A和B范围都在1~p-2时,才能更好地保证DH密钥协商的安全性,由于该算法同样不能保证前向安全性,即如果A或B泄漏,那么会话密钥可被计算出,导致可解密之前所有的流量。该算法也被废弃使用
DH算法的中间人攻击¶
是否DH秘钥协商算法就一定安全呢?应该说也不是,因为存在一种伪装者攻击(或者称为中间人攻击)能够对这种秘钥协商算法构成威胁。
假设秘钥协商过程中,在Alice和Bob中间有一个称为Mallory的主动攻击者,他能够截获Alice和Bob的消息并伪造假消息,考虑如下情况。
1)Alice和Bob已经共享一个素数p及其该素数p的本原根g,当然Mallory监听到报文也得知了这两个消息。
2)此时Alice计算Ya=gA mod p,然而在将Ya发送给Bob的过程中被Mallory拦截,Mallory自己选定一个随机数S,计算Ysb=gS mod p,然后将Ysb发送给了Bob。

3)同时Bob计算Yb=gB mod p,然而在将Yb发送给Alice的过程中被Mallory拦截,Mallory自己选定一个随机数T,计算Yta=gT mod p,然后将Yta发送给了Alice。

由于通讯消息被替换,Alice计算出的秘钥实际上是Alice和Mallory之间协商秘钥:Kam=gA×T mod p;Bob计算出的秘钥实际上是Bob与Mallory之间协商的秘钥:Kbm=gB×S mod p。如果之后Alice和Bob用他们计算出的秘钥加密任何信息,Mallory截获之后都能够解密得到明文,而且Mallory完全可以伪装成Alice或者Bob给对方发消息。
Note
也就是说DH算法的缺点在于无法确定通信对方的身份是否是合法的
参考文章¶
Diffie-Hellman密钥协商算法 - Qcer - 博客园
EDH密钥协商算法¶
静态DH 算法, p 和g 两个参数永远是固定的,而且服务器的公钥C Ys )也是固定的。和RSA 密钥协商算法一样,一旦服务器对应的DH 私钥泄露,就不能提供前向安全性。静态DH 算法的好处就是避免在初始化连接时服务器频繁生成参数p 和g ,因为该过程是非常消耗CPU 运算的。
于是,DH 交换密钥时就只有客户端的公钥是变化,而服务端公钥是不变的,那么随着时间延长,黑客就会截获海量的密钥协商过程的数据,因为密钥协商的过程有些数据是公开的,黑客就可以依据这些数据暴力破解出服务器的私钥,然后就可以计算出会话密钥了,于是之前截获的加密数据会被破解,所以 static DH 算法不具备前向安全性。
既然固定一方的私钥有被破解的风险,那么干脆就让双方的私钥在每次密钥交换通信时,都是随机生成的、临时的,这个方式也就是 DHE 算法,E 全称是 ephemeral(临时性的)。
所以,即使有个牛逼的黑客破解了某一次通信过程的私钥,其他通信过程的私钥仍然是安全的,因为**每个通信过程的私钥都是没有任何关系的,都是独立的,这样就保证了「前向安全」**。
Note
所以EDH和DH算法唯一的区别就在于EDH是每一次会话都要重新使用DH算法计算会话密钥,这种方式使得每次会话间密钥都不一样,从而保证了前向安全性
参考文章¶
https原理--ECDHE密钥协商算法 - xufat - 博客园
ECDH密钥协商算法¶
ECC(椭圆曲线密码学)密钥协商基于椭圆曲线离散对数问题,最常用的是ECDH(椭圆曲线Diffie-Hellman)算法。
ECDH密钥协商过程
- 参数选择:双方约定使用相同的椭圆曲线参数(如secp256r1)
- 密钥对生成:双方各自生成ECC密钥对(私钥d和公钥Q=d×G,其中G是基点)
- 公钥交换:双方交换各自的公钥
- 共享密钥计算:
- Alice计算:S = d_A × Q_B(d_A是Alice的私钥,Q_B是Bob的公钥)
- Bob计算:S = d_B × Q_A(d_B是Bob的私钥,Q_A是Alice的公钥)
- 密钥派生:对共享密钥S应用密钥派生函数(KDF)生成最终会话密钥
由于椭圆曲线的性质,双方计算出的共享密钥S是相同的:d_A × Q_B = d_A × (d_B × G) = d_B × (d_A × G) = d_B × Q_A
协商全过程¶
前提条件:
双方事先约定好使用同一个**椭圆曲线**(例如,在 Golang 中常用的 P-256, P-384, P-521)。
全过程步骤:
- 生成密钥对(Key Pair Generation)
- Alice:随机生成一个**私钥**
dA(一个保密的超大整数)。利用椭圆曲线乘法,计算其对应的**公钥**QA = dA * G,其中G是椭圆曲线上的一个公开的基点(Generator Point)。 - Bob:同样,随机生成自己的**私钥**
dB,并计算对应的**公钥**QB = dB * G。 - 交换公钥(Public Key Exchange)
- Alice 将自己的公钥
QA发送给 Bob。这个通道可以是**不安全的**,即使被窃听也无妨。 - Bob 将自己的公钥
QB发送给 Alice。同样,这个通道也可以是不安全的。 - 计算共享秘密(Shared Secret Calculation)
- Alice 收到 Bob 的公钥
QB后,用自己的私钥dA进行计算:S = dA * QB。- 因为
QB = dB * G,所以S = dA * (dB * G) = (dA * dB) * G。
- 因为
- Bob 收到 Alice 的公钥
QA后,用自己的私钥dB进行计算:S = dB * QA。- 因为
QA = dA * G,所以S = dB * (dA * G) = (dB * dA) * G。
- 因为
- 根据椭圆曲线乘法的交换律,
(dA * dB) * G = (dB * dA) * G。因此,双方计算出的点S是**同一个点**,即(x, y)坐标相同。 - 派生对称密钥(Symmetric Key Derivation)
- 这个共享秘密
S是一个椭圆曲线上的点(包含 X, Y 坐标)。直接将其字节序列作为密钥可能不够安全或长度不合适。 - 双方会使用一个**密钥派生函数(KDF, Key Derivation Function)** 来处理这个共享秘密。通常,只会使用点的 X 坐标(或 X 和 Y 坐标的某种组合)作为 KDF 的输入。
- KDF(如 HKDF)会将这个输入“拉伸”和“混合”,生成一个或多个长度固定、密码学强度高的密钥字节序列。这个最终的字节序列就是双方用于对称加密(如 AES-256)的**共享密钥**。
安全性:
窃听者即使获得了公开的 G, QA, QB,也无法计算出 dA 或 dB(椭圆曲线离散对数难题),因此也无法计算出共享秘密 S。
Note
可以将ECDH算法理解为使用基于ECC椭圆曲线的数学难题代替了原本的数学难题,使其密钥和算法更加复杂和安全,当然如果私钥dA或dB泄漏,同样无法保证前向安全性
ECDHE密钥协商算法¶
它的工作流程如下:
- 客户端和服务器各自选择一个
椭圆曲线私钥(随机数),并使用椭圆曲线算法生成对应的椭圆曲线公钥。 - 在握手阶段,客户端和服务器互相交换
椭圆曲线公钥。 - 客户端和服务器各自使用
对方的椭圆曲线公钥和自己的椭圆曲线私钥,通过椭圆曲线的点运算生成一个共享密钥。由于椭圆曲线的数学性质,这个共享密钥在双方都知道,但是不能被第三方计算出来。(共享密钥并非通过传输手段获得,避免中间人截取。) - 客户端和服务器使用这个共享密钥进行
对称加密通信。
ECDHE 算法的优点是每次握手都会生成一个新的密钥,即使有人能够破解一个会话的密钥
Note
ECDHE与ECDH的区别在于ECDHE生成的密钥是临时的,保证了前向安全性
该算法被广泛用于TLS v1.2和TLS v1.3所以我们有必要从流量层面分析一下该算法协商的过程
TLS v1.2握手过程¶
TLS 握手原理是双方互换信息,协商出共享的 会话密钥。

第一次握手¶
客户端首先会发一个「Client Hello」消息,消息里面有客户端使用的 TLS 版本号、支持的密码套件列表、支持的椭圆曲线、支持的签名算法,以及生成的**随机数(Client Random)**。


第二次握手¶
服务端收到客户端的「打招呼」,同样也要回礼,会返回「Server Hello」消息,消息面有服务器确认的 TLS 版本号,也给出了一个**随机数(Server Random)**,然后从客户端的密码套件列表选择了一个合适的密码套件。

不过,这次选择的密码套件就和 RSA 不一样了,我们来分析一下这次的密码套件的意思。
- 密钥协商算法使用 ECDHE;
- 签名算法使用 RSA;
- 握手后的通信使用 AES 对称算法,密钥长度 128 位,分组模式是 GCM;
- 摘要算法使用 SHA256;
接着,服务端为了证明自己的身份,发送「Certificate」消息,会把证书也发给客户端。

这一步就和 RSA 握手过程有很大到区别了,因为服务端选择了 ECDHE 密钥协商算法,所以会在发送完证书后,发送「Server Key Exchange」消息。

这个过程服务器做了三件事:
- 选择了**名为 named_curve 的椭圆曲线**,选好了椭圆曲线相当于椭圆曲线基点 G 也定好了,这些都会公开给客户端;
- 生成随机数作为服务端椭圆曲线的私钥,保留到本地;
- 根据基点 G 和私钥计算出**服务端的椭圆曲线公钥**,这个会公开给客户端。
也就是传输ECDH算法的公开参数
为了保证这个椭圆曲线的公钥不被第三方篡改,服务端会用 RSA 签名算法给服务端的椭圆曲线公钥做个签名。
随后,就是「Server Hello Done」消息,服务端跟客户端表明:“这些就是我提供的信息,打招呼完毕”。

至此,TLS 两次握手就已经完成了,目前客户端和服务端通过明文共享了这几个信息:Client Random、Server Random 、使用的椭圆曲线、椭圆曲线基点 G、服务端椭圆曲线的公钥,这几个信息很重要,是后续生成会话密钥的材料。
第三次握手¶
客户端收到了服务端的证书后,自然要校验证书是否合法,如果证书合法,那么服务端到身份就是没问题的。校验证书到过程,会走证书链逐级验证,确认证书的真实性,再用证书的公钥验证签名,这样就能确认服务端的身份了,确认无误后,就可以继续往下走。
客户端会生成一个随机数作为客户端椭圆曲线的私钥,然后再根据服务端前面给的信息,生成**客户端的椭圆曲线公钥**,然后用「Client Key Exchange」消息发给服务端。

至此,双方都有对方的椭圆曲线公钥、自己的椭圆曲线私钥、椭圆曲线基点 G。于是,双方都就计算出点(x,y),其中 x 坐标值双方都是一样的,前面说 ECDHE 算法时候,说 x 是会话密钥,但实际应用中,x 还不是最终的会话密钥。
还记得 TLS 握手阶段,客户端和服务端都会生成了一个随机数传递给对方吗?
最终的会话密钥,就是用「客户端随机数 + 服务端随机数 + x(ECDHE 算法算出的共享密钥) 」三个材料生成的。
之所以这么麻烦,是因为 TLS 设计者不信任客户端或服务器「伪随机数」的可靠性,为了保证真正的完全随机,把三个不可靠的随机数混合起来,那么「随机」的程度就非常高了
算好会话密钥后,客户端会发一个「Change Cipher Spec」消息,告诉服务端后续改用对称算法加密通信。

接着,客户端会发「Encrypted Handshake Message」消息,把之前发送的数据做一个摘要,再用对称密钥加密一下,让服务端做个验证,验证下本次生成的对称密钥是否可以正常使用。

第四次握手¶
最后,服务端也会有一个同样的操作,发「Change Cipher Spec」和「Encrypted Handshake Message」消息,如果双方都验证加密和解密没问题,那么握手正式完成。于是,就可以正常收发加密的 HTTP 请求和响应了。

总结¶

| 序号 | 方向 | 握手 | 过程 | 描述 |
|---|---|---|---|---|
| 1 | C -> S | 第一次 | Client Hello | 客户端发送它支持的 TLS 版本,加密套件列表,客户端随机数给服务端 |
| 2 | S -> C | 第二次 | Server Hello | 服务端发送它选择的 TLS 版本,加密套件,服务端随机数给客户端 |
| 3 | S -> C | 第二次 | Certificate | 服务端发送 CA 证书(公钥 + 证书持有者等信息)给客户端 |
| 4 | S -> C | 第二次 | Server Key Exchange | 1. 服务端生成椭圆曲线私钥 ==> 生成椭圆曲线公钥 ==> 服务端的 RSA 私钥实现椭圆曲线公钥签名 2. 服务端发送:椭圆曲线算法信息,(服务端的)椭圆曲线公钥,(服务端的)椭圆曲线公钥签名给客户端 |
| 5 | S -> C | 第二次 | Server Hello Done | 服务端发送确认给客户端,已完成 Hello 阶段流程 |
| 6 | C -> S | 第三次 | Client Key Exchange | 客户端生成椭圆曲线公钥,并将其发送给服务端 |
| 7 | C -> S | 第三次 | Change Cipher Spec | 客户端通知服务端,确认握手过程中的加密算法和密钥已经生效,表示之后的消息都将使用新的密钥 |
| 8 | C -> S | 第三次 | Encrypted Handshake Message | 客户端将之前的握手数据(发送和接收)做一个摘要,再用会话密钥(对称密钥)加密摘要数据,将密文发送给服务端 |
| 9 | S -> C | 第四次 | New Session Ticket | 服务器发送该消息给客户端,包含一个新的会话票据,用于快速恢复会话,避免重复握手 |
| 10 | S -> C | 第四次 | Change Cipher Spec | 服务端接收到客户端生成的 椭圆曲线公钥,也协商出共享的 会话秘钥,并通知客户端表示之后的消息都将使用新的密钥 |
| 11 | S -> C | 第四次 | Encrypted Handshake Message | 服务端将之前的握手数据(发送和接收)做一个摘要,再用会话密钥(对称密钥)加密摘要数据,将密文发送给客户端,确认握手过程的完成 |
TLS v1.3握手过程¶
TLS v1.3的握手过程相较于TLS v1.2来说变化不大,主要是减少了往返过程从而提高了性能,并且还删除了之前TLS v1.2存在的不安全算法,以下是TLS v1.3握手流程图
sequenceDiagram
Client->>Server: ClientHello (key_share)
Server->>Client: ServerHello (key_share) + EncryptedExtensions + Certificate + CertificateVerify + Finished
Client->>Server: Finished
| 特性/场景 | TLS 1.2 | TLS 1.3 |
|---|---|---|
| 握手耗时 | 2-RTT | 1-RTT(或 0-RTT) |
| 密钥交换算法 | 支持 RSA(非前向安全) | 仅 ECDHE/DHE(强制前向安全) |
| 握手消息合并 | 多步骤(如 ServerKeyExchange) | 合并至 ServerHello 后 |
| 0-RTT 支持 | 不支持 | 支持(基于 PSK) |
| 不安全算法 | 允许 SHA-1、RC4 等 | 完全移除 |
| 会话恢复机制 | Session ID 或 Session Ticket | 优先使用 PSK 和 Session Ticket |
| 首次连接延迟 | 高(2-RTT) | 低(1-RTT) |
| 重连延迟(会话恢复) | 中(1-RTT) | 极低(0-RTT) |
| 抗量子计算攻击 | 弱 | 更强(支持 X25519 等算法) |
Note
由于TLS v1.3是2018年发表的,所以部分旧设备还未适配TLS v1.3,所以TLS v1.2仍是HTTPS中使用最广泛的协议
参考文章¶
TLS 1.2 与 TLS 1.3 握手流程深度解析:安全与性能的演进 | Symbol Crash
CA证书¶
概念¶
CA证书 是由权威的证书颁发机构(Certificate Authority)签发的数字证书。
证书作用¶
- 验证网站的身份:CA证书 包含了网站的公钥和其他相关信息,由权威的证书颁发机构签发。当用户访问一个网站时,浏览器会检查网站的证书是否由可信的 CA机构 签发,以验证网站的身份是否可信。
- 加密通信数据:CA证书 使用了公钥加密和对称加密的组合,可以加密传输的数据。这样可以防止第三方窃听、篡改或伪造数据,确保通信的安全性和完整性。
- 建立信任关系:由于 CA证书 是由可信的证书颁发机构签发的,浏览器会预先内置一些受信任的CA机构的根证书。当浏览器检查到网站的证书由受信任的 CA机构 签发时,会建立起对该网站的信任关系,显示安全的锁标志。

证书来源¶
CA 证书由权威的证书颁发机构 CA(Certificate Authority)签发,个人或公司要申请证书,可以通过相关平台付费购买或者免费申请获得。

证书工作原理¶
证书链路¶

- 首先证书颁发机构(CA)会颁发 根证书。
- 用户的计算机系统或浏览器会从 CA 获取根证书,并预装根证书。
- 根证书机构创建 中间证书 授权给 中间证书颁发机构 颁发 SSL证书。
- 个人或公司向 中间证书颁发机构 申请一个 服务器证书,中间颁发证书机构 接受申请,创建证书文件:包含 RSA公钥 的服务器证书文件和 RSA私钥 文件;有些 PERM 证书文件会将 中间证书 和 服务器证书 打包在一起。
- 中间颁发证书机构 创建对应的证书文件后,个人或公司可以从证书签发平台下载下来。
- 服务器启动服程序,并加载:服务器证书文件 和 RSA私钥。
- 用户通过 HTTPS 访问服务程序,进入 TLS 握手环节。
- 服务程序会给客户端发送 服务器证书。
- 客户端获得服务器证书后,通过 证书链 对该服务器证书进行校验。因为之前用户的计算机系统或浏览器已经预装了根证书,那么证书链验证:根证书验证中间证书合法,中间证书验证服务器证书合法。
- 客户端获得的服务器证书里包含了 RSA 的公钥,这个是公开的。RSA 私钥仍然在服务端,那么 RSA 私钥加密的数据(签名数据),公钥可以解密;反过来,RSA 公钥加密的密文,只有私钥可以解密。
- TLS 的握手的其它环节请参考上文。
证书验证¶

- 首先,客户端会从服务器获取证书链。证书链通常包括服务器证书、一个或多个中间证书。
- 客户端首先会检查服务器证书的有效性,包括证书的有效期、证书的颁发机构等。
- 然后,客户端会使用 中间证书的公钥 来验证服务器证书的签名(如上图:证书签名验证)。
- 接着,客户端会检查中间证书的有效性,并使用根证书的公钥来验证中间证书的签名。
- 最后,客户端会检查根证书的有效性。由于根证书是自我签名的,所以客户端会使用根证书的公钥来验证根证书的签名。
- 如果所有的证书都通过了验证,那么证书链就被认为是有效的。如果任何一个证书没有通过验证,那么证书链就被认为是无效的。