云计算时代安全综述-秘钥交换(上)

如题所述

第1个回答  2022-06-24
离上篇文章认证加密(下)发表已经过去好久了,笔者一直在思考要不要继续写安全基础类的文章,直到本周日晚上陪孩子看朗读者节目的时候,特别是节目组邀请到了53岁的清华大学高等研究院杨振宁讲座教授王小云,介绍了她在密码学中的贡献。孩子和家人在观看节目的时候,对MD5是什么,为什么这么重要,特别是王教授谈到基于MD5设计的国家加密标准已经广泛应用到银行卡,社保卡等领域,让加密这个古老但年轻的领域走入更多人的视野。

咱们前边介绍的内容主要围绕对称加密,从这篇文章开始,我们的焦点shift到非对称加密算法上,非对称加密也称作是公钥加密算法,整个算法有个非常关键的环节:秘钥交换。秘钥交换“人”如其名,解决的本质问题是如何安全的交换秘钥。咱们还是请出老朋友爱丽斯女王和鲍勃领主来说明一下。假设爱丽丝女王和鲍勃领主要安全的通信,那么爱丽斯女王和鲍勃领主就把各自的秘钥发给对方。结果是通信的双方都持有这个共享的秘钥,这个共享的秘钥就可以被用来后续信息安全的交互。

为了让后续的讨论更加接地气,咱们假设爱丽斯女王和鲍勃领主从来都没有见过面,那么我们该如何让女王和领主安全的通信呢?这个问题也是秘钥交换算法适用的最原始应用场景。为了确保女王和领主之间通信的隐私性,双方需要一个共享的秘钥,但是安全的沟通共享秘钥并没有想象中那么简单。如果恶意攻击者窃听了女王和领主的电话通信,或者邮件通信(假设传输的明文信息),那么恶意攻击者会窃取到女王和领主共享的秘钥,后续双方所有的通信内容,都可以通过这个秘钥来破解,女王和领主的所有私密通信不安全了,通信内容已经成为整个王国茶余饭后的谈资。

如何解决这个问题呢?这是秘钥交换算法要解决的核心问题,简单来说,通过秘钥交换算法,爱丽丝女王和鲍勃领主就可以安全的实现共享秘钥交换,即便是有恶意攻击者在监听所有的通信线路,也无法获取双方通向的秘钥,女王和领主终于可以无忧无虑的八卦了。

秘钥交换从通信双方生成各自的秘钥开始,通常情况下非对称加密算法会生成两个秘钥:公钥和私钥(public key和private key)。接着通信的双方分别把自己的公钥发送给对方,公钥的”公“在这里是公开的意思,这就意味着恶意攻击者也可以获得通信双方生成的公钥信息。接着女王和领主分别用收到的公钥和自己持有的私钥结合,结果就是共享的通信秘钥。大家可以站在恶意攻击者的角度看这个公钥,由于恶意攻击者没有任何一方的私钥,因此恶意攻击者是无法获取女王和领主通信用的”共享“秘钥。关于共享秘钥在女王和领主侧产生的过程,如下图所示:

了解了秘钥交换算法的大致工作机制后,接着我们来看看秘钥交换算法是如何解决爱丽斯女王和鲍勃领主安全通信问题。如上图所展示的过程,女王和领主通过秘钥交换算法确定了可以用作安全通信的秘钥,这个秘钥可以被用作认证加密的秘钥,因此即便是MITM(中间人攻击者)截获了女王和领主通信的数据,但是由于没有秘钥,因此通信的内容不会被破解,这样女王和领主就可以安全的通信了,如下图所示:

不过这里描述的内容稍微不严谨,我们顶多只能把这种场景称作passive MITM,大白话是说恶意攻击者是被动的在进行监听,和active MITM的主要却别是,active中间人会截获秘钥交换算法交换的数据,然后同时模拟通信双方对端的角色。具体来说,中间人会actively来同时和女王以及领主进行秘钥交换,通信双方”以为“和对方对共享秘钥达成了共识,但是本质上女王和领主只是和中间人达成了共享秘钥的共识。大家可以思考一下造成这种错误认知的原因是啥?

其实背后的原因不难理解,因为通信的双方并没有其他手段判断收到的公钥和通信的对端的持有关系,我们也称作这种秘钥交换为”unauthentiated“秘钥交换,如下图所示:

