说起网络通信协议,相信大家对 TCP 和 HTTP 都很熟悉,它们可以说是当今互联网通信的基石。但是,在网络安全方面,它们却是有着很大安全风险:
为此,SSL/TLS 协议应运而生。SSL/TLS 是建立在传输层之上、应用层之下的安全通信协议,它主要的设计意图就是消除上述几种安全风险,保证网络通信安全。我们熟知的 HTTPS 就是 HTTP + SSL/TLS 构建的,可以说 SSL/TLS 是当今互联网安全通信的基石。
那么,现在假如让你来设计 SSL/TLS 协议,你会怎么设计呢?
本文将从设计者的视角介绍如何一步步设计出一个简易版的 SSL/TLS 的过程,在文章的最后,再简单介绍 TLS 1.2 版本的工作机制,以此帮助大家对 SSL/TLS 协议的基本原理有一个更深入的理解。
窃听风险主要是因为通信双方在网络上明文传输数据,导致攻击者可以通过简单网络抓包就能获取到通信的内容。
要解决窃听风险,就最好的方法就是对数据进行加密。也即客户端在把数据发送出去之前,先对数据进行加密;服务端收到密文之后,再进行解密还原数据。这样就能避免在网络上传播明文,从而可以防止第三方攻击者的窃听。
提到加密算法,很多人首先会想到对称加密算法,它以简单和高效著称。对称加密指的是加密和解密都使用同一份密钥,常见的算法有 DES、AES 等。
现在,我们试着使用对称加密算法来实现安全通信:
使用对称密钥加密的前提是,通信双方都必须用同一份密钥来对数据进行加密。主要有线下和线上密钥交换两种方案可以达到该目的:
因此,单纯的对称加密并不能满足通信安全的要求,我们还要继续优化......
非对称加密算法指的是加密和解密使用不同的密钥,这两个不同的密钥组成一个密钥对,也即公钥和私钥。公钥是公开的密钥,所有人都能获取到;私钥则是保密的。当我们使用公钥对数据进行加密后,只有对应的私钥才能完成解密。常见的非对称加密算法有 RSA、ECC 等。
现在,我们试着使用非对称加密算法来实现安全通信:
通过非对称加密算法,我们既能实现对数据的加密,又能解决密钥交换的问题,从而消除了窃听风险。但是,非对称加密算法最大的缺点,就是加解密速度很慢,相比于对称加密算法要慢1000多倍。因此,非对称加密算法通常只适用于对少量数据的加密。
到目前为止,单纯地使用对称加密算法或非对称加密算法都无法满足要求,还需要继续优化......
既然对称加密算法加解密速度快,但存在密钥交换的问题;而非对称加密算法可以解决密钥交换问题,但加解密速度慢。那么我们可以把两种算法结合起来,也即通过对称加密算法进行数据加密,在交换对称密钥时,使用非对称加密算法来加密对称密钥,确保密钥在网络传输过程中不会被攻击者窃听。
现在,我们试着使用对称加密+非对称加密算法来实现安全通信:
使用对称加密+非对称加密算法的方案,我们消除了窃听风险,也不会存在加解密性能问题,但是还是无法消除冒充风险。
考虑如下场景:
这番操作后,攻击者就能在客户端和服务端都不知情的情况下,得到了对称密钥。在这种场景下,攻击者从被动攻击的窃听,转为主动攻击的冒充,让客户端和服务端都误以为一直在跟对方通信。
因此,我们需要找到一种方法,让客户端能够确保自己收到的公钥,一定是真实的服务端发送过来的,也即能够认证“服务端”的真实身份......
引用百度百科的定义:
数字证书是指在互联网通讯中标志通讯各方身份信息的一个数字认证,人们可以在网上用它来识别对方的身份。
数字证书(Digital Certificate)就好比现实世界中的身份证,用于标识一个网络用户(人、公司、服务器等)的合法身份。就像身份证必须由公安局来颁发,可信的数字证书也必须由一个权威机构来颁发,该机构就是证书授权中心(Certificate Authority,CA),CA 颁发的数字证书我们通常称作 CA 证书。
一个 CA 证书主要包含申请者的公钥、申请者的信息、签发机构 CA 的信息、有效时间、证书序列号等明文信息,同时也包含一个 CA 的数字签名,正是该签名的存在才证明了该证书的有效性。
数字签名建立在非对称加密算法的基础上,CA 在颁发证书时,会先将证书的明文信息用指定的算法(比如 SHA256 算法)计算出一个数字摘要,再使用 CA 的私钥对摘要进行加密,形成签名。
而证书的验证主要包含如下两部分:
数字摘要1
。再使用同样的算法对证书明文信息计算得出数字摘要2
。对比数字摘要1
和数字摘要2
是否相等。颁发证书的机构并非只有一个,比如机构 A 可以用 CA 颁发的根证书去给机构 B 颁发二级证书;机构 B 又可以用二级证书去给机构 C 颁发三级证书,以此类推,也即所谓的证书链。
现在,我们加入 CA 证书来认证通信双方的身份:
引入 CA 证书之后,服务端的公钥就放在它提供的证书之中,当客户端验证服务端证书通过后,也就说明其中的公钥确实是来自服务端的合法公钥。这样,后续的通信流程就可以正常地进行了。
然而,如果对称密钥一直不变的话,攻击者还是很有可能暴力破解出对称密钥。因此,我们还需要最好能够实现每次连接的对称密钥都是不同的......
为了使每次连接的对称密钥都不同,我们可以引入随机数来生成对称密钥,保证它的随机性。但是,考虑到当前计算机生成的随机数都是伪随机数,为了进一步提升随机性,我们可以通过生成多个随机数来达到此目的。
我们可以这么设计:
随机数1
和随机数2
),在 ClientHello
和 ServerHello
报文中完成交换。随机数3
,通过服务端的公钥加密发给服务端。(此时,通信双方都拥有了 3 个一样随机数)这样通过 3 个随机数来生成的密钥,就能较好地保证了密钥的随机性,降低被攻击者破解的可能。
虽然
随机数1
和随机数2
是明文传输,但随机数3
是密传输,也就能够保证攻击者很难破解到密钥。
到目前为止,我们已经通过多种手段成功阻止了攻击者窃听客户端和服务端之间的通信内容。但是,如果攻击者并不以窃听通信内容为目的,而是单纯地想搞破坏。比如,攻击者拦截了 ClientHello
报文,把其中的随机数1
改成了随机数4
,这样就会导致客户端和服务端生成的密钥不一致。在此场景下,虽然连接已经建立起来了,但是客户端和服务端还是无法正常地通信:
为此,我们需要一种机制,校验连接建立阶段(握手阶段)所有消息的正确性,防止建立错误的连接......
我们可以利用数字摘要来校验所有握手消息的正确性,也即,在握手阶段的最后,通信双方都通过 Hash 算法(比如 SHA256)对自己收到的和发送的所有消息计算出数字摘要
,然后使用前面协商好的对称密钥对该数字摘要
进行加密,发送给对方。
当收到对方发过来的数字摘要
密文后,先用对称密钥对其进行解密,如果解密成功,说明密钥生成没问题;接着对比双方的数字摘要
是否一致,如果一致,说明握手阶段的消息没有被篡改过,也即可以建立起正确的连接了。
到现在,我们基本上已经消除了窃听风险(通过数据加密)、冒充风险(通过证书认证)和篡改风险(通过数字摘要)。但是,为了建立起安全通信通道,我们需要经历多次消息交互、加解密、身份认证等步骤,对性能有一定的损耗。
因为经历过一次握手之后,密钥已经协商好,并且双方都保存了下来。下次连接建立时,完全可以沿用上次握手协商好的密钥,从而避免了重新协商密钥,提升了性能。我们需要一种重用会话的机制来提升协议的性能......
为了达到沿用上次协商好的密钥的目的,我们为每次连接都分配一个会话 ID。
ServerHello
返回给客户端。ClientHello
把该会话 ID 发给服务端,表示希望重用该会话。Finished
消息,表示同意了会话重用,也即可以沿用上次会话协商好的密钥进行安全通信了。到这里,我们已经完成了一个简易版的 SSL/TLS 协议的设计,真实的 SSL/TLS 协议当然没这么简单,但是里面的核心思想和基本原理都是类似的。只是 SSL/TLS 为了更好的安全性、扩展性和易用性等增加了一些机制,比如支持多种加密算法、使用 MAC 替代普通的数字摘要完成完整性校验。
下面,我们将简单介绍真实的 SSL/TLS 协议的工作机制。
SSL 协议(Secure Sockets Layer)是 TLS(Transport Layer Security)协议的前身,它们的版本演进如下,当前最新的版本为 TLS 1.3 版本。本节,我们将以当前使用最广泛的 TLS 1.2 版本作为分析对象,介绍 SSL/TLS 的基本工作机制。
SSL 1.0版本 -> SSL 2.0版本 -> SSL 3.0版本 -> TLS 1.0版本 -> TLS 1.1版本 -> TLS 1.2版本 -> TLS 1.3版本
SSL/TLS 协议位于网络协议栈中传输层和应用层之间,它内部又可以分为 2 层,总共 5 种子协议:
最底层的 Record 协议负责对上层子协议的封装,提供安全通信的能力:
上层的 Handshake 协议用在握手阶段,为通信双方提供身份认证、加密算法和密钥协商的能力:
Handshake 协议包含了如下几种报文类型:ClientHello
、SeverHello
、Certificate
、ServerKeyExchange
、CertificateRequest
、ServerHelloDone
、ClientKeyExchange
、CertificateVerify
、ChangeCipherSpec
、Finished
。
Change Cipher Spec 协议也用在握手阶段,当通信的一方发出Change Cipher Spec 报文时,就表示密钥已经协商好,从下一条消息开始,使用该密钥来进行加密传输。
Alert 协议只有在连接异常时才会用上,当前协议定义的 Alert 消息类型如下:
1close_notify: 表示发送方不会再发送任何消息,用于正常关闭连接,类似于TCP中的FIN报文2unexpected_message: 收到不在预期之内的消息3bad_record_mac: 收到的消息中MAC不正确,表示消息已经被篡改过4decryption_failed_RESERVED: 解密失败,用于TLS的早期版本5record_overflow: 消息长度溢出,密文长度不超过2^14+2048字节;压缩后的明文不超过2^14+1024字节6decompression_failure: 使用压缩功能时,解压失败7handshake_failure: 握手阶段无法协商出正确的安全参数8no_certificate_RESERVED: 为了兼容SSL 3.0版本,TLS不再使用9bad_certificate: 证书签名认证失败10unsupported_certificate: 收到不支持的证书类型11certificate_revoked: 收到被废弃的证书12certificate_expired: 收到过期的证书13certificate_unknown: 除上述4种情况外,其他证书异常场景14illegal_parameter: 握手阶段报文的参数非法,比如范围溢出等15unknown_ca: 不可信任的CA颁发的证书16access_denied: 证书校验通过,但发送方却拒绝继续握手17decode_error: 消息解码失败18decrypt_error: 握手阶段安全相关的步骤失败,比如签名校验失败、Finished消息校验失败等19export_restriction_RESERVED: 早期的TLS版本使用20protocol_version: 协议版本不支持21insufficient_security: 服务端要求的安全算法,客户端无法满足22internal_error: 协议内部错误23user_canceled: 用户非正常主动关闭连接24no_renegotiation: 拒绝重新握手25unsupported_extension: 不支持的扩展
Application Data 协议用在通信阶段,封装了应用层的数据,经由 Record 协议封装之后,通过 TCP 协议转发出去。
ClientHello
报文发起连接建立,其中携带了如下内容:
ServerHello
报文,其中携带了如下内容:
Certificate
报文,其中携带了服务端的证书,证书必须是 x.509 标准格式,包含服务端公钥、服务端域名、签发方信息、有效期等信息。
可选,客户端需要通过证书来认证服务端身份时发送Server Key Exchange
报文,其中携带了客户端用于生成 premaster secret 的安全参数。
可选,当 Certificate
报文中携带的信息无法支撑客户端生成 premaster secret 时发送CertificateRequest
报文,索求客户端证书,其中包含了期望的证书类型、签名算法和CA列表。
可选,开启双向认证时发送ServerHelloDone
报文,表示当前服务端已经把所有与密钥交换相关的内容都发送完毕。Certificate
报文,其中携带了客户端证书。
可选,收到服务端的 CertificateRequest
报文时发送ClientKeyExchange
报文,其中包含了使用服务端公钥加密后的 premaster secret (随机数),随后用于生成master secret。CertificateVerify
报文,其中包含了对通信双方到目前为止所有握手报文的数字签名,用于证明自己拥有的私钥与之前发送的证书中的公钥相对应。
可选,给服务端发送 Certificate
报文时发送ChangeCipherSpec
报文,表示从下条消息开始进行加密传输。Finished
报文,加密传输,其中包含了所有握手消息的数字摘要,用于防篡改。ChangeCipherSpec
报文,表示从下条消息开始进行加密传输。Finished
报文,加密传输,其中包含了所有握手消息的数字摘要,用于防篡改。SSL/TLS 协议也并非绝对安全,它也有许多漏洞被黑客们不断地挖掘出来,当然,SSL/TLS 协议也在不断地完善。2018 年发布的 TLS 1.3 版本就在 TLS 1.2 版本的基础上做了许多增强。比如,在性能上,握手阶段从 2-RTT 缩减为 1-RTT,并支持 0-RTT 模式;在安全上,ServerHello
报文之后就开始加密传输、一些不安全的加密套件也不再支持(比如静态 RSA、Diffie-Hellman 等)。
虽然 TLS 1.3 版本机制上改变了很多,但是基本原理还是一样的。因此,把 SSL/TLS 协议原理理解透了,后续不管版本再怎么演进,我们都能快速完成协议机制的学习。
参考 The Transport Layer Security (TLS) Protocol Version 1.2,RFC 5246 The Transport Layer Security (TLS) Protocol Version 1.3,RFC 8446 SSL/TLS 协议运行机制的概述,阮一峰 Overview of SSL/TLS Encryption, MicroSoft Document The First Few Milliseconds of an HTTPS Connection,Jeff Moser 为什么 HTTPS 需要 7 次握手以及 9 倍时延,面向信仰编程 HTTPS权威指南,杨洋、李振宇等 数字证书, 百度百科 更多文章请关注微信公众号:元闰子的邀请
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。