关闭

迟到 39 年的图灵奖 - Diffie-Hellman 密钥交换原理及例程源代码

91人阅读 评论(0) 收藏 举报

转自:https://zhuanlan.zhihu.com/p/28963344?hmsr=toutiao.io&utm_medium=toutiao.io&utm_source=toutiao.io


1976年,两位年轻的数学家Diffie、Hellman合著发表了一篇名为《New Directions in Cryptography(密码学的新方向)》的论文,他们在论文中提出了DH密钥交换算法以及公钥密码思想。众所周知,公钥密码是互联网得以如此兴旺发达的最重要的基础技术,而DH密钥交换算法及其后续版本(ECDH、DHE、ECDHE)也是互联网不可或缺的基石。在该论文发表了39年之后的2015年,这两位伟大的数学家兼密码学家的杰出贡献终于得到世人的认可,获得了计算机界最高奖项图灵奖。(请参考老宋另一篇短文《比特币底层技术-公钥密码学大事件与时间线》)

在本篇短文中,老宋将以最浅显易懂的例子,介绍DH密钥交换算法基本原理,并给出基于NODE.JS编写的最简单的例程源代码,以供密码学或相关领域入门者参考。

首先,让我们理解一下密码学加密解密的基本原理。以魔方还原为例,一个标准的三阶魔方有27个块,除了中心轴点之外的26个块有无数种可能的组合,如果让一个人每秒钟尝试三次且完全不重复的话,需要尝试4500亿年才能遍历完所有组合情况,从而还原出魔方的六个面,而这时宇宙早已经死了。但是,如果依照魔方还原窍门的话,真人世界纪录是4.37秒,机器人不到1秒就可以还原。

虽然有些牵强,但从某一角度来看,可以理解成密码学就如魔方还原。将明文加密成密文的过程就如打乱魔方,将密文解密成明文的过程就如魔方还原。而密钥就如魔方还原窍门,如果使用魔方还原窍门,那么很快就可以还原魔方;如果使用密钥,很快就可以解密出明文。如果不使用魔方还原窍门,理论上尝试若干年后也是可以还原出魔方的,但是这个时间太久了,我们就认为没有窍门是不可还原的;如果不使用密钥,理论上说尝试若干年后也是可以还原出明文的,但是这个时间太长了,我们就认为没有密钥是不可解密的。

OK,虽然魔方还原与密码学加密解密不完全类似,但是对于入门者来说,可以通过这个例子得到形象的印象,从而让我们看到了密钥的作用及其重要性。互联网是一个不安全的通信通道,想要在这个不安全的信道中安全的通信,最重要的事情有如下两点:

  1. 身份认证
  2. 密钥交换

身份认证很好理解,比如你想访问招行官网,但是你需要确认你所访问的网站真的就是招行官网,而不是别的钓鱼网站。密钥交换是指,你和招行官网之间,需要通过某种方式得到一个相同的密钥,这个密钥是当前会话临时生成的,每次会话都会换一个新的,而且只有你们双方才知道,其它第三方都不知道才行。

本文只介绍密钥交换原理,在互联网安全通信协议SSL/TLS中,有两种常见的密钥交换方式,一种基于RSA算法,一种基于DH算法(实际常用的是DHE、ECDHE)。通过RSA交换密钥并不完美前向,原因请见《比特币底层技术-公钥密码学大事件与时间线》;而基于DH的DHE、ECDHE是完美前向的,下面详细介绍。

DH算法有四个重要数据:

  • 私钥,Private Key,记为x1或x2
  • 公钥,Public Key,记为A或B
  • 底数,generator,记为g
  • 模数,prime,记为p

我们先不考虑模数p。假设下图左右分别代表两个人,即爱丽丝和鲍勃。她们双方想要在不安全的互联网上交换共享密钥。双方首先公开交换底数g。爱丽丝的私钥是x1,并通过底数g做幂运算得到公钥A;鲍勃的私钥是x2,并通过底数g做幂运算得到公钥是B。双方公开交换公钥A和B。所谓公开交换,就是指别人第三方都可以看到g、A、B的内容。但是注意的是,x1和x2(下图红框所示)是爱丽丝、鲍勃各自保密的,是不公开的,也不会让对方知道的。

