【网络通信 -- 直播】IM 学习系列 -- 网络通信协议简介(HTTP 协议 六)

【网络通信 -- 直播】IM 学习系列 -- 网络通信协议简介(HTTP 协议 六)

【1】HTTPS 相关概念简介

【1.1】安全的通信过程需要具备四个特性,即机密性、完整性,身份认证和不可否认
机密性(Secrecy/Confidentiality)是指对数据的“保密”,只能由可信的人访问,对其他人是不可见的“秘密”,简单来说就是不能让不相关的人看到不该看的东西;
完整性(Integrity,也叫一致性)是指数据在传输过程中没有被篡改,不多也不少,“完完整整”地保持着原状;
身份认证(Authentication)是指确认对方的真实身份,保证消息只能发送给可信的人;
不可否认(Non-repudiation/Undeniable),也叫不可抵赖,意思是不能否认已经发生过的行为;

【1.2】HTTPS (默认端口号 443)

HTTPS 把 HTTP 下层的传输协议由 TCP/IP 换成了 SSL/TLS,由“HTTP over TCP/IP”变成了“HTTP over SSL/TLS”,让 HTTP 运行在了安全的 SSL/TLS 协议上,收发报文不再使用 Socket API,而是调用专门的安全接口

【1.3】SSL/TLS
SSL 即安全套接层(Secure Sockets Layer),在 OSI 模型中处于第 5 层(会话层),由网景公司于 1994 年发明,有 v2 和 v3 两个版本;SSL 发展到 v3 时已经证明了它自身是一个非常好的安全通信协议,于是互联网工程组 IETF 在 1999 年把它改名为 TLS(传输层安全,Transport Layer Security),正式标准化,版本号从 1.0 重新算起,所以 TLS1.0 实际上就是 SSLv3.1;
TLS 由记录协议、握手协议、警告协议、变更密码规范协议、扩展协议等几个子协议组成,综合使用了对称加密、非对称加密、身份认证等许多密码学前沿技术
浏览器和服务器在使用 TLS 建立连接时需要选择一组恰当的加密算法来实现安全通信,这些算法的组合被称为“密码套件”(cipher suite,也叫加密套件)
TLS 的密码套件命名格式很固定,基本的形式是“密钥交换算法 + 签名算法 + 对称加密算法 + 摘要算法”,如ECDHE-RSA-AES256-GCM-SHA384表示握手时使用 ECDHE 算法进行密钥交换,用 RSA 签名和身份认证,握手后的通信使用 AES 对称算法,密钥长度 256 位,分组模式是 GCM,摘要算法 SHA384 用于消息认证和产生随机数
OpenSSL 一个著名的开源密码学程序库和工具包,几乎支持所有公开的加密算法和协议,已经成为了事实上的标准

【2】对称加密与非对称加密

实现机密性最常用的手段是“加密”(encrypt),即将消息用某种方式转换成不易理解的乱码,只有掌握密钥才能再转换出原始文本;加密前的消息叫“明文”(plain text/clear text),加密后的乱码叫“密文”(cipher text),使用密钥还原明文的过程叫“解密”(decrypt),是加密的反操作,加密解密的操作过程就是“加密算法”;
由于 HTTPS、TLS 都运行在计算机上,所以“密钥”就是一长串的数字,并且度量单位是“位”(bit),而不是“字节”(byte);

【2.1】对称加密

“对称加密”即加密和解密时使用的密钥都是同一个,是“对称”的,只要保证了密钥的安全,那整个通信过程就具有了机密性;

TLS 里有非常多的对称加密算法可供选择,比如 RC4、DES、3DES、AES、ChaCha20 等,但前三种算法都被认为是不安全的,通常都禁止使用,目前常用的只有 AES 和 ChaCha20;

AES 即“高级加密标准”(Advanced Encryption Standard),密钥长度可以是 128、192 或 256,它是 DES 算法的替代者,安全强度很高,性能也很好,而且有的硬件还会做特殊优化,是应用最广泛的对称加密算法;
ChaCha20 是 Google 设计的另一种加密算法,密钥长度固定为 256 位,纯软件运行性能要超过 AES,曾经在移动客户端上比较流行,但 ARMv8 之后也加入了 AES 硬件优化,所以现在不再具有明显的优势,但仍然算得上是一个不错的算法;

加密分组模式
对称算法还有一个“分组模式”的概念,它可以让算法用固定长度的密钥加密任意长度的明文,把密钥转化为密文,最早有 ECB、CBC、CFB、OFB 等几种分组模式,但都陆续被发现有安全漏洞,所以现在基本都不怎么用了;最新的分组模式被称为 AEAD(Authenticated Encryption with Associated Data),在加密的同时增加了认证的功能,常用的是 GCM、CCM 和 Poly1305;
把上面这些组合起来,就可以得到 TLS 密码套件中定义的对称加密算法,比如,AES128-GCM,意思是密钥长度为 128 位的 AES 算法,使用的分组模式是 GCM;ChaCha20-Poly1305 的意思是 ChaCha20 算法,使用的分组模式是 Poly1305;