那么如何解决active MITM攻击呢?相信大家能够猜到authenticated key exchange,咱们先通过一个具体的业务场景来看看,为啥我们需要这种authenticated的模式。假设我们开发了一套提供时间信息的服务,服务被部署在阿里云上,我了预防时间数据被恶意攻击者修改,因此我们使用MAC(message authentication code),如果大家对MAC没有什么概念,请参考笔者前边的文章。

MAC需要秘钥来对数据进行机密性和完整性保护,因此我们在应用部署的时候,生成了一个秘钥,然后这个秘钥被以某种方式非法给所有的客户端用户,应用运行的非常稳定,并且由于有秘钥的存在,守法遵纪的所有客户端都可以读取到准确的时间。但是有个客户学习了本篇文章后,发现这个秘钥可以用来篡改数据,因此我们的网站受到大量客户的投诉,说读到的时间不准确,造成系统的业务运行和数据处理出现问题。

你让架构师赶紧处理,架构师给出了每个用户都生成独享秘钥的方案,虽然能够止血,但是很快你会发现这种方案不可行,不可运维,随着用户数量激增,我们如何配置和管理这些秘钥就变成了一个大问题,还别说定期更换。秘钥交换算法在这里可以派上用场,我们要做的是在服务端生成秘钥,然后为每个新用户提供公钥信息。由于用户端知道服务端的公钥信息,因此MITM攻击就无法在中间双向模拟,我们也称这种模式为:authenticated key exchange。

我们继续分析这个场景,中间人虽然说也可以和服务进行秘钥交换,但是这个时候中间人和普通的客户端就没有差异了,因此也就无法执行active MITM攻击了。

随着科技的发展,互联网几乎在我们生活中无孔不入,如何安全的在通信双方之间确立秘钥就变得极其重要。但是咱们前边介绍的这种模式扩展性不强,因为客户端需要提前预置服务端的公钥,这在互联网场景下尤其明显。举个例子,作为用户,我们希望安全的和多个银行网站,社保网站进行数据通信,如果需要手机,平板,台式机都预置每个网站的公钥信息才能安全的进行访问,那么你可以考虑便利性会有多差,以及我们如何安全的访问新开发的网站?

因此读者需要理解一个非常重要的点,秘钥交换非常重要,但是有上边介绍的扩展性问题,而这个问题的解决是靠数字签名技术,数字签名和秘钥交换结合起来是我们后边要介绍的SSL技术的基础,要讲清楚需要的篇幅会很长,因此咱们后续用专门的章节来介绍SSL原理。不过为了后续介绍的顺畅性,咱们接下来聊几个具体的秘钥交换算法,以及背后的数学原理。

咱们先从笔者系列文章第一篇中提到的Diffie-Hellman秘钥交换算法说起,Whitfield Diffie和Martin E. Hellman在1976年发表了一篇开创新的论文来介绍DH(Diffie-Hellman)秘钥交换算法,论文中把这个算法称作”New Direction in Cryptography“。这篇论文被冠以开创性的主要原因是论文两个第一:第一个秘钥交换算法以及第一次公开发表的公钥加密算法(或者说非对称加密算法)。

DH算法的数据原理是群论(group theory),这也是我们今天所接触到的所有安全机制的基石。因为笔者并不是数学专业毕业,数学基础也不是太牢固,因此一直犹豫要如何继续在安全的角度继续深入下去。为了让这个算法更加容易被读者理解,因此后边的内容会稍微涉及到一些数据基础知识,相信有过高中数学知识的同学,应该都能看懂。

要介绍群论,首要问题是定义清楚什么是群(group)。笔者查阅了相关资料,群在数学领域中有如下两个特征:

1,由一组元素组成

2,元素之间定义了特殊的二元运算符(比如➕或者✖️)

基于上边的定义,如果这组元素以及之上定义的二元操作符满足某些属性,那么我们就称这些元素组成个group。对于DH算法来说,背后使用的group叫做multiplicative group:定义了乘法二元运算符的元素集合。读者可能会问,那么这个multiplicative group具体满足那些属性呢?由于这部分的内容较多,咱们来一一罗列介绍:

- Closure(闭包)。集合中的两个元素通过定义的运算符计算后,结果也在集合中。举个例子,比如我们有集合M,M中有元素a,b和c(c=a*b),那么这三个元素就符合closure属性,集合上定义的运算符是乘法。

