密钥交换(密钥协商)算法及其原理
本⽂转载⾃
1. 导语
本系列的,咱们聊了“密钥交换的难点”以及“证书体系”的必要性。今天这篇来介绍⼀下实战中使⽤的“密钥协商算法”。
2. 密钥交换/协商机制要达到啥⽬的?
介绍了 SSL/TLS 的⾝份认证机制。这个机制是为了防⽌攻击者通过【篡改】⽹络传输数据,来假冒⾝份,以达到“中间⼈攻击/MITM”的⽬的。
⽽今天要聊的“密钥协商机制”是:(在⾝份认证的前提下)如何规避【偷窥】的风险。
通俗地说,即使有攻击者在偷窥你与服务器的⽹络传输,客户端(client)依然可以利⽤“密钥协商机制”与服务器端(server)协商出⼀个⽤来加密应⽤层数据的密钥(也称“会话密钥”)。
3. 密钥交换/协商机制的⼏种类型
俺总结了⼀下,⼤致有如下⼏种类型:
依靠⾮对称加密算法
原理:拿到公钥的⼀⽅先⽣成随机的会话密钥,然后利⽤公钥加密它;再把加密结果发给对⽅,对⽅⽤私钥解密;于是双⽅都得到了会话密钥。
举例:
依靠专门的密钥交换算法
原理:这个原理⽐较复杂,⼀两句话说不清楚,待会⼉聊到 DH 的那个章节会详谈。
举例:及其变种
依靠通讯双⽅事先已经共享的“秘密”
原理:既然双⽅已经有共享的秘密(这个“秘密”可能已经是⼀个密钥,也可能只是某个密码/password),只需要根据某种⽣成算法,就可以让双⽅产⽣相同的密钥(并且密钥长度可以任意指定)
举例:和(可能很多同学没听过这俩玩意⼉。别担⼼,本⽂后续部分有介绍)
4. 基于 RSA 的密钥协商
概述
这⼤概是 SSL 最古⽼的密钥协商⽅式 — — 早期的 SSLv2 只⽀持⼀种密钥协商机制,就是它。的时候,也是拿 RSA 来演⽰。
是⼀种【⾮】对称加密算法。在本系列的背景知识介绍中,已经聊过这种算法的特点 — — 加密和解密⽤使⽤【不同的】密钥。并且“⾮对称加密算法”既可以⽤来做“加密/解密”,还可以⽤来做“数字签名”。
密钥协商的步骤
拍了拍怎么弄(下列步骤只阐述原理,具体的协议细节在下⼀篇讲)
1. 客户端连上服务端
2. 服务端发送 CA 证书给客户端
3. 客户端验证该证书的可靠性
4. 客户端从 CA 证书中取出公钥
5. 客户端⽣成⼀个随机密钥 k,并⽤这个公钥加密得到 k’
6. 客户端把 k’ 发送给服务端
7. 服务端收到 k’ 后⽤⾃⼰的私钥解密得到 k
8. 此时双⽅都得到了密钥 k,协商完成。
如何防范偷窥(嗅探)
如何防范篡改(假冒⾝份)
5. 基于 DH 的密钥协商
特小吃加盟排行榜概述
DH 算法⼜称“Diffie–Hellman 算法”。这是两位数学⽜⼈的名称,他们创⽴了这个算法。该算法⽤来实现【安全的】“密钥交换”。它可以做到 — — “通讯双⽅在完全没有对⽅任何预先信息的条件下通过不安全信道创建起⼀个密钥”。这句话⽐较绕⼝,通俗地说,可以归结为两个优点:
1. 通讯双⽅事先【不】需要有共享的秘密。
2. ⽤该算法协商密码,即使协商过程中被别⼈全程偷窥(⽐如“⽹络嗅探”),偷窥者也【⽆法】知道协商得出的密钥是
啥。
但是 DH 算法本⾝也有缺点 — — 它不⽀持认证。也就是说:它虽然可以对抗“偷窥”,却⽆法对抗“篡改”,⾃然也就⽆法对抗“中间⼈攻击/MITM”(在本系列的,俺已经强调过了 — — 缺乏⾝份认证,【必定会】遭到“中间⼈攻击/MITM”)。
为了避免遭遇 MITM 攻击,DH 需要与其它签名算法(⽐如、、)配合 — — 靠签名算法帮忙来进⾏⾝份认证。当 DH 与 RSA 配合使⽤,称之为“DH-RSA”,与 DSA 配合则称为“DH-DSA”,以此类推
反之,如果 DH 【没有】配合某种签名算法,则称为“DH-ANON”(ANON 是洋⽂“匿名”的简写)。此时会遭遇“中间⼈攻击/MITM”。(具体的中间⼈攻击⼿法,可以参见本系列)
关于该算法的更多介绍,可以参见()。
数学原理
(如果你属于那种“看了数学公式就犯晕的⼈”,可以直接略过本⼩节,不影响你看后续的章节)
从概念上讲:DH 依赖的是:求解“离散对数问题”的复杂性。具体的算法如下:
通讯双⽅(张三、李四)需要先约定好算法参数(algorithm parameters):⼀个素数 p 作为模数,⼀个素数 g 作为基数(g 也称为“⽣成元”)。这两个算法参数是可以对外公开滴。
对于张三⽽⾔,需要先想好⼀个秘密的⾃然数 a 作为私钥(不能公开),然后计算 A = ga mod p 作为⾃⼰的公钥(可以公开)。
对李四⽽⾔也类似,先想好⼀个秘密的⾃然数 b 作为私钥(不能公开),然后计算 B = gb mod p 作为⾃⼰的公钥(可以公开)。
张三和李四互相交换各⾃的公钥。
然后张三计算出 k = Ba mod p,李四计算出 k = Ab mod p
同学聚会主持词该算法⾄少确保了如下⼏点:
1. 张三和李四分别计算出来的 k 必定是⼀致的
2. 张三和李四都⽆法根据已知的数来推算出对⽅的私钥(张三⽆法推算出 b,李四⽆法推算出 a)
3. 对于⼀个旁观者(偷窥者),虽然能看到 p,g,A,B,但是⽆法推算出 a 和 b(就是说,旁观者⽆法推算出双⽅的私
钥),⾃然也⽆法推算出 k
举例
前⾯说得都是符号,⽐较抽象。下⾯拿具体数字举例:
假设约定的算法参数:模数是 97,基数是 3
张三⽤的私钥是 6,李四⽤的私钥是 21,⽤ python 代码演⽰如下(python 语⾔⽤两个连续星号表⽰“幂运算”,⽤百分号表⽰“取模运算”):
*p = 97
g = 3
a = 6
b = 21
A = (ga) % p
B = (gb) % p
print((Ba) % p) # 此处输出 47 print((Ab) % p) # 此处输出 47*
最后打印出来的两个 47 就是双⽅都计算出了【相同的】结果(这个数值可以⽤作之后的“会话密钥”)
上⾯因为是举例,⽤的数字都⽐较⼩。在实战中需要注意如下⼏点,以降低被攻击的风险。
1. p 必须是质数且⾜够⼤(⾄少300位)
2. a,b 也要⾜够⼤(⾄少100位),且必须是随机⽣成。
3. g 必须是质数,【不】需要很⼤,⽐如 2 或 3 或 5 都可以。g 如果太⼤并【不能】显著提升安全性,反⽽会影响性能。
网游 排行榜密钥协商的步骤
(下列步骤只阐述原理,具体的协议细节在下⼀篇讲)
1. 客户端先连上服务端
2. 服务端⽣成⼀个随机数 s 作为⾃⼰的私钥,然后根据算法参数计算出公钥 S(算法参数通常是固定的)
3. 服务端使⽤某种签名算法把“算法参数(模数p,基数g)和服务端公钥S”作为⼀个整体进⾏签名
4. 服务端把“算法参数(模数p,基数g)、服务端公钥S、签名”发送给客户端
5. 客户端收到后验证签名是否有效
6. 客户端⽣成⼀个随机数 c 作为⾃⼰的私钥,然后根据算法参数计算出公钥 C
7. 客户端把 C 发送给服务端
8. 客户端和服务端(根据上述 DH 算法)各⾃计算出 k 作为会话密钥
如何防范偷窥(嗅探)
嗅探者可以通过监视⽹络传输,得到算法参数(模数p,基数g)以及双⽅的公钥,但是【⽆法】推算出双⽅的私钥,也【⽆法】推算出会话密钥(这是由 DH 算法在数学上保证的)
如何防范篡改(假冒⾝份)
flash课件制作DH 的变种 — — 基于“椭圆曲线”的 ECDH
DH 算法有⼀个变种,称之为 ECDH(全称是“Elliptic Curve Diffie-Hellman”)。维基条⽬在“”
它与 DH 类似,差别在于:
DH 依赖的是 — — 求解“离散对数问题”的困难。
ECDH 依赖的是 — — 求解“椭圆曲线离散对数问题”的困难。
ECDH 的数学原理⽐ DH 更复杂。考虑到本⽂读者⼤都【不是】数学系出⾝,俺就不展开了。
ECDH 跟 DH ⼀样,也是【⽆认证】的。同样需要跟其它签名算法(⽐如、、)配合。
6. 基于 PSK 的密钥协商
概述
PSK 是洋⽂“Pre-Shared Key”的缩写。顾名思义,就是【预先】让通讯双⽅共享⼀些密钥(通常是【对称加密】的密钥)。所谓的【预
先】,就是说,这些密钥在 TLS 连接尚未建⽴之前,就已经部署在通讯双⽅的系统内了。
这种算法⽤的不多,它的好处是:
1. 不需要依赖公钥体系,不需要部属 CA 证书。
2. 不需要涉及⾮对称加密,TLS 协议握⼿(初始化)时的性能好于前述的 RSA 和 DH。
更多介绍可以参见,链接在“”。
密钥协商的步骤
(由于 PSK ⽤的不多,下⾯只简单介绍⼀下步骤,让⼤伙⼉明⽩其原理)
在通讯【之前】,通讯双⽅已经预先部署了若⼲个共享的密钥。
为了标识多个密钥,给每⼀个密钥定义⼀个唯⼀的 ID
协商的过程很简单:客户端把⾃⼰选好的密钥的 ID 告诉服务端。
如果服务端在⾃⼰的密钥池⼦中到这个 ID,就⽤对应的密钥与客户端通讯;否则就报错并中断连接。
如何防范偷窥(嗅探)
使⽤这种算法,在协商密钥的过程中交换的是密钥的标识(ID)⽽【不是】密钥本⾝。
就算攻击者监视了全过程,也⽆法知晓密钥啥。
如何防范篡改(假冒⾝份)
PSK 可以单独使⽤,也可以搭配签名算法⼀起使⽤。
对于单独使⽤
如果攻击者篡改了协商过程中传送的密钥 ID,要么服务端发现 ID ⽆效(协商失败),要么服务端得到的 ID 与客户端不⼀致,在后续的通讯步骤中也会发现,并导致通讯终⽌。
(下⼀篇讲具体协议的时候会提到:协议初始化/握⼿阶段的末尾,双⽅都会向对⽅发送⼀段“验证性的密⽂”,这段密⽂⽤各⾃的会话密钥进⾏【对称】加密,如果双⽅的会话密钥不⼀致,这⼀步就会失败,进⽽导致握⼿失败,连接终⽌)
对于搭配签名算法
如果攻击者篡改了协商过程中传送的密钥 ID,验证签名会失败
不知道做什么工作
补充说明
PSK 与 RSA 具有某种相似性 — — 既可以⽤来搞“密钥协商”,也可以⽤来搞“⾝份认证”。
所以,PSK 可以跟 DH(及其变种)进⾏组合。例如:DHE-PSK、ECDHE-PSK
关于 PSK 的更多细节,可以参见
7. 基于 SRP 的密钥协商
概述
SRP 是洋⽂“Secure Remote Password”的缩写。这个算法有点类似于刚才提到的 PSK — — 只不过 client/server 双⽅共享的是⽐较⼈性化的密码(password)⽽不是密钥(key)。该算法采⽤了⼀些机制(盐/salt、随机数)来防范“嗅探/sniffer”或“字典猜解攻击”或“重放攻击”。
这个算法应该⽤得很少 — — OpenSSL 直到2012年才开始⽀持该算法。所以俺这⾥就不展开了。有兴趣的同学可以去看的协议描述。
密钥协商的步骤
(由于 SRP ⽤的不多,俺偷懒⼀下,略去此⼩节)
8. 扫盲⼀下“前向保密(PFS)
【回溯性破解】及其危险性
从技术上讲,攻击者如果能够对通讯双⽅进⾏【嗅探】,也就能够把通讯双⽅的传输数据存储下来。如果攻击者⽐较⽜逼,以⾄于能拿到通讯双⽅的私钥,那就【有可能】根据私钥推导出会话密钥,从⽽解密之前存储的历史数据。
有些同学可能会问:攻击者如何拿到私钥捏?常见的情况有如下⼏种:
1. ⼊侵双⽅的操作系统(搞定了操作系统⾃然就能搞定系统中存储的私钥);
2. 利⽤协议【设计】的漏洞(能达到这种⽔准的,通常是 NSA 之类的国家队,养了⾜够多的密码学家)
3. 利⽤协议【实现】的安全漏洞(⽐如前⼏年惊艳全球的“”,【有可能】会导致私钥泄漏。协议本⾝没问题,是 OpenSSL
的【代码实现】出了 bug)
4. 通过(⽐如政府部门可以直接要求本国的⽹站交出私钥)。
容易遭受回溯破解的密钥协商算法
本⽂前⾯提到了⼏种密钥交换/协商算法,如下这⼏种特别容易遭受“回溯破解”。
RSA
攻击者事先存储了通讯的密⽂(历史数据)。
由于 RSA 的私钥是稳定的(长期不变)。假设有⼀天,攻击者拿到了 RSA 的私钥,就可以⽤这个私钥解密握⼿过程的密⽂,从⽽得到会话密钥(session key),然后⽤会话密钥解密会话的密⽂,得到会话的明⽂。
PSK(Pre-Shared Key)
攻击者事先存储了通讯的密⽂(历史数据)。
由于双⽅共享的 key 是稳定的(长期不变)。如果有⼀天,攻击者拿到了通讯双⽅共享的 key,就可以⽤这个 key 解密握⼿过程的密⽂,从⽽得到会话密钥(session key),然后⽤会话密钥解密会话的密⽂,得到会话的明⽂。
SRP(Secure Remote Password)
攻击者事先存储了通讯的密⽂(历史数据)。
由于双⽅共享的 password & salt 是稳定的(长期不变)。如果有⼀天,攻击者拿到了通讯双⽅共享的 password 和 salt,就可以⽤来解密握⼿过程的密⽂,从⽽得到会话密钥(session key),然后⽤会话密钥解密会话的密⽂,得到会话的明⽂。
解决⽅法 — — “前向保密/完美正向加密”
相⽐前⾯这⼏种密钥协商算法,DH 和 ECDH 是⽐较能抗“回溯破解”滴。为啥这么说捏?下⾯解释:
对于 DH 算法,通讯双⽅握⼿需要⽣成各⾃的私钥(前⾯提到的整数 a 和 b),然后根据 DH 算法计算得出会话密钥。换句话说,会话密钥依赖于双⽅的私钥 a 与 b。DH 算法的优势在于 — — 双⽅的私钥(a & b)是可以【动态⽣成】滴!
为了对抗“回溯性破解”,可以强制要求双⽅每次都⽣成【随机的】私钥。⽽且每次⽣成的两个私钥⽤完就丢弃(销毁)。如此⼀来,攻击者就难以破解过往的历史数据。DH 算法经过如此改良之后叫做 DHE(追加的字母 E 表⽰ ephemeral)。
与 DH 类似,ECDH 也可以做类似的改良,变成 ECDHE,以对抗“回溯破解”。
能够对抗“回溯破解”的密钥交换算法,被称为“前向保密”,洋⽂叫“forward secrecy”,缩写为 FS。它还有另⼀个称呼 — — “完美正向加密”(洋⽂是“perfect forward secrecy”,缩写为 PFS)。关于这⽅⾯的更多介绍,可以参见(链接在“”)。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论