【2.2】非对称加密
对称加密中有一个很大的问题,即如何把密钥安全地传递给对方,术语叫“密钥交换”;在对称加密算法中只要持有密钥就可以解密,如果你和网站约定的密钥在传递途中被黑客窃取,那他就可以在之后随意解密收发的数据,通信过程也就没有机密性可言了;
非对称加密(也叫公钥加密算法),它有两个密钥,一个叫“公钥”(public key),一个叫“私钥”(private key),两个密钥是不同的,公钥可以公开给任何人使用,而私钥必须严格保密,公钥和私钥有个特别的“单向”性,虽然都可以用来加密解密,但公钥加密后只能用私钥解密,反过来,私钥加密后也只能用公钥解密;
非对称加密可以解决“密钥交换”的问题,网站秘密保管私钥,在网上任意分发公钥,你想要登录网站只要用公钥加密就行了,密文只能由私钥持有者才能解密,而黑客因为没有私钥,所以就无法破解密文;


非对称加密算法在 TLS 里只有很少的几种,比如 DH、DSA、RSA、ECC 等;
RSA 的安全性基于“整数分解”的数学难题,使用两个超大素数的乘积作为生成密钥的材料,想要从公钥推算出私钥是非常困难的;10 年前 RSA 密钥的推荐长度是 1024,但随着计算机运算能力的提高,现在 1024 已经不安全,普遍认为至少要 2048 位;
ECC(Elliptic Curve Cryptography)基于“椭圆曲线离散对数”的数学难题,使用特定的曲线方程和基点生成公钥和私钥,子算法 ECDHE 用于密钥交换,ECDSA 用于数字签名;
对比 RSA,ECC 在安全强度和性能上都有明显的优势,160 位的 ECC 相当于 1024 位的 RSA,而 224 位的 ECC 则相当于 2048 位的 RSA,因为密钥短,所以相应的计算量、消耗的内存和带宽也就少,加密解密的性能高;

【2.3】混合加密

TLS 的混合加密方式
1. 在通信刚开始的时候使用非对称算法,比如 RSA、ECDHE,首先解决密钥交换的问题;
2. 用随机数产生对称算法使用的“会话密钥”(session key),再用公钥加密,因为会话密钥很短,通常只有 16 字节或 32 字节,所以慢一点也无所谓;
3. 对方拿到密文后用私钥解密,取出会话密钥,这样,双方就实现了对称密钥的安全交换,后续就不再使用非对称加密,全都使用对称加密;

【3】数字签名与证书

【3.1】摘要算法

实现完整性的手段主要是摘要算法(Digest Algorithm),即散列函数、哈希函数(Hash Function),可以把摘要算法近似地理解成一种特殊的压缩算法,其能够把任意长度的数据“压缩”成固定长度、而且独一无二的“摘要”字符串,就好像是给这段数据生成了一个数字“指纹”;也可以把摘要算法理解成特殊的“单向”加密算法,它只有算法,没有密钥,加密后的数据无法解密,不能从摘要逆推出原文;

摘要算法需要处理“冲突”的可能性并且具有“单向性”和“雪崩效应”,输入的微小不同会导致输出的剧烈变化;
常见的摘要算法: 
MD5(Message-Digest 5) 能够生成 16 字节长度的数字摘要;
SHA-1(Secure Hash Algorithm 1),能够生成 20 字节长度的数字摘要;
SHA-2 是一系列摘要算法的统称,总共有 6 种,常用的有 SHA224、SHA256、SHA384,分别能够生成 28 字节、32 字节、48 字节的摘要;

【3.2】数字签名

实现“身份认证”和“不可否认”的手段主要是“数字签名”,即使用私钥再加上摘要算法;
数字签名的原理是把公钥私钥的用法反过来,即私钥加密、公钥解密;由于非对称加密效率太低,因此私钥只加密原文的摘要,这样运算量就小的多,而且得到的数字签名也很小,方便保管和传输;签名和公钥一样完全公开,任何人都可以获取;但这个签名只有用私钥对应的公钥才能解开,拿到摘要后,再比对原文验证完整性;

【3.3】数字证书和 CA

“公钥的信任”问题需要确认一个公认的可信第三方,让其作为“信任的起点,递归的终点”,构建起公钥的信任链,即 CA(Certificate Authority,证书认证机构);它具有极高的可信度,由它来给各个公钥签名,用自身的信誉来保证公钥无法伪造,是可信的;
CA 对公钥的签名认证的格式包含序列号、用途、颁发者、有效时间等等,把这些打成一个包再签名,完整地证明公钥关联的各种信息,形成“数字证书”(Certificate);知名的 CA 有 DigiCert、VeriSign、Entrust、Let’s Encrypt 等,它们签发的证书分 DV、OV、EV 三种,区别在于可信程度;其中,DV 是最低的,只是域名级别的可信;EV 是最高的,经过了法律和审计的严格核查,可以证明网站拥有者的身份;