爱丽丝将鲍勃传过来的公钥B作为底数,用自己的私钥x1做幂运算,得到y1。鲍勃将爱丽丝传过来的公钥A作为底数,用自己的私钥x2做幂运算,得到y2。根据乘法交换律,实际上y1=y2,记为y,因此爱丽丝和鲍勃得到了相同的共享密钥y

那么,因为g、A、B是公开的,别人可否通过g、A、B获得y呢?因为y是B的x1次幂,或者y是A的x2次幂,因此想要得到y,必须得到x1或者x2;而x1和x2是爱丽和鲍勃各自保密的,并不公开,因此别人需要通过计算获得x1或x2,也就是计算以g为底A的对数,或者以g为底B的对数。我们知道,在实数域上,求对数是容易的,可以很容易得到x1或x2。

虽然求对数是容易的,但是求离散对数是困难的,而在有限整数域上求离散对数更加困难,这个求解过程,就好像前边的魔方还原一样,如果不知道窍门,那么可以认为不可求解。

如下图所示,爱丽丝和鲍勃将g、x1、x2、A、B的作用域限定在整数域上,同时再引入模数p将作用域进一步限定在有限整数域上。这样的话,可以认为不可能通过g、A、B、p求得x1或x2,也就是说,别人是不可能获得爱丽丝或鲍勃的共享密钥y的,就是说y只有爱丽丝和鲍勃才知道,她们在保留自己的秘密x1及x2的情况下,成功交换了共享密钥。

下图展示了实数域上的指数函数整数域上的离散指数函数、以及有限整数域上的离散指数函数,可以看到加上“有限”二字之后,指数的逆运算几乎就是不可能的了,至少目前还没有数学算法能快速求解有限整数域上的离散对数。

为什么取模会让逆运算变得异常复杂呢,可以这样简单的理解,比如一个小孩拿着一个钟表,将时针旋转了很多圈后,指向了2点的位置,然后他问你,刚才他转了多少圈?是不是回答不出来。这就是取模的威力。

NODE.JS提供的CRYPTO库支持DH算法,下边通过简单的NODE.JS代码示例,进一步介绍DH算法的应用,并打印输出DH算法相关数据的内容,从而给大家一个形象的认知。

首先,爱丽丝以模数p的长度为512位作为参数,用crypto.createDiffieHellman()方法创建DH对象alice。爱丽丝再通过generateKeys()方法生成一对自己的新的私钥和公钥,该方法返回公钥,而私钥会在alice对象内部保存,如果想把私钥拿出来看一看,可以用getPrivateKey()方法。因为调用crypto.createDiffieHellman()时没有指定底数g,所以底数g默认为2。

爱丽丝将公开的模数p和底数g公开出来,提供给鲍勃;鲍勃用它们作为参数,也调用crypto.createDiffieHellman()方法,生成DH对象bob。鲍勃调用generateKeys()方法生成一对自己的新的私钥和公钥,该方法返回公钥,而私钥会在bob对象内部保存,如果想把私钥拿出来看一看,可以用getPrivateKey()方法。

爱丽丝将自己的公钥aliceKey公开提供给鲍勃,鲍勃将自己的公钥bobKey公开提供个爱丽丝。双方各自在自己的DH对象上,将对方的公钥作为参数,调用computeSecret()方法,计算共享密钥,得到了相同的共享密钥,即上文中所述的y。

[root@DH tmp]# cat example.js 
const crypto = require('crypto');
const assert = require('assert');

// Generate Alice's keys...
const alice = crypto.createDiffieHellman(512);
const aliceKey = alice.generateKeys(); // generate Private/Public Keys; return Public Key
const alicePubKey = alice.getPublicKey(); // the same as aliceKey
const alicePrivKey = alice.getPrivateKey();

// Generate Bob's keys...
const bob = crypto.createDiffieHellman(alice.getPrime(), alice.getGenerator());
const bobKey = bob.generateKeys(); // generate Private/Public Keys; return Public Key
const bobPubKey = bob.getPublicKey(); // the same as bobKey
const bobPrivKey = bob.getPrivateKey();

