Diffie-Hellman 密钥交换协议,允许双方在没有预先共享秘密密钥的情况下通过不安全的通信渠道建立共享的秘密密钥。这个名字来源于发明者 Whitfield Diffie 和 Martin Hellman。
Diffie-Hellman 密钥交换原理简介
Diffie-Hellman 密钥交换(通常简称为 DH)依赖于数论中的一个事实:在一个有限字段上,给定生成元 g 和素数 p,计算 $g^a \mod p$ 相对容易,但是尝试反向计算,即已知 $g^a \mod p$ 求 a,则是计算上不可行的,这种问题被称为离散对数问题。
流程
-
参数生成和共享:首先,双方同意使用一个公共的大素数 p 和基数 g(这两个值就是所谓的 “DH Parameters”),g 通常是 2。
-
私钥和公钥生成:
- 每一方选择一个私有(不与对方共享)的随机数,作为自己的私钥。设发送方私钥为 $\alpha$,接收方为 $\beta$。
- 然后计算公钥 $A = g^\alpha \mod p$(发送方)和 $B = g^\beta \mod p$(接收方),并互相交换这些公钥。
- 计算共享秘密:
- 发送方计算 $S = B^\alpha \mod p$。
- 接收方计算 $S = A^\beta \mod p$。
- 如果计算正确,双方将得到相同的值 S,该值可以用作通信双方的共享秘密。
由于反向计算离散对数是计算上不可行的,因此第三方无法仅仅通过拦截 A 和 B 来确定共享秘密 S,除非他们能够解决离散对数问题,这在实践中是非常困难的,尤其是对于足够大的 p。
使用场景
Diffie-Hellman 主要用于在不安全的通道上安全地交换密钥,这些密钥之后可以用于加密后续通信。例如,在 TLS/SSL 握手过程中就可能使用它来建立会话密钥。
密码套件和 DH 参数
TLS 支持多种类型的密码套件,这决定了密钥交换、消息认证、加密和密钥材料生成算法。当涉及到 Diffie-Hellman 密钥交换的密码套件时,它们通常会分为两类:
-
传统 DH 密钥交换:在这种情况下,服务器和客户端事先同意一组 DH Parameters(公共的大素数 p 和基数 g)。服务器在 TLS 协议的相应阶段将这些参数发送给客户端。然后,服务器和客户端各自生成一个随机私钥,并基于此私钥和接收的参数计算公钥,再互换公钥以建立一个共享秘密。由于这些参数(特别是素数 p 和基数 g)是公开交换的,所以对安全性几乎没有影响,关键是私钥的私密性。
-
椭圆曲线 Diffie-Hellman 密钥交换(ECDH):与传统 DH 类似,但使用椭圆曲线数学而非模幂运算。在 ECDH 中,参数是指椭圆曲线的定义,以及用于生成公私钥对的基点。这些参数同样需要在通信双方间共享或事先约定。
SSL/TLS 握手和 DH 参数
在实际的 SSL(或 TLS)握手过程中,以下步骤涉及 DH Parameters 的使用:
-
服务器 Hello 消息:服务器选择一个密码套件,该套件可能包含 DH 密钥交换方法。
-
服务器 Key Exchange 消息:如果所选的密码套件基于 Diffie-Hellman 密钥交换,服务器将在这个消息中发送 DH Parameters(对于 ECDH,发送椭圆曲线参数和服务器的公钥)。对于某些 DH 套件,服务器的公钥可能已经在一个证书中,这种情况下,参数可能不需要在这条消息中发送。
-
客户端 Key Exchange 消息:客户端接收到服务器的 DH Parameters 后,生成自己的 DH 密钥对,发送自己的公钥给服务器。
-
Premaster Secret 的计算:一旦双方都有了对方的公钥,它们就可以独立计算出一个共同的秘密值(Premaster Secret),接下来使用这个秘密值生成会话使用的加密密钥。
在整个过程中,即使 DH Parameters(素数 p、基数 g 和相应的公钥)是公开的,由于 Diffie-Hellman 问题的难解性,攻击者不能轻易地计算出共享秘密,从而保证了密钥交换过程的安全性。
注意
虽然 Diffie-Hellman 本身是一种安全的密钥交换协议,但它不提供身份验证功能。因此,在某些实现中,它通常会与数字证书或其他身份验证机制结合使用以防范中间人攻击。