本文回顾了Diffie-Hellman密钥交换方法,并介绍了其在加密通信中的应用。
关于 Diffie Hellman 和 Signal 的 Diffie Hellman 实现(棘轮协议)的回顾。
Diffie Hellman 是一种端到端加密的密钥交换方法,它允许双方安全地通信,通过给予每一方足够的信息来获得相同的秘密,而无需共享该秘密。由 Ralph Merkle、Whitfield Diffie 和 Martin Hellman 于 1976 年开发,并由英国信号情报机构发现。
一些使用 Diffie Hellman 来增强安全性的协议包括:
整个想法是双方同意使用拼图的某些部分,使用这些部分以及只有他们知道的秘密来解决拼图的一部分,然后他们分享已解决的部分以获得共享的秘密。
瞧!现在双方都有了共享的秘密!
传统的 Diffie Hellman 不再是一种安全的选择,因此在应用程序中,我们使用 Diffie Hellman 的不同变体,它们是:
为每个事务创建唯一的密钥,因此即使黑客获得了密钥,他们也只能从单个事务中获取信息,而无法查看过去的信息。
以下是关于 PFS 重要性的有用资源:
目前,RSA 和 Diffie Hellman (DH) 是互联网上最流行的加密算法。RSA 依赖于“因式分解问题”,而 DH 依赖于“离散对数问题”。一种加密算法并不比另一种更好;它们只是解决加密的不同方法,并且根据用例是有益的。
在 RSA 中,用户发布一个公钥,另一方使用该公钥来加密他们的消息。当他们将其发回时,用户可以使用他们的私钥解密消息。如果你想进一步深入了解 RSA,请查看下面的文章:
有人会使用 Diffie Hellman 而不是 RSA,因为它的完全正向保密 (PFS) 功能。
使用 Diffie Hellman 的一些缺点是:
通过使用数字域筛选算法解决大多数离散对数问题,Logjam 攻击成为可能。整个想法是他们可以预先计算 G,因为大多数互联网流量都使用 1024 位或更小的组。一旦他们事先弄清楚了这一点,他们只需要担心解决特定的对数即可。
作者需要数千个 CPU 核心一周才能预先计算单个 512 位素数的数据以执行此攻击。预先计算 1024 位素数大约需要 1 亿美元。
建议使用椭圆曲线 Diffie Hellman 和至少 2048 位来防止 logjam 攻击。使用至少 2048 位会使求解难度比 1024 位素数高 10⁹ 倍。
请查看下面的白皮书,了解有关 Logjam 攻击的更多详细信息:
好消息是有许多经过验证的库已经支持 Diffie Hellman。经验法则是“永远不要编写你自己的加密实现!”
如果你是 NodeJS 开发人员,则可以使用 Crypto 库。以下是指向文档的链接:
以下是使用 Crypto 库实现 Diffie Hellman 的一个简单示例:
import assert from 'assert';
const {
createDiffieHellman
} = await import('crypto');
// Generate Alice's keys...
// 生成 Alice 的密钥...
const alice = createDiffieHellman(2048);
const aliceKey = alice.generateKeys();
// Generate Bob's keys...
// 生成 Bob 的密钥...
const bob = createDiffieHellman(alice.getPrime(), alice.getGenerator());
const bobKey = bob.generateKeys();
// Exchange and generate the secret...
// 交换并生成密钥...
const aliceSecret = alice.computeSecret(bobKey);
const bobSecret = bob.computeSecret(aliceKey);
// OK
assert.strictEqual(aliceSecret.toString('hex'), bobSecret.toString('hex'));
由于 ECDH(椭圆曲线 Diffie Hellman)更受欢迎,因此这里有一个使用 Crypto 库实现 ECHD 的示例:
import assert from 'assert';
const {
createECDH
} = await import('crypto');
// Generate Alice's keys...
// 生成 Alice 的密钥...
const alice = createECDH('secp521r1');
const aliceKey = alice.generateKeys();
// Generate Bob's keys...
// 生成 Bob 的密钥...
const bob = createECDH('secp521r1');
const bobKey = bob.generateKeys();
// Exchange and generate the secret...
// 交换并生成密钥...
const aliceSecret = alice.computeSecret(bobKey);
const bobSecret = bob.computeSecret(aliceKey);
assert.strictEqual(aliceSecret.toString('hex'), bobSecret.toString('hex'));
// OK
Diffie Hellman 更复杂的实现是 Signal 的协议。双棘轮是大多数端到端加密消息应用程序(如 Signal 和 WhatsApp)中使用的实现。
该协议应该在密码学上模拟棘轮工具的功能(只能向前移动),同时使用以下功能:
棘轮技术来自这样的概念:你不能从后面的状态往回工作到之前的状态并解密过去的消息。双重来自于我们使用 KDF(密钥派生函数)链和 X3DH(扩展三重 Diffie Hellman)进行棘轮的事实。
KDF (密钥派生函数) 链
KDF 是一种加密哈希函数,它使用 HMAC 和 HKDF 哈希。它的功能类似于哈希,但它们是一种加密原语。
当 KDF 的一部分输出用作输出密钥,而另一部分用于替换 KDF 密钥时,我们使用术语 KDF 链,然后可以将其与另一个输入一起使用。
下图表示一个 KDF 链处理三个输入并生成三个输出密钥。
在消息传递场景中,第一条消息需要加密,因此它会通过 KDF 函数并生成一个 KDF 密钥和一个输出密钥。KDF 密钥是下一层的输入密钥,输出密钥加密第一条消息。第二条消息进来并且需要加密;发生相同的过程,但是输入密钥来自先前产生的 KDF 密钥,并且输出密钥对于以下消息是新的。
这样做的好处是你具有前向保密,如果密钥被破解,则无法解密过去的消息。它不提供的是未来保密,如果密钥被破解,那么你可以找出链中更下游的密钥。这就是 Diffie Hellman 棘轮发挥作用的地方,它提供了一种自修复特性,可以重置发送和接收 KDF 链。
回到消息传递场景,信使上的每个朋友都有 3 个棘轮,2 个 KDF 棘轮用于发送和接收消息,1 个用于重置消息。Alice 的发送棘轮必须始终与 Bob 的接收棘轮同步,这样他才能加密 Alice 的消息。现在和以后,或者可能在每条消息之后,我们必须重置 KDF 链,这样如果有人破解了 Alice 或 Bob 链中的一个密钥,我们可以保护他们免受未来被破解的其他消息的影响。
X3DH(扩展三重 Diffie Hellman)
X3DH 提供前向保密和密码学上的可否认性。它专为一方离线且需要保存到服务器的异步设置而设计。
X3DH 专为异步设置而设计,在这种设置中,一个用户(“Bob”)处于离线状态,但已将一些信息发布到服务器。 另一个用户(“Alice”)想要使用该信息向 Bob 发送加密数据,并建立用于未来通信的共享密钥。
X3DH 在高级别上执行以下步骤:
查看 Signal 的官方文档 x3DH:
观看下面的视频,了解有关 X3DH 的简单解释:
视频最初在 https://asecuritysite.com/encryption/go_x3dh 上找到
以下是关于双棘轮协议内部运作的官方文档:
以下是双棘轮协议的 java 实现的官方 GitHub:
GitHub - signalapp/libsignal-protocol-java: 用于 Java/Android 的 Signal 协议库
Diffie Hellman 已经存在超过 50 年了,但即使这么多年过去了,它在当今世界仍然非常流行。 即使今天没有人使用原始的 Diffie Hellman 实现,许多协议都是从 Diffie Hellman 派生的,并在我们每天使用的工具中使用,例如 WhatsApp、Signal 或 TLS 3.0。
- 原文链接: medium.com/insatiablemin...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!