网络安全篇,面对复杂多变的网络环境,我们需要掌握哪些关于网络安全的相关知识,聊一聊与网络安全相关的:HTTPS、SSL、TLS 等。
《 网络安全 — HTTPS 》
《 网络安全的基石(上)— 加密 》
《 网络安全的基石(下)— 完整性与身份认证 》
《 公钥信任问题 — 数字证书与 CA 》
《 信任始于握手 — TLS 连接过程详解 》
《TLS 1.3 特性解析》
《 如何优化 HTTPS 连接 》- 待完善
早在 2013 年,IETF(互联网工程小组) 就对 TLS 1.2 的过时设计和两次往返开销心生不满,因此开始着手准备新版本的 TLS。同年 8 月由 Eirc Rescorla 提议出新版本 TLS 的 功能愿望清单 。在经过一番 辩论 后,最终该提议内容被定义为 TLS 1.3。推动 TLS 1.3 设计的主要问题大概有:
终于在 2018 年 8 月 10 日,历经 4 年时间,TLS 1.3 最终版本发布了 — RFC-8446 。新的协议使得互联网变得更快、更安全;随着 TLS 1.3 的采用率不断提高,它势必会长远影响互联网的发展;同时尽快将 TLS 1.3 平滑应用到线上环境无疑是势在必行。
不过在这之前, TLS 1.2 的应用也已经有 10 年(2008 年)的时间了,毕竟历经了种种考验,新的协议在推广和部署上必定会带来新的挑战。接下来我们就来看看新版本的 TLS 是如何做的?
由于 TLS 1.1/1.2 等协议已经出现了很多年,很多应用软件、中间代理(Middlebox)只认老的记录协议格式,更新改造很困难,甚至僵化。
可部署性
正式由于这些中间代理/软件(Middlebox)在新的更改中表现不佳,即使是对 TLS 1.3 协议的细微更改(例如消除冗余的 ChangeCipherSpec 消息,版本号从 0x03 升级为 0x04),也最终导致了某些设备的连接失败问题。这也是 TLS 1.3 从草稿到最终发布花费了这么长时间的重要原因之一。
为了保证这些被广泛部署的“旧设备”能够继续使用,TLS 1.3 不得不做出妥协,通过“伪装”来实现兼容:保持现有的记录格式不变,使得 TLS 1.3 看上去“像是” TLS 1.2。
扩展协议
那么,如何区分是 1.2 还是 1.3 呢?
这里用到一个新的 扩展协议 (Extension Protocol),它有点“补充条款”的意思,通过在记录末尾添加一系列的“扩展字段”来增加新的功能,旧版本的 TLS 不认识它可以直接忽略,这就实现了“向后兼容”。
TLS 1.3 正是利用扩展实现了许多重要的功能,比如 “supported_groups” “key_share” “signature_algorithms” “server_name” 等。
在经历十余年的实践中获得许多宝贵经验的 TLS 1.2 陆续发现了很多的漏洞和加密算法的弱点。因此消除潜在的危险设计来纠正以前的错误成为 TLS 1.3 的设计目标之一。所以新版本的 TLS 协议里要修补这些不安全的因素。
例如:
固定密钥交换
经过这样一番“减肥瘦身”之后,TLS 1.3 的密钥交换算法只有 ECDHE 和 DHE 了,关于椭圆曲线(ECC)也被“砍”到只剩 P-256 和 x25519 等 5 种。
首先来说下废除 RSA 和 DH 密钥交换算法的原因:
由于客户端默认会选择 ECDHE 而非 RSA 做密钥交换,这是因为它不具有“ 前向安全 ”(Forward Secrecy):“假设有人长期记录了加密的数据,然后在后续的某个时间段获得了服务器的 RSA 私钥,那么黑客就能够使用该私钥解密出之前所有报文的 “Pre-Master”,再计算出会话密钥,破解所有密文。这便是 今日截获,明日破解 ”
而 ECDHE 算法在每次握手时都会生成一对临时公钥和私钥,每次通信的秘钥对都是不同的,也就是“一次一密”,即使黑客花大力气破解了这一次的会话密钥,也只是这次通信被攻击,之前的历史消息不会受到影响,仍然是安全的。
所以现在主流的服务器和客户端在握手阶段都已经不再使用 RSA,改用 ECDHE,而 TLS 1.3 在协议里明确废除了 RSA 和 DH 则在标准层面保证了“前向安全”。
固定密码
多年以来,密钥交换机制不是唯一引起安全漏洞的部分,对称密钥部分也有相当一部分问题。
同样,用于对称加密的算法在经过“减肥瘦身”之后也只保留了 AES、ChaCha20 ,分组模式只能用 AEAD 的 GCM、CCM 和 Poly1305,摘要算法也只能用 SHA 256、SHA 384。
这样原来众多的加密算法、参数组合导致密码套件非常复杂,难以选择。而经过瘦身之后的 TLS 1.3 只剩下 5 个套件,使得客户端或服务端在选择密码套件时变得“更加容易”。然而更重要的是,这些算法在 TLS 长期的实践过程中先后已经被证实是构成不安全的因素,从而导致安全漏洞。
修复数字签名
经过前面的学习,相信你也知道 TLS 另一个重要部分是身份验证。在每个连接中服务都是用具有公钥的数字证书向客户端提供身份认证。在 RSA 加密模式下,服务器通过解密预主密钥并通过对话记录计算 MAC 来证明其对私钥的所有权。在 Diffie-Hellman 模式下,服务器使用数字签名来证明私钥的所有权。
在 TLS 1.2 和更早的版本中,服务器的签名仅涵盖部分握手。用于协商使用哪种对称密码的部分没有由私钥签名。这也导致许多引人注目的漏洞 FREAK , LogJam 等。而在 TLS 1.3 由于服务器对整个握手记录进行签名,因此可以避免这些情况。
HTTPS 建立连接时除了要做 TCP 握手,还要做 TLS 握手,在 TLS 1.2 中会多花两个消息往返(2 - RTT),这可能导致几十毫秒甚至上百毫秒的延迟,在移动网络中延迟还会更严重。
1-RTT 模式
密码套件的大幅度简化,也就没有必要再像以前那样走复杂的的协商流程了。TLS 1.3 压缩了以前的 “Hello” 协商过程,删除了 “Key Exchange” 消息,把握手时间减少到了 “1-RTT”,效率提高了一倍。
下面是 TLS 1.3 握手过程的简图,注意与前面介绍的 TLS 1.2 对比区别在哪里。
0-RTT 恢复
除了标准的 “1-RTT” 握手,受 QUIC 协议的启发,客户端可以在其第一条消息中将加密的数据发送到服务器,与未加密的 HTTP 相比,没有额外的延迟成本。
在 TLS 1.2 中,有两种恢复连接的方法:会话 ID 和会话 Ticket,而 1.3 则将他们组合在一起形成称为 PSK(pre-shared key,预共享密钥)恢复的新模式。
握手分析
目前 Nginx 等 Web 服务器都能够很好的支持 TLS 1.3,但是要求底层的 OpenSSL 必须是 1.1.1。因此如果要部署需要先升级你的 OpenSSL 版本。
首先TCP 建立连接之后,浏览器首先还是发一个 “ Client Hello ”。
由于 1.3 的消息要兼容 1.2,所以开头的版本号、支持的密码套件和随机数(Client Random)结构都是一样的(这时的随机数是 32 个字节)。
注意 “Client Hello” 里的扩展,“ supported_versions ” 表示这是 TLS 1.3,“ supported_groups ” 是支持的曲线,“ key_share ”是曲线对应的参数。
这有点是像是“有话尽量一口气说完”,还是按照老规矩进行“打招呼”,我这边有这些信息,考虑到版本升级,所以附带了一些信息,可能后面会用到。
服务器收到 “Client Hello” 同样返回 “Server Hello” 消息,还是要给出一个 随机数 (Server Random)和选定密码套件。
表面上看 Version 和 TLS 1.2 是一样的,重点是后面的扩展。“ supported_versions ” 里确认使用的是 TLS 1.3,然后在 “ key_share ” 扩展带上曲线和对应的公钥参数。
服务器的回应还是老套路,服务端对客户端的提供的信息作出选择,另外服务端还要再附加上几个参数,这次加密就协商定了。
可以看到相比 TLS 1.2 的握手过程,TLS 1.3 仅用两条消息就共享了 4 个信息: Client Random 和 Server Random 、 Client Params 和 Server Params 。两边就可以各自用 DH 算出 “ Pre-Master ”,再用 HKDF 生成主密钥 “ Master Secret ”,效率比 TLS 1.2 提高了一大截。
在计算出主密钥后,服务器立刻发出 “ Change Cipher Spec ” 消息,比 TLS 1.2 提早进入加密通信,后面的证书等就都是加密的了,减少握手时明文信息泄露。
TLS 1.3 还多了一个 “ Change Cipher Spec ” 消息,服务器用私钥把前面的曲线、套件、参数等握手数据加了签名,作用和 “ Finished ” 消息差不多。但由于是私钥签名,所以强化了身份认证和防篡改。
两个“打招呼”消息之后,客户端验证服务器证书,再发 “Finished” 消息,就正式完成了握手,开始收发 HTTP 报文。
现在已经有很多网站都支持了 TLS 1.3,例如 GitHub :
今天我们主要介绍了 TLS 1.3 的一些新特性,简单总结下来主要包含下面几点:
TLS 1.3 涉及的内容很多,有关它的更详细信息请去参照 RFC-8446 ,关于这部分大家还有哪些要分享的呢?欢迎您的留言或指正。
网络安全系列专题
扩展阅读
SSL(Socket Layer Security)和 TLS(Transport Layer Security) 都是属于安全协议,主要作用是保证客户端和服务端之间能安全通讯。SSL是较早的协议,TLS 是 SSL的替代者。
SSL 版本 1.0、2.0 和 3.0,TLS 版本 1.0、1.2 和 1.3。SSL协议和TLS1.0 由于已过时被禁用,目前TLS 1.3 是互联网上部署最多的安全协议,它是TLS最新版本 ,它增强了过时的安全性,并增加了更多的触控性。通过下面几点可以有个简单认识:
现代浏览器支持 TLS 1.2 和 TLS 1.3 协议,但 1.3 版本要好得多。 TLS 1.3 对早期版本进行了多项改进,最明显的是简化了TLS握手操作,使得握手时间变短、网站性能得以提升、改善了用户体验,另外支持的密码套件更安全和简单。
密码套件
TLS/SSL 使用一种或多种密码套件。 密码套件是身份验证、加密和消息身份验证的算法组合。TLS 1.2 版使用的算法存在一些弱点和安全漏洞。在 TLS 1.3 中删除了这些算法:
另外一个很重要的更新是TLS1.3 支持 perfect-forward-secrecy (PFS)算法。
向前保密 (PFS)是特定密钥协商协议的一项功能,如果一个长周期的会话密钥被泄露,黑客就会截获大量数据,我们可以为每个会话生成唯一的会话密钥,单个会话密钥的泄露不会影响该会话之外的任何数据。
TLS在早期版本的握手期间可以使用两种机制之一交换密钥:静态 RSA密钥和 Diffie-Hellman 密钥。 在 TLS1.3 中,RSA 以及所有静态(非 PFS)密钥交换已被删除,只保留了DHE、ECDHE
可以查看网站的安全详情来确认它是否使用"ECDHE"或"DHE"。
AES (Advanced Encryption Standard) 对称加密,它是 高级加密 标准。早期的加密标准DES(Data Encryption Standard) 已被弃用。
AES选择合适的 加密模式 很重要,应用比较多的两种模式 CBC 和 GCM。
CBC 密码分组链接模式
明文分块,第一个块使用初始化向量,后面的每个明文块在加密前与前一个密文块进行异或运算。
这种模式存在的问题:
CTR 计数模式
明文分块按顺序编号,通过加密"计数器"的连续值来生成下一个密钥流块。CTR 模式非常适合在多核处理器上运行,明文块可以并行加密。
GCM 伽罗瓦/计数器模式
GCM = CTR + Authentication。其加密过程,明文块是按顺序编号的,然后这个块号与初始向量 组合并使用块密码E加密,然后将此加密的结果与明文进行异或以生成密文。
简单来说,GCM 是 CTR 身份验证的组合,它更快、更安全。它将接受流水线和并行化实现,并具有最小的计算延迟,所以它的应用更加广泛。
客户端最低版本
客户端最低版本
一般建议同时兼容1.2和1.3
测试是否支持 TLS 1.2
测试是否支持 TLS 1.3
上期我们说到对称加密算法
AES DES
目前使用的几乎都是AES-GCM(DES安全性太差基本处于废弃状态)
那除了这两种还有其他的吗?
答案是有的
ChaCha20
那这种算法与AES-GCM相比有什么特别之处呢?
上图展示的是CHACHA20-Poly1305 与 AES-GCM 两种对称加密算法的加密效率。
从这张图中我们可以看到 ChaCha20的加密速度比AES快了差不多3倍左右。那为什么现在的网站打开都基本上AES-GCM呢?
仔细看图我们可以看到,这是基于ARM架构的移动端CPU的加密速度。CHACHA20虽然在移动端CPU架构上加解密速度非常快,但是在传统>的x86架构上却比AES慢。再加上支持CHACHA20的证书比较难申请的到。所以导致了现在的网站打开都基本上AES-GCM。
不过如果业务主要针对是移动端并且服务端硬件配置比较好且申请到了支持CHACHA20的证书。由于该算法在移动端加解密速度非常快。
所以能够得到较好的用户体验。(虽然从运维的角度来说应该尽量降低服务器的负载,将负载转移到用户端比较好。主要还是看如何取
舍)
首先我们了解下正常的https请求的流程:
从图片中我们可以看到http的延迟时间大概在56ms
而https因为是在http协议上额外增加了tls协议所以延迟时间大概需要168ms(http+tls)
由此可以看出使用https确实会给网站的打开速度产生影响,最直接的就是用户打开网站速度变慢。而且当用户不小心断开之后又要重>新走完这整一套的步骤。那有什么办法可以规避这种办法呢?
session id是一种用户断线重连之后能快速建立连接的一种方法。原理非常简单,当用户与服务器第一次成功完成握手之后,服务器>端生成一个session id 自身保存一份,另外一份发送给客户端。当客户端断线重连之后客户端像服务端发送session id 如果服务端发
现这个id存在。则免去繁琐的tls握手步骤 直接连接。从图中我们也看到采用这样的方式延迟时间降低了50%左右
但是方法不适合分布式架构的业务,原因在于session id 是在每一台服务器中生成的。所以当客户端重连后连接到服务器的另外一台
后端业务服务器就会因为没有id 而重新进行一次完整握手。
session ticket的原理与session id 相同只不过session ticket 不是生成id 而是根据服务器上的ticket key 加密一个数据blob发>送给客户端,然后客户端重连时发送blob给服务器,服务器解密这个blob来判断是否是重连用户从而免去繁琐的tls握手步骤。采取这>样的方式的好处就是我们可以将session key 存储在所有的分布式后端业务服务器上。这样不管用户重连到哪一台服务器都可以通过session key来解密判断是否为重连用户。
那我们有更简单方便的方法吗?
有的,那就是tls1.3!
如上图:
tls1.3是最新的tls协议版本。
废弃了很多年老安全性差的算法并且采用了更优秀的握手机制。
tls1.3 移除了RSA握手机制,采用了(EC)HDE 握手机制(RSA与DH的优缺点在(对称加密模式在 关于TLS经验小结(上) 中有介绍)
移除CBC对称加密模式,采用AEAD模式(对称加密模式在 关于TLS经验小结(中) 中有介绍)
以及其他的特性。 具体详见
其中最瞩目的莫过于新的握手协商机制
TLS1.3
TLS1.2
如上图tls1.3协议将之前tls1.2需要的步骤整合在一起,然后集中传输。减少了握手次数,从而大幅减少了延迟时间。加快了网站访问
速度,使我们再也不用去纠结不上https不安全,上了https访问速度慢的历史性问题。
从之前讲的算法到握手机制。使大家对整个tls协议有了一个大概的认识。从生产环境角度来说,采用ECDH
+ECDSA+AES-GCM的 ECC证书是目前在安全性和性能上都相对平衡的一种证书种类。本站的证书就是采用了ECC证书。
关于ECC证书可以查看
在此感谢峰哥的一次知识分享让我了解到了相关的知识(文章中的一些示例图也源于峰哥的ppt)
想具体了解大佬可以访问以下博客更深入的了解
TLS 1.3 如何用性能为 HTTPS 正名
图解SSL/TLS协议
分组密码工作模式
完
欢迎分享,转载请注明来源:夏雨云
评论列表(0条)