【计算机网络】HTTPS

20 阅读13分钟

HTTPS

HTTPS 在 HTTP 与 TCP 层之间加入了 SSL/TLS 协议,可以很好的解决了上述的风险:

  • 信息加密:混合加密,防止窃听。
  • 校验机制:摘要算法+数字签名,无法篡改通信内容。
  • 身份证书:数字证书,防止伪造。

混合加密

  • 对称加密:使用一个密钥,运算速度快,密钥必须保密,无法做到安全的密钥交换。

  • 非对称加密:使用公钥和私钥,公钥可以任意分发而私钥保密,解决了密钥交换问题但速度慢。

  • 混合加密:

    • 在通信建立前:非对称加密的方式交换「会话秘钥」。

    • 通信过程中使用对称加密的「会话密钥」加密明文数据。

摘要算法 + 数字签名

  • 摘要算法(哈希函数):对内容计算出哈希值一起发送,对方收到再计算一遍,一致说明内容未篡改。

Why?

内容和哈希值一起被篡改,无法分辨

How?

  • 数字签名:对内容的哈希值加密,私钥对信息加密,公钥解密。私钥是不可泄露的,如果公钥能正常解密出私钥加密的内容,就能证明这个消息是来源于持有私钥身份的人发送的。

数字证书

Why?

防止公钥是伪造的,被做了局。

How?

  • 数字证书:第三方可信单位确保公钥的真实性

数字证书签发和验证流程

数字证书通常包含了:

  • 公钥;
  • 持有者信息;
  • 证书认证机构(CA)的信息;
  • CA 对这份文件的数字签名及使用的算法;
  • 证书有效期;
  • 还有一些其他额外信息;

CA 签发证书的过程:

  • CA 会把持有者的公钥、用途、颁发者、有效时间等信息打成一个包, Hash 计算得到一个 Hash 值;
  • CA 会使用自己的私钥将该 Hash 值加密,生成 Certificate Signature,也就是 CA 对证书做了签名;
  • 最后将 Certificate Signature 添加在文件证书上,形成数字证书;

客户端校验服务端的数字证书的过程:

  • 客户端会使用同样的 Hash 算法获取该证书的 Hash 值 H1;

  • 通常浏览器和操作系统中集成了 CA 的公钥信息,公钥解密 Certificate Signature 内容,得到 Hash 值 H2 ;

  • 最后比较 H1 和 H2,如果值相同,则为可信赖的证书,否则则认为证书不可信。

证书信任链

Why?

向 CA 申请的证书一般不是根证书签发的,而是由中间证书签发的

三级层级关系的证书的验证过程如下:

  • 直到证书的签发机构,然后向 CA 请求该中间证书。
  • 中间证书没有上级签发机构,说明它是根证书,也就是自签证书。软件会检查此证书有否已预载于根证书清单上,如果有,则可以利用根证书中的公钥去验证。
  • 依次向下验证。

Root CA 为什么不直接颁发证书?

确保根证书的绝对安全性,将根证书隔离地越严格越好,不然根证书如果失守了,那么整个信任链都会有问题。

SSL/TLS 流程

  1. ClientHello:

    1. 客户端支持的 TLS 协议版本,如 TLS 1.2 版本。
    2. 客户端生产的随机数(Client Random),后面用于生成「会话秘钥」条件之一。
    3. 客户端支持的密码套件列表,如 RSA 加密算法。
  2. SeverHello

    1. 确认 TLS 协议版本,如果浏览器不支持,则关闭加密通信。
    2. 服务器生产的随机数(Server Random),也是后面用于生产「会话秘钥」条件之一。
    3. 确认的密码套件列表,「(密钥交换算法 + 签名算法) + 对称加密算法 + 摘要算法」。
    4. 服务器的数字证书,用户CA解密得到公钥。
  3. 客户端回应

    1. 首先通过浏览器或者操作系统中的 CA 公钥,确认服务器的数字证书的真实性。如果证书没有问题,客户端会从数字证书中取出服务器的公钥,然后使用它加密报文,向服务器发送如下信息:

      • 一个随机数(pre-master key)。该随机数会被服务器公钥加密。
      • 加密通信算法改变通知,表示随后的信息都将用「会话秘钥」加密通信。
      • 客户端握手结束通知,表示客户端的握手阶段已经结束。这一项同时把之前所有内容的发生的数据做个摘要,用来供服务端校验。
    2. 服务器和客户端有了这三个随机数(Client Random、Server Random、pre-master key),接着就用双方协商的加密算法,各自生成本次通信的「会话秘钥」。

  4. 服务器的最后回应

    1. 服务器收到客户端的第三个随机数(pre-master key)之后,通过协商的加密算法,计算出本次通信的「会话秘钥」。然后,向客户端发送最后的信息:

      • 加密通信算法改变通知,表示随后的信息都将用「会话秘钥」加密通信。

      • 服务器握手结束通知,表示服务器的握手阶段已经结束。这一项同时把之前所有内容的发生的数据做个摘要,用来供客户端校验。