// Exchange and generate the secret...
const aliceSecret = alice.computeSecret(bobKey);
const bobSecret = bob.computeSecret(aliceKey);

// OK
assert.strictEqual(aliceSecret.toString('hex'), bobSecret.toString('hex'));

[root@DH tmp]# 

为了给入门读者密码学数据数量级的认识,在上边例程中增加打印,打印输出如下,可以看到,底数g是2很小的,而模数p、公钥、私钥都是非常大的大数,最终计算得到的共享密钥y也是非常大的大数。注意,模数p和私钥同时都是质数。

[root@DH tmp]# node example_with_print.js 

aliceKey          :6598fe48bea0c2e24efa287765a745dae423d47599395b863a4d9d558cd405eaac6a7fe86038d2f769fdf4095bf4a3aad756f50ebac4f72f6b02aa9ab59df9d2
alicePubKey       :6598fe48bea0c2e24efa287765a745dae423d47599395b863a4d9d558cd405eaac6a7fe86038d2f769fdf4095bf4a3aad756f50ebac4f72f6b02aa9ab59df9d2
alicePrivKey      :6b6823abf966591660c8a60373cdff03c30404749e926c6f2403f0598c5c85db238d6557a934b6e53ad5d27e2b4402720299ebd5c1b25c61aff425eb707ad5d1
alice's prime     :d068804c7e01cf922907fd6dc909c6a7ee96b6e9ec66b60be52416e47a02c93a9a1bc63762c238c291880b474755b14d8cd61d24e9298791ac4baa91ad6356a3
alice's generator :02

bobKey          :2840567fe7badf92c1f8d6d172c53a533917ac3df7e30b0fd83cc44ee86fb9ffbefa2788bfe12839a7c63b0e1fb7c808196c7ba21304aa044a4394aa295b7bc5
bobPubKey       :2840567fe7badf92c1f8d6d172c53a533917ac3df7e30b0fd83cc44ee86fb9ffbefa2788bfe12839a7c63b0e1fb7c808196c7ba21304aa044a4394aa295b7bc5
bobPrivKey      :7b6c4d227be43731ee87f526fbc313175f9de76c4e429a72a1988ec9e0d0d0f3a9dcb8140440f25b596ff3879495f71bf0afb862cc74658b2f32bc1da044b6e1
bob's prime     :d068804c7e01cf922907fd6dc909c6a7ee96b6e9ec66b60be52416e47a02c93a9a1bc63762c238c291880b474755b14d8cd61d24e9298791ac4baa91ad6356a3
bob's generator :02

aliceSecret   :326558f71d0c54666469794d2727a333660c2620038cc1db1c31501f0a1d154672b18509f4d010a5c4783c075f5302cdf8a9f3b85efcf93c56622e47afdea5de
bobSecret     :326558f71d0c54666469794d2727a333660c2620038cc1db1c31501f0a1d154672b18509f4d010a5c4783c075f5302cdf8a9f3b85efcf93c56622e47afdea5de
[root@DH tmp]# 

需要注意的是,DH密钥交换不能抵抗中间人攻击,所以为了避免交换得到中间人的假密钥,DH密钥交换必须在身份认证之后才能进行。

正如本文所述,DH密钥交换算法思想非常容易理解和使用,正是这样简单易行的算法为人类整个互联网通讯提供了强大安全保障,互联网业务尤其是金融电商等才得以百花齐放兴盛繁荣。从1976到2015,图灵奖迟到了39年,Diffie、Hellman的确当之无愧。

Reference:

0. 老宋的独家号

1. Diffie-Hellman key exchange

2. New Directions in Cryptography (1976)

3. 比特币底层技术-公钥密码学大事件与时间线

4. Node.js

注:本文为老宋原创文章,转载前请至【知乎专栏-老宋的独家号】点赞或评论建议。


0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:350399次
    • 积分:3831
    • 等级:
    • 排名:第8689名
    • 原创:28篇
    • 转载:202篇
    • 译文:0篇
    • 评论:31条
    文章分类
    最新评论