【3.3.1】CA 的认证

【3.3.2】证书体系的弱点
1. CA 失误或者被欺骗,签发了错误的证书,虽然证书是真的,可它代表的网站却是假的;
2. CA 被黑客攻陷或者 CA 有恶意,因为它(即根证书)是信任的源头,导致整个信任链里的所有证书都不可信;
对策,针对第一种,开发出了 CRL(证书吊销列表,Certificate revocation list)和 OCSP(在线证书状态协议,Online Certificate Status Protocol),及时废止有问题的证书;对于第二种,因为涉及的证书太多,就只能操作系统或者浏览器撤销对 CA 的信任,列入“黑名单”,这样它颁发的所有证书就都会被认为是不安全的;

【4】TLS1.2 连接过程解析

【4.1】TLS 协议的组成
TLS 包含 记录协议、警报协议、握手协议、变更密码规范协议等子协议;
记录协议(Record Protocol)规定了 TLS 收发数据的基本单位即记录(record),所有的其他子协议都需要通过记录协议发出,但多个记录数据可以在一个 TCP 包里一次性发出,也并不需要像 TCP 那样返回 ACK;
警报协议(Alert Protocol)的职责是向对方发出警报信息,有点像是 HTTP 协议里的状态码;比如,protocol_version 是不支持旧版本,bad_certificate 是证书有问题,收到警报后另一方可以选择继续,也可以立即终止连接;
握手协议(Handshake Protocol),浏览器和服务器会在握手过程中协商 TLS 版本号、随机数、密码套件等信息,然后交换证书和密钥参数,最终双方协商得到会话密钥,用于后续的混合加密系统;
变更密码规范协议(Change Cipher Spec Protocol),实质是一个“通知”,告诉对方,后续的数据都将使用加密保护,那么反过来,在它之前,数据都是明文的;

下面的这张图简要地描述了 TLS 的握手过程,其中每一个“框”都是一个记录,多个记录组合成一个 TCP 包发送,最多经过两次消息往返(4 个消息)就可以完成握手,然后就可以在安全的通信环境里发送 HTTP 报文,实现 HTTPS 协议;

【4.2】ECDHE 握手过程

【4.3】RSA 握手过程

【4.4】双向认证
双向认证的流程只是在“Server Hello Done”之后,“Client Key Exchange”之前,客户端要发送“Client Certificate”消息,服务器收到后也把证书链走一遍,验证客户端的身份;

【5】TLS1.3特性解析

TLS1.3 的三个主要改进目标:兼容、安全与性能
最大化兼容性
TLS1.3 保持现有的记录格式不变,通过“伪装”来实现兼容,使得 TLS1.3 看上去“像是”TLS1.2使用新的扩展协议(Extension Protocol)可以区分 1.2 和 1.3,通过在记录末尾添加一系列的“扩展字段”来增加新的功能,老版本的 TLS 不认识它可以直接忽略,这就实现了“后向兼容”;在记录头的 Version 字段被兼容性“固定”的情况下,只要是 TLS1.3 协议,握手的“Hello”消息后面就必须有“supported_versions”扩展,它标记了 TLS 的版本号,使用它就能区分新旧协议;

Handshake Protocol: Client Hello
    Version: TLS 1.2 (0x0303)
    Extension: supported_versions (len=11)
        Supported Version: TLS 1.3 (0x0304)
        Supported Version: TLS 1.2 (0x0303)

强化安全
改进方面如 1.伪随机数函数由 PRF 升级为 HKDF(HMAC-based Extract-and-Expand Key Derivation Function);2. 明确禁止在记录协议里使用压缩;3. 废除了 RC4、DES 对称加密算法;4. 废除了 ECB、CBC 等传统分组模式;5. 废除了 MD5、SHA1、SHA-224 摘要算法;6. 废除了 RSA、DH 密钥交换算法和许多命名曲线;
TLS1.3 里只保留了 AES、ChaCha20 对称加密算法,分组模式只能用 AEAD 的 GCM、CCM 和 Poly1305,摘要算法只能用 SHA256、SHA384,密钥交换算法只有 ECDHE 和 DHE,椭圆曲线只保留 P-256 和 x25519 等 5 种;

提升性能
利用扩展,客户端在“Client Hello”消息里直接用“supported_groups”带上支持的曲线,比如 P-256、x25519,用“key_share”带上曲线对应的客户端公钥参数,用“signature_algorithms”带上签名算法;服务器收到后在这些扩展里选定一个曲线和参数,再用“key_share”扩展返回服务器这边的公钥参数,就实现了双方的密钥交换;