- Associativity(可结合性)。这个和中学数学中的结合性概念一致,你能理解数学公式a × (b × c) = (a × b) × c就行。

- Identity element(单位元素)。集合中包含单位元素,任何元素和单位元素经过运算符计算后,元素的值不发生变化。比如我们有集合M,包含的元素(1,a,b,c....),那么1就是单位元素,因为1*a = a,a和单位元素1通过运算符计算后,结果不变。

- Inverse element(逆元素)。集合中的任何元素都存在逆元素,比如我们有集合元素a,那么这个元素的逆元素是1/a,元素a和逆元素通过运算符计算后,结果为1。

笔者必须承认由于我粗浅的数学知识,可能导致对上边的这四个属性的解释让大家更加迷惑了,因此准备了下边这张图,希望能对群具备的4个属性有更加详细的补充说明。

有了前边关于群,群的属性等信息的介绍,咱们接着来具体看看DH算法使用的group具体长啥样。DH算法使用的群由正整数组成,并且大部分情况下组成群的元素为素数,比如这个群(1,2,3, ....,p-1),这里的p一般取一个很大的素数,为了保证算法的安全性。

注:数学上对素数的定义就是只能被自己和1整除的数,比如2,3,5,7,11等等。素数在非对称加密算法中有非常广泛的应用。计算机专业的同学在大学期间应该写过寻找和打印素数的程序,算法的核心就是按顺序穷举所有的数字,来判断是否是素数,如果是就打印出来。不过从算法的角度来看,这样穷举的模式效率不高,因此业界也出现了很多高效的算法,很快就能找到比较大的素数。

DH算法使用的群除了元素是素数之外,另外一个属性是模运算符,具体来说叫modular multiplication运算。咱们先从模运算开始,模运算和小学生的一些拔高数学题很类似,关注的是商和余数。比如我们设modulus为5,那么当数字大于5的时候,就会wrap around从1重新开始,比如数字6对5求模计算后,结果是1,7的结果是2,以此类推。对于求模计算最经典的例子莫过于钟表了,一天24个小时,因此当我们采用12小时计数的时候,13点又被成为下午1点,因为13 = 1*12 + 1(其中12为modulo)。

接着我们来看modular multiplication的定义,我们以6作例子,6 = 3 ✖️ 2, 如果modulo是5的话,我们知道6全等于(congruent to)1 modulo 5,因此我们的公式就可以写成:

3 × 2 = 1 mod 5

从上边的等式我们得出了一个非常重要的结论,当我们把mod 5去掉后,就得出3 × 2 = 1,那么3和2就互为逆元素。

最后我们来总结一下DH算法base的群的两个特征:

- Commutative(交换律),群中两个元素计算具备交换律,也就是ab=ba,通常我们把具备交换律的群成为Galois group

- Finite field(有限域),关于有限域的特征我们下边详细介绍

DH算法定义的group也被称作为FFDH(Finite Field Diffie-Hellman),而subgroup指的是group的一个子集,我们对子集中的元素通过定义的运算符操作后,会到到另外一个subgroup。

关于群论中有个非常重要的概念是cyclic subgroup,大白话的意思是通过一个generator(或者base)不断的和自己进行乘法运算,如下变的例子,generator 4可以了subgroup 1和4:

4 mod 5 = 4

4 × 4 mod 5 = 1

4 × 4 × 4 mod 5 = 4 (重新开始,这也是cylic subgroup的体现)

4 × 4 × 4 × 4 mod 5 = 1

等等

当我们的modulus是素数,那么群中的每个元素都是一个generator,可以产生clylic subgroup,如下图所示:

最后我们完整的总结一下群和DH定义的Galois群:

- group就是一组定义了二元操作的元素集合,并具备closure, associativity, identity element, inverse element属性

- DH定义的群叫Galois group,组成群的元素是素数,并在群上定义了modular multiplication运算

- 在DH定义的群中,每个元素都是一个generator,重复和自己相乘后,产出subgroup

Groups是很多加密算法的基础,笔者这是只是稍微的介绍了一点皮毛知识,如果读者对这部分感兴趣,可以查阅相关的材料。有了群的初步认识了,咱们下篇文章来介绍DH算法背后的工作原理,敬请期待!