博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Diffie-hellman 密匙交换
阅读量:7229 次
发布时间:2019-06-29

本文共 6977 字,大约阅读时间需要 23 分钟。

新的需求

在之前的章节中,Alice 和 Bob 在进行加密通信之前,他们首先需要面对面的共享那个用于加解密的密匙。但是,如果 Alice 和 Bob 无法面对面的交换密匙,将会面临什么问题?

随着计算机网络的普及,人们之间的交流不再受到的地理位置的限制。如果 Alice 和 Bob 之间需要通过计算机网络去进行一些私密消息的传递时,他们就需要将信息加密。于是他们就会在网络通信时首先向对方发送本次通信的密匙,然后发送加密的内容。但是,他们之间总是存在一个窃听者 Eve,他将 Alice 和 Bob 之间的网络通信截取并拷贝下来,然后原封不动的发给另一方。通过这中方式,Eve 就会得到 Alice 和 Bob 之间的密匙,以及全部的加密消息,当然因为有了密匙,他也轻而易举的窃取了全部的通信内容。那么,有没有一种密匙交换方式,可以使得 Alice 和 Bob 在 Eve 的窃听下协商出一个不被 Eve 获知的通信密匙呢?

Diffie-hellman 密匙交换

在 1976 年,Whitfield Diffie 和 Martin Hellman 一起发明了一个让人叫绝的方式,被称为 “迪菲-赫尔曼密钥交换 Diffie–Hellman key exchange 简称 D-H”。D-H 是基于模运算的一个算法。所以首先我们看下什么是模运算。

比如,现在我们有一个圆形的时钟,我们注意到时钟上面的小时刻度将这个时钟的周长分成了 12 个等份,我们简称这个等份为 小时刻度周长等份。然后我们手上有一根绳子,绳子的长度为 15 倍于小时刻度周长等份。现在我们做一件事,将绳子的一头放在时钟的 0 刻度位置(或者 12 刻度),然后顺时针的将绳子沿着时钟的边缘进行一圈一圈的环绕。最后我们会发现绳子的另一头停在了刻度 3 上。简化成一个数学式子就是 15 mod 12 = 3 ,它表示 15 对 12 取模后剩余 3。

我们发现模运算有一个特点,就是对一个数求模,可以容易的得到其求模后的结果。但是如果反过来想获取原本的数却很难。比如 2187 mod 7 = 31594323 mod 7 = 3 等等,如果知道了结果 3,和模 7,无法准确得知原本的数。

接下来,我们看看在使用 D-H 密匙交换方式时,Alice 和 Bob 之间是如何协商出通信密匙的:

  1. 首先 Alice 先要随机选择两个数 a,n 作为模运算的基础,然后再次随机出一个数 x
  2. 然后 Alice 通过一个运算生成一个数 p,p 的运算方式为:
p = a^x mod n复制代码
  1. 然后 Alice 把 p、a、和 n 告诉了 Bob,当然,Eve 也知道了这些内容
  2. 接着, Bob 随机选择一个数 y,并通过下面的运算生成一个数 q:
q = a^y mod n复制代码

在 q 生成了之后,Bob 将其告诉了 Alice,当然,Eve 也得知了 q 5. 现在,Alice 和 Bob 开始生成密匙

// Alicekey = q^x mod n// Bobkey = p^y mod n 复制代码

通过上面的运算,Alice 和 Bob 生成了他们之间的密匙。

现在,你可能很疑惑,那就是为什么经过这一系列的运算后,Alice 和 Bob 之间生成了一把 Eve 不知道的密匙。

我们先来看看 Alice,她接收到了 Bob 传过来的公开信息 q:

q = a^y mod n               1)复制代码

之后,为了得到密匙,她进行了下面的操作:

q^x mod n                   2)复制代码

那么将 1) 中的 q 带入到 2) 中的式子,替换 2) 中的 q,Alice 生成密匙的操作等价于:

(a^y mod n)^x mod n         3)复制代码

