共计 6431 个字符,预计需要花费 17 分钟才能阅读完成。
互联网通信技术的倒退利用,让信息无远弗届,连贯随时产生。关注【融云寰球互联网通信云】理解更多
但与此同时,互联网通信也暴露出了一系列平安问题。咱们须要有针对性地利用相干平安技术,加强通信零碎的安全性和可靠性,为爱护用户集体信息安全筑起防护墙。
在融云互联网通信安全系列文章首篇“链路平安”中,咱们介绍了对于链路加密的相干技术和实际。在传输即时通信音讯时启用 TLS 链路加密,保障音讯在达到服务器前无奈被窃听和篡改;应用 CA 认证机制,杜绝中间人攻打。
这些都是晋升客户端到服务器之间数据传输安全性的无效方法,然而未能解决用户间通信隐衷性和安全性面临的危险问题。因为在将数据传输到服务器之后,所有有权拜访此服务器的人,包含员工、相干供应商及其他无关人员甚至黑客,都有可能读取到用户的数据。
因而,端到端加密技术被鼎力推动,其呈现后很快被公众所认知并承受。在 WhatsApp、Signal、Telegram 等即时通信软件中都有所利用。
明天,咱们分享互联网通信安全系列文章的第三篇,率领大家一文读懂端到端音讯加密。
端到端加密方案设计思路
说到端到端加密,咱们首先想到的解决方案是,在发送端发送音讯前对整个音讯进行加密,接收端接管到音讯后进行解密。这样,音讯直达服务器就无奈获取咱们的音讯内容了。
事实上,这的确是端到端加密中音讯收发的简化版解决方案,只是咱们在理论利用中要更加简单,成果也更加平安。
咱们须要先解决的前置问题是,如何平安地传递用于音讯加解密的密钥。
答案是用非对称加密的形式传输密钥,与 SSL / TLS 中平安替换密钥的形式相似。
非对称加密传输对称加密密钥的算法,个别归纳两种形式:一种是以 RSA、ECC 等为主的,公钥加密私钥解密的形式,实质是加解密的算法;另一种是以 DH、ECDH 为主的生成共享密钥的形式,实质是通过计算协商一个独特的密钥而不是加解密算法。
大部分即时通信软件中的端到端加密都采纳生成共享密钥的形式来传输会话密钥。这是为什么呢?
此处为了不便了解,附上 DH 算法介绍:
基于原根的定义及性质,能够定义 Diffie-Hellman 密钥替换算法。该算法形容如下:
- 有两个全局公开的参数,一个素数 q 和一个整数 a, a 是 q 的一个原根。
- 假如用户 A 和 B 心愿替换一个密钥,用户 A 抉择一个作为公有密钥的随机数 XA(XA<q)< span=””>,并计算公开密钥 YA=a^XA mod q。A 对 XA 的值窃密寄存而使 YA 能被 B 公开取得。相似地,用户 B 抉择一个公有的随机数 XB<q< span=””>,并计算公开密钥 YB=a^XB mod q。B 对 XB 的值窃密寄存而使 YB 能被 A 公开取得。
- 用户 A 产生共享机密密钥的计算形式是 K = (YB)^XA mod q。同样,用户 B 产生共享机密密钥的计算是 K = (YA)^XB mod q。这两个计算产生雷同的后果。
推导过程如下:
K = (YB)^XA mod q
= (a^XB mod q)^XA mod q
= (a^XB)^XA mod q(依据取模运算规定失去)
= a^(XBXA) mod q
= (a^XA)^XB mod q
= (a^XA mod q)^XB mod q
= (YA)^XB mod q
因而相当于单方曾经替换了一个雷同的机密密钥。
4. 因为 XA 和 XB 是窃密的,一个敌对方能够利用的参数只有 q,a,YA 和 YB。因此敌对方被迫取离散对数来确定密钥。例如,要获取用户 B 的机密密钥,敌对方必须先计算 XB,而后再应用用户 B 采纳的同样办法计算其机密密钥 K。
Diffie-Hellman 密钥替换算法的安全性依赖于这样一个事实:尽管计算以一个素数为模的指数绝对容易,但计算离散对数却很艰难。对于大的素数,计算出离散对数简直是不可能的。
简要形容一下 DH 共享密钥的过程如下:
其中“密钥 S”即为最终的共享密钥。
总结而言,端到端加密采纳生成共享密钥的形式来传输会话密钥有如下几个起因:
- 如果采纳 RSA、ECC 等公钥加密私钥解密的形式传输密钥,须要在创立会话时生成长期密钥,并通过对方公钥加密后传输到接收端。这就须要齐全保障音讯的可靠性,如果该音讯在任何一个环节中失落或损坏,则后续通信都无奈进行。或者,须要采纳更为牢靠的传输计划,通常做法为须要接收端在线,通过各种确认来保障这个可靠性。而采纳共享密钥的形式则只须要晓得对方的公钥,就能够实现生成共享密钥,并不一定须要对方在线。
- 如果曾经生成的长期对称密钥失落,则须要从新协商密钥。而采纳共享密钥的形式则只须要晓得对方的公钥,就能够实现生成共享密钥,不须要从新协商。
- 采纳公钥加密私钥解密的形式至多会比生成共享密钥形式多一次替换对称密钥的通信过程。
- 密钥协商形式,不仅仅能够实现两个点之间的密钥协商,还能够延展到多人之间的独特协商出雷同的密钥,这样能满足多人群体沟通的需要。
端到端加密初步计划
咱们联合对于 DH 算法这种共享密钥形式的认知(公钥可随便公开),先设计一个简略的端到端音讯加密的过程。
- 在客户端 APP 首次装置时,基于服务器公开的两个全局的参数,生成本人的 DH 公钥和私钥。
- 将本人的公钥上传证书服务器,证书服务器上保留用户标识与其公钥的关系。私钥则保留在客户端上。
- 首次给对方发送音讯或首次接管到对方音讯时,便到证书服务器查问对方的公钥。
- 依据对方公钥和本人的私钥计算出共享密钥。
- 后续与对方所有的音讯都基于这个密钥和雷同的对称加解密算法进行加密解密操作。
(端到端音讯加密过程)
至此咱们实现了一个简略的端到端音讯加密计划,在这个计划中咱们引入了一个第三方的用于存储用户公钥的角色,这个角色的存在能够让任何一方都不必关怀对方的在线状态,随时给对方发送加密过音讯,而音讯转发服务器无奈解密音讯。
接下来,咱们针对这个简略计划存在的各种问题,进行剖析和优化。
端到端加密计划优化
HMAC
在音讯传输过程中,单方须要确认彼此音讯的完整性,简略的做法就是将音讯进行 Hash,失去的 Hash 值附加到音讯后,随音讯一起发送;对端接管后,同样进行 Hash,来验证音讯是否被篡改。
关键点在于不同数据失去的 Hash 值肯定不同,其中带密钥的 Hash 值就是 MAC。
另外,为了防止应用同样的 Hash 函数对雷同数据进行操作总是得出同样的值,额定退出一个密钥,这样应用不同密钥就能够得出不同的 MAC。当然,这个密钥是两个对端都晓得的。
这样,咱们就失去了基于加密 Hash 的音讯完整性认证的算法——Hash-based MAC。
ECDH
DH 算法是以离散对数的数学难题为根底的,随着计算机计算能力逐渐加强,咱们要不停地应用更大的数以减少破解难度,目前业界普遍认为至多须要应用 2048 位 DH 算法才具备更好的安全性。
在此咱们引入 ECDH 算法替换 DH 算法。ECDH 密钥协商算法是 ECC 算法和 DH 密钥替换原理联合应用。ECC 是建设在基于椭圆曲线的离散对数问题上的明码体制。在雷同破解难度下,ECC 具备更小长度的密钥和更快的正向计算速度劣势。
咱们零碎上的 ECDH 能够间接采纳目前公开的 sepc256kl 和 Curve25519 曲线,而无需服务再提供公开大数参数。
前向平安
在音讯传输过程中,如果协商好的密钥泄露了,就意味着所有信息都将裸露于危险之下。为了避免这种状况产生,咱们须要每次加密应用的密钥都与上一次不同,且不能够反向推导得出之前的密钥。
此处引入一个 Hash 算法,这个 Hash 算法能够通过输出一个密钥导出另外一个离散性更大的密钥,每次发送音讯时都是用上次的音讯密钥进行 Hash 运算得出本次密钥,因为 Hash 算法具备单向不可逆的个性,因而就无奈通过本次的密钥推导之前的密钥。从感观上,这就像一个棘轮,棘轮就是一种非凡的齿轮,他只能往一个方向转下去,而不能往回转。
双棘轮
出于极致的安全性要求,咱们会思考前向平安和后向平安。如何保障在某次通信中,被破解进去的密钥,不能破解出之前的音讯,而且在肯定周期内,这个破解进去的密钥将不会再起作用。
介于此咱们再引入另外一个棘轮来保障其向后的安全性。这就是赫赫有名的 Signal protocol 中的双棘轮算法。
双棘轮算法蕴含一个 KDF 棘轮和一个 DH 棘轮。
KDF 全称(Key derivation function)密钥导出函数,用于从一个原始的密钥导出一个或多个密钥。实质上就是 Hash 函数,通常用来将短明码变成长明码。另外 KDF 须要加“盐”(salt),用于防彩虹表,出于 Hash 的个性,这个“盐”的长度至多要大于 Hash 后果长度。
KDF (原密钥,盐) = 导出密钥
KDF 棘轮就是使用 KDF 算法,设计出一种密钥一直变动的成果,流程如下:
(KDF 棘轮流程)
第一步,将初始密钥应用 KDF 算法导出新的密钥,新密钥被切成两局部,前半部分作为下一次 KDF 计算的输出,后半局部作为音讯密钥。
每迭代一次(也能够说棘轮步进一次),就会生成新的音讯密钥。
因为 KDF 算法的单向性,通过这条音讯的密钥无奈倒推出上一条音讯密钥。这就保障了密钥的前向平安。然而如果 KDF 中的盐被把握,那么它就能够依照这种算法计算出当前所有的音讯密钥。
为了保障后向平安,就要设计一种办法,使每次迭代时引入的盐是随机的,从而保障每次的音讯密钥是不能够向后推算的。
由后面介绍的 DH 算法得悉,两对密钥对能够通过 DH 协定生成一个平安的协商密钥,如果更换其中一个密钥对,新的协商密钥也会变动。
依据这个办法,咱们能够设计出一个安全更新盐的办法。咱们在证书服务器减少一个长期公钥证书,这个长期证书是依照接管单方标识构建的长期公钥对,即每个人的每个单人会话都具备一个长期公钥。每进行一个音讯轮回,就更新一次己方的长期公钥,同时依据另外一方的长期公钥和己方的私钥进行协商,并将协商出的密钥作为盐,使得 KDF 棘轮算法生成的音讯密钥具备后向安全性。
在初始时咱们无奈预测出每个人所有的新二人会话,那么咱们就能够规定创立新的二人会话时,发起方首先生成一个新的长期 DH 公私钥对,并向服务器上传本人的长期 DH 公钥;其次发送方用接管方颁布的长期公钥与本人的长期私钥协商出密钥作为音讯加密的密钥,对音讯进行加密;最初接管方首次接管到音讯后用本人的长期公钥和发送方的长期私钥计算得出音讯密钥,并在首次回复音讯时生成长期公私钥,同时上传长期公钥。
问题是,如果接收端不在线,而发送端每条音讯都去更新己方的长期公钥证书,就会导致收回去的这些音讯,在接收端上线并收取后无奈被失常解密。
为了解决这个问题,咱们须要规定:只有在收回音讯并失去对方回复后才更新长期证书,若对方不回复音讯则不去更新长期证书。接收端能回复音讯就示意其曾经上线并接管完音讯,这样就能够保障离线音讯或者音讯乱序也能够被对方失常解析。这种办法就是双棘轮算法中的另外一个 DH 棘轮。
X3DH
比照最后的计划,为了满足音讯的前向平安和后向平安,咱们减少了双棘轮算法,在原根底计划上为每个人减少了一组会话级别长期 DH 密钥,每个人都领有一个长期密钥和一组长期密钥。
然而,因为长期密钥无奈被更换,所以计划仍然存在着安全隐患。因而,Signal protocol 设计了一种更为简单和平安的 DH 密钥替换过程,称之为 X3DH,即 DH 协定的 3 倍扩大版。
在 X3DH 协定里,每个人都要创立 3 种密钥对,别离如下:
- 身份密钥对(Identity Key Pair)—— 一个长期的合乎 DH 协定的密钥对,用户注册时创立,与用户身份绑定;
- 已签名的预共享密钥(Signed Pre Key)——一个中期的合乎 DH 协定的密钥对,用户注册时创立,由身份密钥签名,并定期进行轮换,此密钥可能是为了爱护身份密钥不被泄露;
- 一次性预共享密钥(One-Time Pre Keys)—— 一次性应用的 Curve25519 密钥对队列,装置时生成,有余时补充。
所有人都要将这 3 种密钥对的公钥上传到服务器上,以便其他人发动会话时应用。
如果 Alice 要给 Bob 发送音讯,首先要和 Bob 确定音讯密钥,流程大抵如下:
- Alice 要创立一个长期密钥对(ephemeral key),咱们设成 EPK-A,此密钥对是为了前面棘轮算法筹备,在此处作用不大;
- Alice 从服务器获取 Bob 的三种密钥对的公钥:身份密钥对 IPK-B;已签名的预共享密钥 SPK-B;一次性预共享密钥 OPK-B;
- Alice 开始应用 DH 协定计算协商密钥,要引入参数包含:本人创立的两个密钥对的私钥,以及 Bob 的三个公钥。而后用相似排列组合的形式,将本人的私钥与对方的公钥别离带入 DH 算法计算。
DH1 = DH(IPK-A, SPK-B)
DH2 = DH(EPK-A, IPK-B)
DH3 = DH(EPK-A, SPK-B)
DH4 = DH(IPK-A, OPK-B)
如图所示:
而后将计算失去的四个值,前后连接起来,就失去了初始密钥,如下:
DH = DH1 || DH2 || DH3 || DH4
注:“||”代表连接符,比方 456 || 123 = 456123
然而 DH 这个密钥太长,不适宜作为音讯密钥,所以对这个初始密钥进行一次 KDF 计算,以衍生出固定长度的音讯密钥 S
S = KDF(DH1 || DH2 || DH3 || DH4)
这一步,Alice 终于计算出了音讯密钥 S。
- Alice 应用音讯密钥 S 对音讯进行加密,连同本人的身份公钥 IPK-A 和长期公钥 EPK-A 一起发给 Bob。
- Bob 收到 Alice 的信息后,取出 Alice 的 2 个公钥,连同本人的密钥,应用与 Alice 雷同的算法计算音讯密钥 S。
- Bob 和 Alice 应用音讯密钥进行加密通信。
由上可知,X3DH 理论是简单版的 DH 协定。
至此,咱们简略介绍了 Signal Protocol 中最为外围的 X3DH 协定与双棘轮算法,基本上能够满足前向平安和后向平安。当然,实在的处理过程会更为简单和平安。
群聊的端到端加密计划
在即时通讯场景中,除了二人之间的聊天以外,还有一个重要的场景就是群聊,那么群体之间的音讯如何做端到端加密呢?
咱们再次回到 DH 密钥协商算法上的推导过程。显然,多方状况下仍然能够持续应用 DH 密钥协商算法,这就是群聊中端到端加密的根底。
而在 Signal Protocol 在群组聊天中的设计与二人聊天又有所不同,因为群聊的保密性要求绝对低一些,只采纳了 KDF 链棘轮 + 公钥签名来进行加密通信以保障加密的前向平安。
通信流程如下:
- 每个群组成员都要首先生成随机 32 字节的 KDF 链密钥(Chain Key),用于生成音讯密钥,以保障音讯密钥的前向安全性,同时还要生成一个随机 Curve25519 签名密钥对,用于音讯签名。
- 每个群组成员用向其它成员独自加密发送链密钥 (Chain Key) 和签名公钥。此时每一个成员都领有群内所有成员的链密钥和签名公钥。
- 当一名成员发送音讯时,首先用 KDF 链棘轮算法生成的音讯密钥加密音讯,而后应用私钥签名,再将音讯发给服务器,由服务器发送给其它成员。
- 其它成员收到加密音讯后,首先应用发送人的签名公钥验证,验证胜利后,应用相应的链密钥生成音讯密钥,并用音讯密钥解密。
- 当群组成员来到时,所有的群组成员都革除本人链密钥和签名公钥并从新生成,再次独自发给每一位成员。这样操作,来到的成员就无奈查看群组内的音讯了。
由上可知,一个人在不同的群组里,会生成不同的链密钥和签名密钥对,以保障群组之间的隔离。在每个群组中,每个成员还要存储其它成员的 KDF 链和签名公钥,如果群组成员过多,加解密运算量十分大,会影响发送和接管速度,同时密钥治理数据库也会十分大,读取效率也会升高。
所以,群组聊天应用 Signal Protocol 协定,群人数不宜太多。
端到端加密计划补充阐明
下面咱们介绍了即时通信中二人聊天和群组聊天的端到端加密全副过程。然而失常状况下端到端音讯加密只是加密音讯的理论负载局部,而音讯的管制层则不会被加密,因为音讯转发服务器须要依据管制信息进行音讯转发或路由。
为了避免音讯被定向剖析(剖析用户什么工夫向谁发送了音讯,或接管了谁的音讯),咱们仍然须要对整体即时通信的长连贯链路进行加密爱护,避免信息被两头网络设备截获并剖析;为了避免密钥服务器被中间人攻打,也须要开启链路加密爱护。