每一个「框」都是一个记录(record),记录是 TLS 收发数据的基本单位,类似于 TCP 里的 segment。多个记录可以组合成一个 TCP 包发送,所以通常经过「四个消息」就可以完成 TLS 握手,也就是需要 2个 RTT 的时延。

RSA 算法的缺陷

  • 不支持前向保密。一旦服务端的私钥泄漏了,过去被第三方截获的所有 TLS 通讯密文都会被破解。

ECDHE 算法

离散对数

ECDHE 密钥协商算法是 DH 算法演进过来。DH 算法使用离散对数,是非对称加密算法, 因此它可以用于密钥交换

  • 底数 a 和模数 p(大质数) 是离散对数的公共参数,b 是真数,i 是对数。
  • 从左向右任意,右向左难

DH算法

  • p、g:公开数
  • a、b:私钥
  • 公钥 A = G ^ a ( mod P );
  • 公钥 B = G ^ b ( mod P );
  • K = B ^ a ( mod P ) = G ^ b ( mod P ) ^ a ( mod P )
  • K = A ^ b ( mod P ) = G ^ a ( mod P ) ^ b ( mod P )
  • 得到了只有他两个人相互知道的数K

DHE算法

根据私钥生成的方式,DH 算法分为两种实现:

  • static DH 算法,已废弃:不具备前向安全性

    • 有一方的私钥是静态的,服务端不变,客户端的私钥则是随机生成的。
    • 由截获海量的密钥协商过程的数据,暴力破解出服务器的私钥。
  • DHE 算法

    • 双方的私钥在每次密钥都是随机生成的、临时的,E 全称是 ephemeral(临时性的)。

ECDHE算法

Why?

DHE 算法由于计算性能不佳

How?

在 DHE 算法的基础上利用了 ECC 椭圆曲线特性,可以用更少的计算量计算出公钥,以及最终的会话密钥。

ECDHE握手过程

  • TLS 第一次握手

    • 客户端「Client Hello」消息:TLS 版本号、支持的密码套件列表,以及生成的随机数(Client Random)
  • TLS 第二次握手

    • 服务端「Server Hello」消息:确认的 TLS 版本号,随机数(Server Random),密码套件。TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384

      • 密钥协商算法:ECDHE;
      • 签名算法:RSA;
      • 通信加密 AES 对称算法,密钥长度 256 位,分组模式是 GCM;
      • 摘要算法:SHA384;
    • 发送「Certificate」消息,会把证书也发给客户端。

    • 发送「Server Key Exchange」消息

      • 选择了名为 x25519 的椭圆曲线,相当于椭圆曲线基点 G 也定好了,这些都会公开给客户端;
      • 生成随机数作为服务端椭圆曲线的私钥,保留到本地;
      • 根据基点 G 和私钥计算出服务端的椭圆曲线公钥, RSA 对公钥做签名。公开给客户端。
    • 「Server Hello Done」消息,打招呼完毕。

  • TLS 第三次握手

    • 客户端生成随机数作为椭圆曲线的私钥,生成椭圆曲线公钥,「Client Key Exchange」消息发给服务端。
    • 至此,双方都有对方的椭圆曲线公钥、自己的椭圆曲线私钥、椭圆曲线基点 G。双方都就计算出点(x,y),其中 x 坐标值双方都是一样的。
    • 会话密钥,就是用「客户端随机数 + 服务端随机数 + x(ECDHE 算法算出的共享密钥) 」
    • 算好会话密钥后,客户端会发一个「Change Cipher Spec」消息,告诉服务端后续改用对称算法加密通信。
    • 发送「Encrypted Handshake Message」消息,把之前发送的数据做一个摘要,再用对称密钥加密一下,让服务端做个验证,验证下本次生成的对称密钥是否可以正常使用。
  • TLS 第四次握手

    • 服务端也会有一个同样的操作,发「Change Cipher Spec」和「Encrypted Handshake Message」消息,如果双方都验证加密和解密没问题,那么握手正式完成。

    • 客户端不用等服务端的最后一次 TLS 握手,就可以提前发出加密的 HTTP 数据,节省了一个消息的往返时间

HTTPS 的应用数据是如何保证完整性的?😡

blog.csdn.net/zhanyiwp/ar…

  1. 消息被分割成多个较短的片段,然后分别对每个片段进行压缩。

  2. 加上消息认证码(MAC 值,这个是通过哈希算法生成的),这是为了保证完整性,并进行数据的认证。通过附加消息认证码的 MAC 值,可以识别出篡改。与此同时,为了防止重放攻击,在计算消息认证码时,还加上了片段的编码。

  3. 再加上消息认证码会一起通过对称密码进行加密。

  4. 再加上由数据类型、版本号、压缩后的长度组成的报头就是最终的报文数据。

SSL/TLS 1.2 需要 4 握手,需要 2 个 RTT 的时延,SSL/TLS 1.3 优化了过程,只需要 1 个 RTT 往返时延,也就是只需要 3 次握手。