再来看看 Bob,他接收到了 Alice 传来的公开信息 p,为了生成密匙,他做了下面的操作:

p^y mod n              4)复制代码

那么我们看看 p 是什么,它是由 Alice 这样生成的:

p = a^x mod n          5)复制代码

这次,我们将 5) 带入到 4) 中,替换 4) 中的 p,然后我们发现 Bob 的操作等价于

(a^x mod n)^y mod n    6)复制代码

现在,我们如果可以证明 3) 和 6) 是等价的话,就可以说明这种方式是可以工作的。

开始求证

上文中,我们通过使用一个绳子沿着时钟的边缘绕圈的例子,对求模运算有了一个形象的认识。现在,如果需要操作一根长度为 136 倍于小时刻度周长等份的绳子的话,你已经知道该如何做了 - 就是将绳子的一头放在 0 刻度,沿着时钟边缘不断地绕圈,看绳子另一头最终落在哪个刻度上。

现在,尝试以相似的方式去理解运算(100+36) mod 12 。你可以想象成,在你准备对一个长度是 136 倍于小时刻度周长等份的绳子进行绕圈之前,绳子不小心断成了两段,一段长度为 100 倍于小时刻度周长等份、另一段长度为 36 倍于小时刻度周长等份(下面就简称 “100 长度”“36 长度”)。

为了完成工作,你先将 100 长度的绳子的一头放在 0 刻度,然后开始沿着时钟边缘进行绕圈,在这个 100 长度的绳子绕完之后,绳子的另一头应该落在某个刻度上,我们使用 (100 mod 12) 去表示这个刻度。然后,你拿起另外一段 36 长度的绳子,也将它的一头放在 0 刻度,开始对时钟进行绕圈,绕完之后,绳子的另一头也落在了某个刻度上,我们使用 (36 mod 12) 去表示这个刻度。最后你将 100 mod 12 加上了 36 mod 12

为什么可以相加? 之前,我们将 36 长度的绳子的一头放在的 0 刻度,通过让绳子沿着时钟边缘不断地顺时针绕圈,使得最终绳子的另一头会落在时钟上的某一个刻度上,我使用 36 mod 12 去表示这个刻度。我们换一个角度,36 mod 12 其实也表示了一个顺时针的偏移量,你可以想象一下,不论起始刻度选在哪里,最终绳子另一头落下的刻度和起始刻度之间总会有一个 36 mod 12 的偏移量。当我们绕完了 100 长度的绳子时,我们知道了它的终点落在了 100 mod 12 这个刻度上,于是,我们拿起 36 长度的绳子,接着 100 长度的绳子的终点继续绕圈。站在偏移量的角度,“将 36 长度的绳子的一头放在 100 长度绳子结束的刻度上,然后让它继续沿着时钟边缘绕圈” 就可以看成是 “在 100 长度绳子结束的刻度上又顺时针偏移了 36 mod 12

所以我们可以让 100 mod 12 加上 36 mod 12 。不过还有一点需要注意,就是在 100 mod 12 的刻度上再顺时针偏移 36 mod 12 的话,可能会超过 0 刻度又开始新的一个绕圈。所以,100 mod 12 加上 36 mod 12 的结果还需要再 mod 12。所以完整的表示就是 (100 mod 12 + 36 mod 12) mod 12

通过这个形象的例子,我们得出一个模运算的加法规律:

(a+b) mod p = (a mod p + b mod p) mod P复制代码

我们可以通过这个加法规律衍生出一个乘法规律:

(a*b) mod p = (a mod p * b mod p) mod p复制代码

下面是关于这个乘法规律的证明:

证明:(a*b) mod p = (a mod p * b mod p) mod p, a、b、p ∈ 正整数∵  对于正整数 a,等式 a = k1*p + r1 一定成立    对于正整数 b,等式 b = k2*p + r2 一定成立∴	a*b = (k1*p + r1 ) * (k2*p + r2)		= k1*k2*p^2 + k1*p*r2 + r1*k2*p + r1*r2∵  (a+b) mod p = (a mod p + b mod p) mod p∴  (a*b) mod p = (k1*k2*p^2 + k1*p*r2 + r1*k2*p + r1*r2) mod p	= (k1*k2*p^2 mod p + k1*p*r2 mod p + r1*k2*p mod p + r1*r2 mod p) mod p	= (0 + 0 + 0 + r1*r2 mod p) mod p	= (r1*r2 mod p) mod p	= r1*r2 mod p∵  r1 = a mod p, r2 = b mod p∴ (a*b) mod p = (a mod p * b mod p) mod p得证复制代码

那么,(a^b) mod p 有什么变换规律呢?因为 a^b = a*a*a*a...*a 一共是 ba 相乘。那么根据上面的乘法规律 (a^b) mod p 其实就是:

(a*a*a*a...*a) mod p = (a mod p * a mod p * a mod p ... * a mod p) mod p复制代码

于是就得出了乘方的规律:

(a^b) mod p = (a mod p)^b mod p复制代码

那么我就开始证明,为什么 Alice 生成密匙的操作与 Bob 生成密匙的操作会得到相同的结果,其实也就是证明上面的 3) 与 6) 等价,即:

(a^y mod n)^x mod n = (a^x mod n)^y mod n   10)复制代码

首先我们结合刚得到的乘方公式,看下 10) 等式的左边:

rule: (a^b) mod p = (a mod p)^b mod pleft:             (a^y mod n)^x mod n通过这样对齐,我们可以将 left 中的 a^y 看做一个整体,于是 left 就可以变换为:      a^y*x mod n复制代码

同样的,对于 10) 等式的右边:

a^x*y mod n复制代码

于是我们发现,左右两边的等式是相同,因而 Alice 和 Bob 可以得到相同的结果。

繁琐的回报

到目前为止 Alice 和 Bob 之间为了协商出一个不被 Eve 获知的密匙可谓是费尽周折。那么,这么做有什么用吗?

首先,我们看看一直在窃听的 Eve 手上有了哪些信息:p,q,a,n 。

然后我们知道,对于密匙生成方式实际就是 a^x*y mod n。在这个生成密匙的式子中,Eve 只直接知道了 a 和 n,对于 x 和 y 他并没有直接获取到。当然,他也获取了 x 和 y 的相关信息,就是 p = a^x mod nq = a^y mod n。于是他只有通过两条式子去逆推出 x 和 y。

如何逆推呢?根据 p = a^x mod n,可以转换成 a^x = k*n + p,已知 a,n,p,通过不断的调整 k 算出可能的 x,同理再不断的算出可能的 y,将它们相乘再配合实际的密匙生成式子 key = a^x*y mod n 猜测所有可能的 key。

使加密更加牢固

回顾一下 Alice 是怎么生成 p 的?

// Alicep = a^x mod n复制代码

我们选几组不同的 a 和 n ,然后不断的调整 x 的大小,看看 p 有怎样的变化:

// 在浏览器控制台中运行var test = function (a, n, x) {    var unique = {}, out = [], p;        for (var i = 1; i < x; i++) {        p = Math.pow(a, i) % n;        out.push(p);        if (unique[p] === true) continue;        unique[p] = true;    }        console.log("Output: ", out.join(', '));    console.log("count: ", out.length);    console.log("%c------------------------------------------------", "color:blue");    console.log("Unique:", Object.keys(unique));    console.log("count: ", out.length);    console.log("%c================================================", "color:red")};复制代码
// test(4, 10, 100);Output:  4, 6, 4, 6, 4, 6, 4, 6, 4, 6, 4, 6, 4, 6, 4, 6, 4, 6, 4, 6, 4, 6, 4, 6, 4, 6, 4, 6, 4, 6, 4, 6, 4, 6, 4, 6, 4, 6, 4, 6, 4, 6, 4, 6, 4, 6, 4, 6, 4, 6, 4, 6, 4, 6, 4, 6, 4, 6, 4, 6, 4, 6, 4, 6, 4, 6, 4, 6, 4, 6, 4, 6, 4, 6, 4, 6, 4, 6, 4, 6, 4, 6, 4, 6, 4, 6, 4, 6, 4, 6, 4, 6, 4, 6, 4, 6, 4, 6, 4count:  99------------------------------------------------Unique: ["4", "6"]count:  99================================================复制代码
// test(3, 10, 100);Output:  3, 9, 7, 1, 3, 9, 7, 1, 3, 9, 7, 1, 3, 9, 7, 1, 3, 9, 7, 1, 3, 9, 7, 1, 3, 9, 7, 1, 3, 9, 7, 1, 3, 8, 4, 6, 6, 0, 6, 8, 2, 6, 6, 4, 2, 4, 0, 8, 8, 4, 2, 0, 4, 8, 8, 0, 4, 2, 4, 0, 2, 4, 4, 0, 2, 8, 4, 6, 2, 8, 4, 0, 8, 6, 6, 0, 4, 8, 2, 8, 2, 8, 0, 6, 8, 2, 8, 4, 0, 6, 2, 6, 0, 0, 0, 2, 6, 4, 0count:  99------------------------------------------------Unique: ["0", "1", "2", "3", "4", "6", "7", "8", "9"]count:  99================================================复制代码
test(3, 11, 100);Output:  3, 9, 5, 4, 1, 3, 9, 5, 4, 1, 3, 9, 5, 4, 1, 3, 9, 5, 4, 1, 3, 9, 5, 4, 1, 3, 9, 5, 4, 1, 3, 9, 5, 3, 9, 7, 0, 4, 4, 1, 5, 4, 8, 0, 0, 6, 5, 1, 9, 5, 4, 9, 6, 0, 9, 3, 0, 0, 6, 5, 7, 3, 2, 2, 1, 1, 3, 3, 0, 7, 10, 6, 4, 4, 2, 0, 8, 1, 5, 1, 10, 4, 9, 6, 7, 9, 4, 1, 10, 7, 0, 0, 8, 2, 6, 1, 3, 5, 1count:  99------------------------------------------------Unique: ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10"]count:  99================================================复制代码

在上面的输出中,我们发现对于式子 p = a^x mod n 来说,当 (a, n) = 1 (读作 a 与 n 互素)时,不断地调整 x,对应的 p 值是 0~n 之间的随机整数。所以说,为了确保 p 的密匙空间足够大,我们在随机选择 a 和 n 时,要确保它们是互素的。在实际操作中,为了简化操作,我们直接随机选择素数的 a 和 素数的 n,这样就可以省略判断 a 和 n 互素的步骤。

至此,我们对 D-H 方法的作用以及原理有了简单的认识。

转载地址:http://fzcfm.baihongyu.com/

你可能感兴趣的文章
Oracle redo解析之-4、rowid的计算
查看>>
Easy Scheduler 1.0.3 发布,分布式工作流任务调度系统
查看>>
java 颠倒整数
查看>>
Python入门教程100天:Day05-练习总结
查看>>
环境搭建,8种基本类型,Static,package和import,log4j
查看>>
即将到来的 Debian 10 Buster 发布版的新特点
查看>>
iOS 头部视图下拉变大
查看>>
Disruptor并发框架
查看>>
react-hooks 实现简单的评论list
查看>>
【多图警告】学会JavaScript测试你就是同行中最亮的仔(妹)
查看>>
19-04-25
查看>>
一个JAVA程序员成长之路分享
查看>>
30K iOS程序员的简述:如何快速进阶成为高级开发人员
查看>>
Go 夜读 - 每周四晚上 Go 源码阅读技术分享
查看>>
tranform知多少
查看>>
Android电量优化
查看>>
[爬虫手记] 我是如何在3分钟内开发完一个爬虫的
查看>>
【译】Css Grid VS Flexbox: 实践比较
查看>>
iOS 开发知识索引
查看>>
Linux iptables命令
查看>>