握手分析

【6】HTTPS的优化

HTTPS 连接大致上可以划分为两个部分,第一个是建立连接时的非对称加密握手,第二个是握手后的对称加密报文传输;
“HTTPS 连接慢”指的就是刚开始建立连接的那段时间,在 TCP 建连之后,正式数据传输之前,HTTPS 比 HTTP 增加了一个 TLS 握手的步骤,这个步骤最长可以花费两个消息往返,即 2-RTT;而在握手消息的网络耗时之外,还会有其他的一些“隐形”消耗,比如:产生用于密钥交换的临时公私钥对(ECDHE);验证证书时访问 CA 获取 CRL 或者 OCSP;非对称加密解密处理“Pre-Master”;

【6.1】硬件优化

HTTPS 连接是计算密集型,而不是 I/O 密集型
1. 选择更快的 CPU,最好还内建 AES 优化,这样即可以加速握手,也可以加速传输;
2. 选择“SSL 加速卡”,加解密时调用它的 API,让专门的硬件来做非对称加解密,分担 CPU 的计算压力;
3. “SSL 加速服务器”,用专门的服务器集群来彻底“卸载”TLS 握手时的加密解密计算;

【6.2】协议优化
1. 采用 TLS1.3,它大幅度简化了握手的过程,完全握手只要 1-RTT,而且更加安全;
2. 如果暂时不能升级到 1.3,只能用 1.2,那么握手时使用的密钥交换协议应当尽量选用椭圆曲线的 ECDHE 算法,它不仅运算速度快,安全性高,还支持“False Start”,能够把握手的消息往返由 2-RTT 减少到 1-RTT,达到与 TLS1.3 类似的效果;
3. 椭圆曲线也要选择高性能的曲线,最好是 x25519,次优选择是 P-256;
4. 对称加密算法方面,可以选用“AES_128_GCM”,它比“AES_256_GCM”略快一点点;

【6.3】证书优化
服务器的证书可以选择椭圆曲线(ECDSA)证书而不是 RSA 证书,因为 224 位的 ECC 相当于 2048 位的 RSA,即能够节约带宽也能减少客户端的运算量;
客户端的证书的验证其实是个很复杂的操作,除了要公钥解密验证多个证书签名外,因为证书还有可能会被撤销失效,客户端有时还会再去访问 CA,下载 CRL 或者 OCSP 数据,这又会产生 DNS 查询、建立连接、收发数据等一系列网络通信,增加好几个 RTT;
CRL(Certificate revocation list,证书吊销列表)由 CA 定期发布,里面是所有被撤销信任的证书序号,查询这个列表就可以知道证书是否有效,但 CRL 因为是“定期”发布,就有“时间窗口”的安全隐患,而且随着吊销证书的增多,列表会越来越大,一个 CRL 经常会上 MB,因此基本不用了;
OCSP(在线证书状态协议,Online Certificate Status Protocol),向 CA 发送查询请求,让 CA 返回证书的有效状态,但 OCSP 也要多出一次网络请求的消耗,而且还依赖于 CA 服务器,如果 CA 服务器很忙,那响应延迟也是等不起的;
“OCSP Stapling”(OCSP 装订),它可以让服务器预先访问 CA 获取 OCSP 响应,然后在握手时随着证书一起发给客户端,免去了客户端连接 CA 服务器查询的时间;

【6.4】会话复用
1. “Session ID”,就是客户端和服务器首次连接后各自保存一个会话的 ID 号,内存里存储主密钥和其他相关的信息;当客户端再次连接时发一个 ID 过来,服务器就在内存里找,找到就直接用主密钥恢复会话状态,跳过证书验证和密钥交换,只用一个消息往返就可以建立安全通信;

2. “Session Ticket”,存储的责任由服务器转移到了客户端,服务器加密会话信息,用“New Session Ticket”消息发给客户端,让客户端保存;重连的时候,客户端使用扩展“session_ticket”发送“Ticket”而不是“Session ID”,服务器解密后验证有效期,就可以恢复会话,开始加密通信;

【6.5】预共享密钥
“Pre-shared Key”,在发送 Ticket 的同时会带上应用数据(Early Data),免去了服务器确认步骤,但“PSK”为了追求效率而牺牲了一点安全性,容易受到“重放攻击”(Replay attack)的威胁,黑客可以截获“PSK”的数据,反复向服务器发送;解决的办法是只允许安全的 GET/HEAD 方法,在消息里加入时间戳、“nonce”验证,“一次性票证”限制重放;

参考致谢
本博客为博主的学习实践总结,并参考了众多博主的博文,在此表示感谢,博主若有不足之处,请批评指正。

【1】透视HTTP协议

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章