HTTPS 如何优化

分析性能损耗

  • TLS 协议握手过程:2RTT延迟+性能损耗

    • 对于 ECDHE 密钥协商算法,握手过程中会客户端和服务端都需要临时生成椭圆曲线公私钥;
    • 客户端验证证书时,会访问 CA 获取 CRL 或者 OCSP,目的是验证服务器的证书是否有被吊销;
    • 双方计算 Pre-Master,也就是对称加密密钥;
  • 握手后的对称加密报文传输:主流的对称加密算法 AES、ChaCha20 性能不错,CPU 硬件级别优化

硬件优化

HTTPS 协议是计算密集型,而不是 I/O 密集型

选择可以支持 AES-NI 特性的 CPU,指令级别优化了 AES 算法

# 查看 CPU 是否支持 AES-NI 指令集
sort -u /proc/crypto | grep module | grep aes
module       : aesni_intel

软件优化

  • 软件升级:

    • 将 Linux 内核从 2.x 升级到 4.x;
    • 将 OpenSSL 从 1.0.1 升级到 1.1.1;

协议优化

  • 密钥交换算法优化

    • TLS 1.2 版本 4 次握手,也就是要花费 2 RTT,安全性也不高。

    • TLS 1.3 版本,第 3 次握手后,第 4 次握手前,发送加密的应用数据,花费 1 RTT,安全性高。

      • 椭圆曲线尽量选择 x25519 曲线,最快
  • 对称加密算法:

    • 对安全性不是特别高的要求,可以选用 AES_128_GCM,它比 AES_256_GCM 快一些
  • TLS 升级

    • 把 TLS 1.2 升级成 TLS 1.3,把 Hello 和公钥交换这两个消息合并成了一个消息,客户端在 Client Hello 消息里带上了支持的椭圆曲线,以及这些椭圆曲线对应的公钥。

    • TLS1.3 对于密钥交换算法,废除了不支持前向安全性的 RSA 和 DH 算法,只支持 ECDHE 算法。

    • 对于对称加密和签名算法,只支持目前最安全的几个密码套件,比如 openssl 中仅支持下面 5 种密码套件:

      • TLS_AES_256_GCM_SHA384
      • TLS_CHACHA20_POLY1305_SHA256
      • TLS_AES_128_GCM_SHA256
      • TLS_AES_128_CCM_8_SHA256
      • TLS_AES_128_CCM_SHA256

证书优化

  • 证书传输:选择椭圆曲线(ECDSA)证书,在相同安全强度下, ECC 密钥长度比 RSA 短的多。

  • 证书验证

    • CRL 称为证书吊销列表(Certificate Revocation List):

      • CA 维护,客户端在更新 CRL 之前还是会信任这个证书,实时性较差;
      • 随着吊销证书的增多,列表会越来越大,下载速度慢,验证延时很大
    • OCSP 在线证书状态协议(Online Certificate Status Protocol)

      • 向 CA 发送查询请求,让 CA 返回证书的有效状态。如果网络状态不好,或者 CA 服务器繁忙,也会导致客户端在校验证书这一环节的延时变大。
    • OCSP Stapling

      • 服务器向 CA 周期性地查询证书状态,获得一个带有时间戳和签名的响应结果并缓存它。
      • 签名的存在,服务器无法篡改,客户端就能得知证书是否已被吊销了,不需要再去查询。

会话复用

首次 TLS 握手协商的对称加密密钥缓存起来,待下次需要建立 HTTPS 连接时,直接「复用」这个密钥

  • Session ID

    • 客户端和服务器首次 TLS 握手连接后,双方会在内存缓存会话密钥,并用唯一的 Session ID 来标识

    • 缺点:

      • 随着客户端的增多,服务器的内存压力也会越大
      • 多台服务器通过负载均衡提供服务,客户端再次连接不一定会命中,还要完整的 TLS 握手过程;
  • Session Ticket

    • 服务器不再缓存每个客户端的会话密钥,而是把缓存的工作交给了客户端,类似于 HTTP 的 Cookie。
    • 首次建立连接时,服务器会加密「会话密钥」作为 Ticket 发给客户端,交给客户端缓存该 Ticket。
    • 对于集群服务器的话,确保每台服务器加密 「会话密钥」的密钥是一致的,这样客户端携带 Ticket 访问任意一台服务器时,都能恢复会话。

缺点

  • Session ID 和 Session Ticket 都不具备前向安全性

  • 应对重放攻击也很困难

    • 中间人截获了某个客户端的 Session ID 或 Session Ticket 以及 POST 报文,可以利用此截获的报文,不断向服务器发送该报文。
    • 应该对会话密钥设定一个合理的过期时间
    • Session ID 和 Session Ticket 方式都需要在 1 RTT 才能恢复会话。
  • Pre-shared Key

    • 重连 TLS1.3 只需要 0 RTT,原理和 Ticket 类似,在重连时,客户端会把 Ticket 和 HTTP 请求一同发送给服务端。
    • Pre-shared Key 也有重放攻击的危险