数字证书
现实世界中有两种达成信任的方式:
- 基于共同私密信息的信任
譬如某个陌生号码找你,说是你的老同学,生病了要找你借钱。你能够信任他的方式是向对方询问一些你们两个应该知道,且只有你们两个知道的私密信息,如果对方能够回答上来,他有可能真的是你的老同学,否则他十有八九就是个诈骗犯。
- 基于权威公证人的信任
如果有个陌生人找你,说他是警察,让你把存款转到他们的安全账号上。你能够信任他的方式是去一趟公安局,如果公安局担保他确实是个警察,那他有可能真的是警察,否则他十有八九就是个诈骗犯。
零知识证明
零知识证明(Zero—Knowledge Proof)是由S.Goldwasser、S.Micali及C.Rackoff在20世纪80年代初提出的。它指的是证明者能够在不向验证者提供任何有用的信息的情况下,使验证者相信某个论断是正确的。零知识证明实质上是一种涉及两方或更多方的协议,即两方或更多方完成一项任务所需采取的一系列步骤。证明者向验证者证明并使其相信自己知道或拥有某一消息,但证明过程不能向验证者泄露任何关于被证明消息的信息。大量事实证明,零知识证明在密码学中非常有用。如果能够将零知识证明用于验证,将可以有效解决许多问题。
例子
A要向B证明自己拥有某个房间的钥匙,假设该房间只能用钥匙打开锁,其他任何方法都打不开,而且B确定该房间内有某一物体。此时A用自己拥有的钥匙打开该房间的门,然后把物体拿出来出示给B,从而证明自己确实拥有该房间的钥匙。在这个过程中,证明者A能够在不给验证者B看到钥匙的情况下,使B相信他是有钥匙开门的。
非对称加密
非对称加密的一个重要特点是:使用公钥加密的数据必须使用私钥才能解密,同样的,使用私钥加密的数据必须使用公钥解密。正是因为这个特点,网站就可以在自己的证书中公开自己的公钥,并使用自己的私钥将自己的身份信息进行加密一起公开出来,这段被私钥加密的信息就是证书的数字签名,浏览器在获取到证书之后,通过证书里的公钥对签名进行解密,如果能成功解密,则说明证书确实是由这个网站发布的,因为只有这个网站知道他自己的私钥(如果他的私钥没有泄露的话)。
当然,如果只是简单的对数字签名进行校验的话,还不能完全保证这个证书确实就是网站所有,黑客完全可以在中间进行劫持,使用自己的私钥对网站身份信息进行加密,并将证书中的公钥替换成自己的公钥,这样浏览器同样可以解密数字签名,签名中身份信息也是完全合法的。这就好比那些地摊上伪造公章的小贩,他们可以伪造出和真正的公章完全一样的出来以假乱真。为了解决这个问题,信息安全的专家们引入了 CA ,全称为 Certificate Authority ,证书授权中心,它是专门负责管理和签发证书的第三方机构。
CA 证书可以具有层级结构,它建立了自上而下的信任链,下级 CA 信任上级 CA ,下级 CA 由上级 CA 颁发证书并认证。 最顶部的证书称之为根证书(root certificate),根证书由自己证明自己,换句话来说也就是根证书是不需要证明的。
SSL/TLS
传输安全层是如何保障所有信息都是第三方无法窃听(加密传输)、无法篡改(一旦篡改通信算法会立刻发现)、无法冒充(证书验证身份)的。TLS 1.2 在传输之前的握手过程一共需要进行上下两轮、共计四次通信
-
客户端请求:Client Hello
客户端向服务器请求进行加密通信,在这个请求里面,它会以明文的形式,向服务端提
供以下信息。- 支持的协议版本,譬如 TLS 1.2。但是要注意,1.0 至 3.0 分别代表 SSL1.0 至 3.0,TLS
1.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”的扩展信息,以便一台服务器给不同的站点安装不同的证书。
- 支持的协议版本,譬如 TLS 1.2。但是要注意,1.0 至 3.0 分别代表 SSL1.0 至 3.0,TLS
-
服务器回应: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 就必定能够安枕无忧。