文章目录
-
- 简介
- DH(FFDH)
- [static DH](#static DH)
- DHE
- ECDHE
- 基于ECDHE的密钥协商流程
-
- TLS第一次握手
-
- [1.Client Hello](#1.Client Hello)
- TLS第二次握手
-
- [2.Server Hello](#2.Server Hello)
- 3.Certificate
- [4.Server Key Exchange](#4.Server Key Exchange)
- [5.Server Hello Done](#5.Server Hello Done)
- TLS第三次握手
-
- [6.Client Key Exchange](#6.Client Key Exchange)
- [7.Change Cipher Spec](#7.Change Cipher Spec)
- [8.Encrypted Handshake Message](#8.Encrypted Handshake Message)
- TLS第四次握手
-
- [9.New Session Ticket](#9.New Session Ticket)
- [10.Change Cipher Spec](#10.Change Cipher Spec)
- [11.Encrypted Handshake Message](#11.Encrypted Handshake Message)
简介
HTTPS 常用的密钥交换算法有两种,分别是 RSA 和 ECDHE 算法。
其中,RSA 是比较传统的密钥交换算法,上一篇文章已经介绍过了,它不具备前向安全的性质,因此现在很少服务器使用的。而 ECDHE 算法具有前向安全,所以现在基本都是使用这个算法。
首先我们拆解一下ECDHE的命名组成:
- EC椭圆曲线(Elliptic Curve) 是一种密钥算法。
- DH(Diffie-Hellman是一个密钥交换协议/机制。
- E(ephemeral临时性的代表每次协商密钥都使用不同的参数以保证随机性。
首先了解一下什么是DH,DH本质上是一个密钥交换协议/机制,
- DH 定义了一种交互过程 :两个通信方(Alice 和 Bob)如何通过公开交换一些信息,最终各自独立地计算出一个相同的秘密值(即共享密钥)。
- 这个协议的核心思想是利用单向函数(正向计算容易,反向求解困难)来实现:即使攻击者监听到双方交换的所有公开信息,也无法计算出最终的共享密钥。
- 协议本身并不规定具体使用哪个数学难题或哪个群结构。它描述的是一个通用的密钥协商框架。
DH最常用的两种实现是:
- FFDH: 基于有限域 (
Z_p*
) 上的离散对数问题 (DLP)。 - ECDH: 基于椭圆曲线群上的离散对数问题 (ECDLP)。
一般不加前缀的DH指的就是FFDH。所以一般我们见到的组合有:DH(FFDH)、DHE(FFDHE)、ECDH、ECHDE。
DH(FFDH)
DH算法基于有限域上的离散对数这个数学难题,他的原理很简单:
ga mod p = A
g的a次方除以p的余数等于A,这个公式有两个特点:
- 已知g,a,p求解A非常简单;而根据g,p,A在[1,p]范围内求解a却非常的困难,尤其当p特别大的时候。
- 已知ga mod p = A,gb mod p = B ,那么Ba mod p = Ab mod p ,这个结果是通过二项式展开得到的: Ba mod p = (gb mod p)a mod p = gab mod p = (ga mod p)b mod p = Ab mod p
我们来看下TLS怎么利用这些特点实现密钥的协商的。

-
Alice选择两个质数:p, g
p必须是一个非常大的质数,而g则是一个与p相关的数,成为生成元(Generator, 或数论中叫做本原根),g可以是一个比较小的数。 p, g是不需要保密的,即使被窃听也无关痛痒。
-
Alice生成一个随机数a
a是一个位于1 ~ p-2之间的整数。这个数只能自己知道,不需要告诉Bob, 也不能让其他人知道。
-
Alice计算出A
A = ga mod p
-
Alice将p, g, A全部发送给Bob这三个数可以让其他人知道,没有关系
-
Bob生成一个随机数b
b是一个位于1 ~ p-2之间的整数。这个数只能自己知道,不需要告诉Alice, 也不能让其他人知道。
-
Bob计算出B Bob已经接收到Alice发来的g,p,因此可以计算出B。
B = gb mod p
-
Bob只需要将B发送给Alice B也可以让其他人知道,没有关系
-
Alice利用Bob发来的B计算共享密钥K
K = Ba mod p
-
Bob利用Alice发来的A计算共享密钥K
K = Ab mod p
最后Alice和Bob计算出的共享密钥可以通过数学公式证明是同等的。因此通过DH密钥协商,最终双方协商出了只有两个人知道的共享密钥。
static DH
根据DH算法进行密钥协商服务端和客户端就可以生成一个共享密钥,并且不被第三方所知,根据私钥生成的方式,TLS的DH密钥协商分为两种,static DH 算法,这个是已经被废弃了,DHE 算法,现在常用的;
静态DH 算法,DH 交换密钥时就只有客户端的公钥是变化,而服务端公钥是不变的,那么随着时间延长,黑客就会截获海量的密钥协商过程的数据,因为密钥协商的过程有些数据是公开的,黑客就可以依据这些数据暴力破解出服务器的私钥,然后就可以计算出会话密钥了,和RSA 密钥协商算法一样,一旦服务器对应的DH 私钥泄露,之前截获的加密数据会被破解,所以 static DH 算法不具备前向安全性。
DHE
既然静态DH算法中,一方固定一方临时生成的方式不安全,那么我们就双方都不固定。通讯双方的私有密钥都采用临时生成的方式,这中DH算法称之为DHE算法(E是指Ephemeral, 临时的)。
ECDHE
DHE 算法由于计算性能不佳,因为需要做大量的乘法,为了提升 DHE 算法的性能,所以就出现了现在广泛用于密钥交换算法 ------ ECDHE 算法。
ECDHE 是使用椭圆曲线(ECC)的 DH(Diffie-Hellman)算法,ECDHE 算法是在 DHE 算法的基础上利用了 ECC 椭圆曲线特性,可以用更少的计算量计算出公钥,以及最终的会话密钥。具体的算法就不介绍了,有兴趣的可以自己去了解一下。
基于ECDHE的密钥协商流程

和之前讲的RSA密钥交换一样,ECDHE密钥协商同样分为4步,下面我们通过抓包握手协议来分析这些过程:

可以看到和RSA密钥交换相比多了一个Server Key Exchange,这个侧面证明密钥是两方共同协商生成的,下面我们来一步步分析。
TLS第一次握手
1.Client Hello

这一步和RAS密钥交换的一样,直接看上一篇文章即可。
TLS第二次握手
2.Server Hello

这一步和RAS密钥交换就有了区别,加密套件变成了TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,即密钥交换方式变成ECDHE。
- 密钥协商算法使用 ECDHE;
- 签名算法使用 RSA;
- 握手后的通信使用 AES 对称算法,密钥长度 256 位,分组模式是 GCM;
- 摘要算法使用 SHA256;
3.Certificate

这一步就是传证书,和RAS密钥交换一样。
4.Server Key Exchange

比RSA密钥交换多出的步骤,在ECDHE密钥协商中非常重要,下面我们来分析他的数据:
- Named Curve: secp256r1:是椭圆曲线算法的名称,由于ECDHE需要约定好椭圆曲线基点等公开信息,所以会有提前定义好的代表不同基点的算法名称。
- Pubkey:服务端生成自己随机数(私钥)后通过椭圆曲线算法计算出来的参数(公钥)
- Signature Algorithm: rsa_pkcs1_sha512:为了保证服务端pubkey的可靠性,服务端还会用证书的私钥对pubkey进行哈希后加密,客户端拿到后用证书的公钥对pubkey进行解密验证。这里的参数就是定义加密和哈希的算法,分别是rsa和sha512
- Signature: pubkey哈希加密后的内容。
5.Server Hello Done

和RAS密钥交换一样。
TLS第三次握手
6.Client Key Exchange

RAS密钥交换这里直接传的是证书公钥加密后的pre-master,这里传的是客户端生成自己随机数(私钥)后通过椭圆曲线算法计算出来的参数(公钥),到这里客户端通过拥有的:服务端的公钥,客户端的公钥,客户端的私钥 就可以计算是pre-master,但是这里并不需要传递给服务端,服务端拿到客户端的公钥后通过:客户端的公钥,服务端的公钥,服务端的私钥就可以计算出和客户端一样的pre-master,再之后通过**(客户端随机数 + 服务端随机数 + 预主密钥 = 主密钥 ==> 会话密钥)计算出会话密钥。**
7.Change Cipher Spec
8.Encrypted Handshake Message
TLS第四次握手
9.New Session Ticket
10.Change Cipher Spec
11.Encrypted Handshake Message
接着后面的7、8、9、10、11的步骤和RAS密钥交换完全相同,这里就不再赘述了。
目前为止我们讲的都是单向认证,也就是只有客户端验证服务端的身份,但是对于某些对安全要求较高的,比如银行类的网站可能就会要求认证用户的身份,这时候就用到双向认证了,比如银行的U盾就是用于双向认证。下一篇文章来讲讲双向认证的内容。