learn-tech/专栏/周志明的架构课/29_传输(下):数字证书与传输安全层.md
2024-10-16 06:37:41 +08:00

197 lines
18 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

因收到Google相关通知网站将会择期关闭。相关通知内容
29 _ 传输(下):数字证书与传输安全层
你好,我是周志明。
上节课,我们花了很多时间来学习传输安全层中的摘要、加密和签名的主要用途和差别,在最后,我给你留了一个问题:数字签名需要分发公钥,但在网络世界里,“公开”具体是一种什么操作?如何保证每一个获取公钥的服务,拿到的公钥就是授权服务器所希望它拿到的呢?在网络中一切皆不可信任的假设前提下,任何传输都有可能被篡改,那这个问题能够解决吗?
答案其实是可以的,这就是数字证书要解决的问题。
所以接下来,我们就先从数字证书如何达成共同信任开始说起,一起来了解下在传输安全的过程中,数字证书与传输安全层的相关实现细节。
如何通过数字证书达成共同信任?
有了哈希摘要、对称和非对称加密之后,签名还是无法保证负载中的信息不可篡改、不可抵赖。所以,当我们无法以“签名”的手段来达成信任时,就只能求助于其他途径。
现在,你不妨想想真实的世界中,我们是如何达成信任的。其实不外乎以下这两种:
基于共同私密信息的信任-
比如某个陌生号码找你,说是你的老同学,生病了要找你借钱。你能够信任他的方式是向对方询问一些你们两个应该知道,而且只有你们两个知道的私密信息,如果对方能够回答上来,他有可能真的是你的老同学,否则他十有八九就是个诈骗犯。
基于权威公证人的信任-
如果有个陌生人找你,说他是警察,让你把存款转到他们的安全账号上。你能够信任他的方式是去一趟公安局,如果公安局担保他确实是个警察,那他有可能真的是警察,否则他也十有八九就是个诈骗犯。
那回到网络世界中我们其实并不能假设授权服务器和资源服务器是互相认识的所以通常不太会采用第一种方式。而第二种就是目前保证公钥可信分发的标准这个标准有一个名字公开密钥基础设施Public Key InfrastructurePKI
额外知识公开密钥基础设施Public Key InfrastructurePKI-
又称公开密钥基础架构、公钥基础建设、公钥基础设施、公开密码匙基础建设或公钥基础架构,是一组由硬件、软件、参与者、管理政策与流程组成的基础架构,其目的在于创造、管理、分配、使用、存储以及撤销数字证书。-
密码学上公开密钥基础建设借着数字证书认证中心Certificate AuthorityCA将用户的个人身份跟公开密钥链接在一起。对每个证书中心用户的身份必须是唯一的。链接关系通过注册和发布过程创建取决于担保级别链接关系可能由CA的各种软件或在人为监督下完成。PKI的确定链接关系的这一角色称为注册管理中心Registration AuthorityRA。RA确保公开密钥和个人身份链接可以防抵赖。
咱们不必纠缠于PKI概念上的内容只要知道里面定义的“数字证书认证中心”就相当于前面例子中“权威公证人”的角色它是负责发放和管理数字证书的权威机构。
当然任何人包括你我也都可以签发证书只是不权威罢了而CA作为受信任的第三方就承担了公钥体系中公钥的合法性检验的责任。
可是这里和现实世界仍然有一些区别。在现实世界里你去找的公安局大楼不太可能是剧场布景冒认的而网络世界里在假设所有网络传输都有可能被截获冒认的前提下“去CA中心进行认证”本身也是一种网络操作。那你就要问了这跟之前的“去获取公钥”的操作在本质上不是没什么差别吗
其实还是有差别的世界上的公钥成千上万、不可枚举而权威的CA中心则应该是可数的。“可数的”就意味着可以不通过网络而是在浏览器与操作系统出厂时就预置好或者是提前就安装好如银行的证书。比如说下图就是我机器上现存的根证书
那到这里其实就出现了我们这节课要探讨的主角之一证书Certificate
证书是权威CA中心对特定公钥信息的一种公证载体你也可以理解为是权威CA对特定公钥未被篡改的签名背书。由于客户的机器上已经预置了这些权威CA中心本身的证书可以叫做CA证书或者根证书这样就让我们在不依靠网络的前提下使用根证书里面的公钥信息对其所签发的证书中的签名进行确认。
所以到这里,我们就终于打破了鸡生蛋、蛋生鸡的循环,使得整套数字签名体系有了坚实的逻辑基础。
PKI中采用的证书格式是X.509标准格式,它定义了证书中应该包含哪些信息,并描述了这些信息是如何编码的。其中最关键的,就是认证机构的数字签名和公钥信息两项内容。
那么下面我们就通过一个标准X.509格式的CA证书的例子来看看一个数字证书具体都包含了哪些内容。
第一是版本号Version它会指出该证书使用了哪种版本的X.509标准版本1、版本2或是版本3。版本号会影响证书中的一些特定信息在这个例子当中目前的版本为3。
Version: 3 (0x2)
第二是序列号Serial Number这是由证书颁发者分配的本证书的唯一标识符。
Serial Number: 04:00:00:00:00:01:15:4b:5a:c3:94
第三是签名算法标识符Signature Algorithm ID它是签证书的算法标识由对象标识符加上相关的参数组成用于说明本证书所用的数字签名算法。比如SHA1和RSA的对象标识符就用来说明该数字签名是利用RSA对SHA1的摘要结果进行加密。
Signature Algorithm: sha1WithRSAEncryption
第四是认证机构的数字签名Certificate Signature这是使用证书发布者私钥生成的签名以确保这个证书在发放之后没有被篡改过。
第五是认证机构Issuer Name 即证书颁发者的可识别名。
Issuer: C=BE, O=GlobalSign nv-sa, CN=GlobalSign Organization Validation CA - SHA256 - G2
第六是有效期限Validity Period 即证书起始日期和时间以及终止日期和时间,意为指明证书在这两个时间内有效。
Validity
Not Before: Nov 21 08:00:00 2020 GMT
Not After : Nov 22 07:59:59 2021 GMT
第七是主题信息Subject证书持有人唯一的标识符Distinguished Name这个名字在整个互联网上应该是唯一的通常使用的是网站的域名。
Subject: C=CN, ST=GuangDong, L=Zhuhai, O=Awosome-Fenix, CN=*.icyfenix.cn
第八是公钥信息Public-Key 它包括了证书持有人的公钥、算法(指明密钥属于哪种密码系统)的标识符和其他相关的密钥参数。
那么到此为止数字签名的安全性其实已经可以完全自洽了但相信你大概也已经感受到了这条信任链的复杂与繁琐如果从确定加密算法到生成密钥、公钥分发、CA认证、核验公钥、签名、验证每一个步骤都要由最终用户来完成的话这种意义的“安全”估计只能一直是存于实验室中的阳春白雪。
所以,如何把这套繁琐的技术体系,自动化地应用于无处不在的网络通讯之中,就是接下来我们要讨论的主题了。
传输安全层是如何隐藏繁琐的安全过程的?
在计算机科学里,隔离复杂性的最有效手段(没有之一)就是分层,如果一层不够就再加一层,这点在网络中更是体现得淋漓尽致。
OSI模型、TCP/IP模型从物理特性比特流开始将网络逐层封装隔离到了HTTP协议这种面向应用的协议里使用者就已经不会去关心网卡/交换机是如何处理数据帧、MAC地址的了也不会去关心ARP如何做地址转换不会去关心IP寻址、TCP传输控制等细节。
那么想要在网络世界中让用户无感知地实现安全通讯最合理的做法就是在传输层之上、应用层之下加入专门的安全层来实现。这样对上层原本是基于HTTP的Web应用来说甚至都察觉不到有什么影响。
而且构建传输安全层这个想法几乎可以说是和万维网的历史一样长早在1994年就已经有公司开始着手去实践了
1994年网景Netscape公司开发了SSL协议Secure Sockets Layer的1.0版这是构建传输安全层的起源但是SSL 1.0从未正式对外发布过。
1995年Netscape把SSL升级到2.0版,正式对外发布,但是刚刚发布不久,就被发现有严重漏洞,所以并未大规模使用。
1996年修补好漏洞的SSL 3.0对外发布这个版本得到了广泛的应用很快成为Web网络安全层的事实标准。
1999年互联网标准化组织接替网景公司将SSL改名为TLSTransport Layer Security随即就形成了传输安全层的国际标准。第一个正式的版本是RFC 2246定义的TLS 1.0该版TLS的生命周期极长直到2020年3月主流浏览器Chrome、Firefox、IE、Safari才刚刚宣布同时停止TLS 1.0/1.1的支持。而讽刺的是由于停止后许多政府网站被无法被浏览此时又正值新冠病毒的爆发期Firefox紧急发布公告宣布撤回该改动因此目前TLS 1.0的生命还在顽强延续。
2006年TLS的第一个升级版1.1发布RFC 4346但它除了增加对CBC攻击的保护外几乎没有任何改变沦为了被遗忘的孩子当时也很少有人会使用TLS 1.1甚至TLS 1.1根本都没有被提出过有啥已知的协议漏洞。
2008年TLS 1.1发布2年之后TLS 1.2标准发布RFC 5246迄今超过90%的互联网HTTPS流量都是由TLS 1.2所支持的,现在我们仍在使用的浏览器几乎都完美支持了该协议。
2018年最新的TLS 1.3RFC 8446发布比起前面版本相对温和的升级TLS 1.3做出了一些激烈的改动修改了从1.0起一直没有大变化的两轮四次2-RTT握手首次连接仅需一轮1-RTT握手即可完成在有连接复用支持的时候甚至可以把TLS 1.2原本的1-RTT下降到0-RTT显著提升了访问速度。
那么接下来我就以现在被广泛使用的TLS 1.2为例,给你介绍一下传输安全层是如何保障所有信息都是第三方无法窃听(加密传输)、无法篡改(一旦篡改通讯算法会立刻发现)、无法冒充(证书验证身份)的。
TLS 1.2在传输之前的握手过程中,一共需要进行上下两轮、共计四次的通讯。我们来看一下这个握手过程的时序图:
下面,我们就一一来详细解读一下这个过程。
第一步客户端请求Client Hello
客户端向服务器请求进行加密通讯,在这个请求里面,它会以明文的形式,向服务端提供以下信息:
支持的协议版本比如TLS 1.2。但是你要注意1.0至3.0分别代表了SSL1.0至3.0而TLS1.0则是3.1一直到TLS1.3的3.4。
一个客户端生成的32 Bytes随机数。这个随机数将稍后用于产生加密的密钥。
一个可选的SessionID。注意你不要和前面的Cookie-Session机制混淆了这个SessionID是指传输安全层的Session它是为了TLS的连接复用而设计的。
一系列支持的密码学算法套件。比如TLS_RSA_WITH_AES_128_GCM_SHA256代表着密钥交换算法是RSA加密算法是AES128-GCM消息认证码算法是SHA256。
一系列支持的数据压缩算法。
其他可扩展的信息。为了保证协议的稳定后续对协议的功能扩展大多都是添加到这个变长结构中。比如TLS 1.0中由于发送的数据并不包含服务器的域名地址导致了一台服务器只能安装一张数字证书这对虚拟主机来说就很不方便所以从TLS 1.1起就增加了名为“Server Name”的扩展信息以便一台服务器给不同的站点安装不同的证书。
第二步服务器回应Server Hello
服务器接收到客户端的通讯请求后,如果客户端声明支持的协议版本和加密算法组合,与服务端相匹配的话,就向客户端发出回应。如果不匹配,将会返回一个握手失败的警告提示。这次回应同样是以明文发送的,主要包括以下信息:
服务端确认使用的TLS协议版本。
第二个32 Bytes的随机数稍后用于产生加密的密钥。
一个SessionID以后可通过连接复用减少一轮握手。
服务端在列表中选定的密码学算法套件。
服务端在列表中选定的数据压缩方法。
其他可扩展的信息。
如果协商出的加密算法组合是依赖证书认证的服务端还要发送出自己的X.509证书,而证书中的公钥是什么,也必须根据协商的加密算法组合来决定。
密钥协商消息这部分内容对于不同的密码学套件有着不同的价值。比如对于ECDH + anon这样的密钥协商算法组合来说基于椭圆曲线的ECDH算法可以在双方通讯都公开的情况下协商出一组只有通讯双方知道的密钥就不需要依赖证书中的公钥而是通过Server Key Exchange消息协商出密钥。
第三步客户端确认Client Handshake Finished
由于密码学套件的组合复杂多样这里我就只用RSA算法作为密钥交换算法来给你举个例子介绍下客户端确认的后续过程。
首先,客户端在收到服务器应答后,要先验证服务器的证书合法性。然后,如果证书不是可信机构颁布的,或者是证书中的信息存在问题,比如域名与实际域名不一致、或证书已经过期、或通过在线证书状态协议得知证书已被吊销,等等,这都会向访问者显示一个“证书不可信任”的警告,由用户自行选择是否还要继续通信。
而如果证书没有问题,客户端就会从证书中取出服务器的公钥,并向服务器发送以下信息:
客户端证书可选。部分服务端并不是面向全公众的而是只对特定的客户端提供服务此时客户端就需要发送它自身的证书来证明身份。如果不发送或者验证不通过服务端可自行决定是否要继续握手或者返回一个握手失败的信息。客户端需要证书的TLS通讯也被称为“双向TLS”Mutual TLS常简写为mTLS这是云原生基础设施的主要认证方法也是基于信道认证的最主流形式。
第三个32 Bytes的随机数这个随机数不再是明文发送而是以服务端传过来的公钥加密的它被称为PreMasterSecret将与前两次发送的随机数一起根据特定算法计算出48 Bytes的MasterSecret这个MasterSecret也就是为后续内容传输时的对称加密算法所采用的私钥。
编码改变通知,表示随后的信息都将用双方商定的加密方法和密钥发送。
客户端握手结束通知,表示客户端的握手阶段已经结束。这一项同时也是前面发送的所有内容的哈希值,以供服务器校验。
第四步服务端确认Server Handshake Finished
服务端向客户端回应最后的确认通知,包括以下信息:
编码改变通知,表示随后的信息都将用双方商定的加密方法和密钥发送。
服务器握手结束通知,表示服务器的握手阶段已经结束。这一项同时也是前面发送的所有内容的哈希值,以供客户端校验。
那么到这里整个TLS握手阶段就宣告完成一个安全的连接就成功建立了。你要知道每一个连接建立的时候客户端和服务端都会通过上面的握手过程协商出许多信息比如一个只有双方才知道的随机产生的密钥、传输过程中要采用的对称加密算法例子中的AES128、压缩算法等此后该连接的通讯将使用此密钥和加密算法进行加密、解密和压缩。
这种处理方式对上层协议的功能上完全透明的在传输性能上会有下降但在功能上完全不会感知到有TLS的存在。建立在这层安全传输层之上的HTTP协议就被称为“HTTP Over SSL/TLS”也即是我们所熟知的HTTPS。
另外从上面握手协商的过程中我们还可以得知HTTPS并非不是只有“启用了HTTPS”和“未启用HTTPS”的差别采用不同的协议版本、不同的密码学套件、证书是否有效、服务端/客户端对面对无效证书时的处理策略如何都会导致不同HTTPS站点的安全强度的不同。因此并不能说只要启用了HTTPS就必定能够安枕无忧。
小结
今天我们通过在网络中如何安全分发公钥这个问题引出了如何通过数字证书达成共同信任、如何通过PKI体系来签发数字证书。在了解了数字证书的工作原理后你还要了解的重点是如何通过传输安全层把繁琐的安全过程隐藏起来让开发者不需要时刻注意到那些麻烦而又琐碎的安全细节。
一课一思
除了TLS你还知道数字证书有什么具体应用吗欢迎给我留言分享你的思考。
如果你觉得有收获,也欢迎你把今天的内容分享给更多的朋友。感谢你的阅读,我们下一讲再见。