SSL TLS协议?https协议?数字签名?看这一篇就够了

198 阅读7分钟

此篇文章灵感来自于李永乐老师区块链防伪加密的讲解。传送门

ssl/tls 协议是什么?

SSL(Secure Sockets Layer 安全套接层)是一种标准安全协议,旨在 两个通信应用程序 之间安全交换信息(加密)。

那 TLS 又是什么?Transport Layer Security (TLS)是SSL协议的升级版,TLS 1.0通常被标示为SSL 3.1,TLS 1.1为SSL 3.2,TLS 1.2为SSL 3.3。现在习惯将这个两个组合在一起称为 SSL/TLS,只要知道它是一种用于加密的安全协议就好了。

ssl/tls 的位置

SSL介于应用层和传输层之间。应用层数据不再直接传递给传输层,而是传递给SSL层,SSL层对从应用层收到的数据进行加密,并增加自己的SSL头。

2012100609461432.png

不使用SSL/TLS的HTTP通信,就是不加密的通信。所有信息明文传播,带来了三大风险。

(1) 窃听风险(eavesdropping):第三方可以获知通信内容。

(2) 篡改风险(tampering):第三方可以修改通信内容。

(3) 冒充风险(pretending):第三方可以冒充他人身份参与通信。

SSL/TLS协议是为了解决这三大风险而设计的,希望达到:

(1) 所有信息都是加密传播,第三方无法窃听。

(2) 具有校验机制,一旦被篡改,通信双方会立刻发现。

(3) 配备身份证书,防止身份被冒充。

HTTPS 经由 HTTP 进行通信,但利用 SSL/TLS 来加密数据包。

💥所以,ssl/tls + http(超文本传输协议) = https(超文本传输安全协议)

https 运行的基本过程

一、ssl/tls 协议执行握手阶段(非对称加密)

握手阶段分成五步:

  • 第一步,客户端给出tls协议版本号、一个客户端生成的随机数(Client random),以及客户端支持的加密方法。

  • 第二步,服务器确认双方使用的加密方法,并给出数字证书、以及一个服务器生成的随机数(Server random)。

  • 第三步,客户端确认数字证书有效,然后生成一个新的随机数(Premaster secret),并使用数字证书中的公钥,加密这个随机数,发给服务器。

  • 第四步,服务器使用自己的私钥,获取客户端发来的随机数(即Premaster secret)。

  • 第五步,客户端和服务器根据约定的加密方法,使用前面的三个随机数,生成"对话密钥"(session key),用来加密接下来的整个对话过程。

img

二、握手结束,使用 http 协议通信,采用"对话密钥"加密消息(对称加密)

整个握手阶段全部结束。接下来,客户端与服务器进入加密通信,就完全是使用普通的HTTP协议,只不过用"会话密钥"加密内容。


服务器私钥的作用

握手阶段有三点需要注意。

  1. 生成对话密钥一共需要三个随机数

  2. 握手之后的对话使用 "对话密钥" 加密(对称加密),服务器的公钥和私钥只用于加密和解密"对话密钥"(非对称加密),无其他作用。

  3. 服务器公钥放在服务器的数字证书之中。

从上面第二点可知,整个对话过程中(握手阶段和其后的对话),服务器的公钥和私钥只需要用到一次。

举个例子:

某些客户(比如银行)想要使用外部CDN,加快自家网站的访问速度,但是出于安全考虑,不能把私钥交给CDN服务商。这时,完全可以把私钥留在自家服务器,只用来解密对话密钥,其他步骤都让CDN服务商去完成。

img

上图中,银行的服务器只参与第四步,后面的对话都不再会用到私钥了。

所以 CloudFlare 提供的 Keyless 服务,即你把网站放到它们的CDN上,不用提供自己的私钥,也能使用 SSL 加密链接。

DH算法的握手阶段

整个握手阶段都不加密(也没法加密),都是明文的。因此,如果有人窃听通信,他可以知道双方选择的加密方法,以及三个随机数中的两个。整个通话的安全,只取决于第三个随机数(Premaster secret)能不能被破解。

虽然理论上,只要服务器的公钥足够长(比如2048位),那么Premaster secret可以保证不被破解。但是为了足够安全,我们可以考虑把握手阶段的算法从默认的RSA算法,改为 Diffie-Hellman算法(简称DH算法)。

采用DH算法后,Premaster secret不需要传递,双方只要交换各自的参数,就可以算出这个随机数。

img

上图中,第三步和第四步由传递Premaster secret变成了传递DH算法所需的参数(Server DH paramerter & Client DH parameter),然后双方各自算出Premaster secret。这样就提高了安全性。

为什么这么说呢?

因为就算中间人拿到了 server 以及 client 的 DH 参数,也无法计算出第三个随机数(Premaster secret)。

请看下图,DH 算法的是利用以下原理,截自DH算法:(爱丽丝与鲍伯分别代表客户端与服务器)

img

相关问题

客户端如何验证数字证书?

数字签名防止数据被篡改

服务器的数字证书(digital certificate) 中包含了服务器的公钥、组织信息、有效时间、证书序列号等明文信息,同时包含一个 CA 生成的数字签名。

证书签名过程:

  1. CA 使用 Hash 函数来计算服务器提交的明文信息,并得出信息摘要(digest)

  2. CA 再使用私钥对信息摘要进行加密,加密后的密文就是 CA 颁发给服务器的 数字签名。盖章啦😁

在客户端与服务器ssl握手时,服务器向客户端发送数字证书。

客户端验证过程:

  1. 客户端读取证书中的明文信息,采用 CA 签名时相同的 Hash 函数来计算并得到 信息摘要A
  2. 客户端再利用 CA 公钥来解密签名数据,得到 信息摘要B
  3. 对比信息摘要 A 和信息摘要 B,如果一致证书是合法的。
  4. 同时客户端还会验证证书相关的域名信息、有效时间等。

下图是服务器向客户端发送信息、签名与验证的过程,与 CA 证书验证大致相同:

私钥数字签名;公钥解密签名。最终验证摘要

WechatIMG25.jpeg

由上图可以看到,最终验证摘要是否相同,相同则信息未被修改过。

关于数字签名更详细介绍请跳转这里

关于 tls 版本问题

两个通信应用程序(服务器<=>服务器,浏览器<=>服务器等等)之间必须保证 tls 支持的版本一致性,若不一致被请求一方关闭加密通信。

实际开发中遇到的情况:

  • 环境:node v12,bird,server1(support tls v1.0) server2(support tls v1.0 tls v1.1 tls v1.2 tls v1.3)

bird 为本地node开发代理服务器

  • 问题描述:

本地启动 bird 去连接 server2,一切正常访问。

本地启动 bird 去连接 server1,发现如下问题:

image

  • 问题分析:

    • node v11.4之后对 tls 最小支持的版本为 v1.2

    image

    • server1 仅支持 tls v1.0

    版本支持不一致,服务器关闭加密通信。

  • 解决方案:

第一种:启动 bird(node) 时, 添加 --tls-min-v1.0 , 使 node 支持的最小版本为 v1.0。

node --tls-min-v1.0 run.js

第二种:node 降级至 11.4 以下。

第三种:server 支持 tls 高版本。

参考

  1. 图解SSL/TLS协议 by 阮一峰
  2. SSL协议详解
  3. ssl/tls是什么?是怎么工作的?
  4. SSL/TLS协议运行机制的概述 by 阮一峰