跳至主要內容

HTTP - HTTPS


概述

HTTP 是超文本传输协议,信息是明文传输,存在安全风险的问题。HTTPS 则解决 HTTP 不安全的缺陷,在 TCP 和 HTTP 网络层之间加入了 SSL/TLS 安全协议,使得报文能够加密传输。

HTTP 连接建立相对简单, TCP 三次握手之后便可进行 HTTP 的报文传输。而 HTTPS 在 TCP 三次握手之后,还需进行 SSL/TLS 的握手过程,才可进入加密报文传输。

两者的默认端口不一样,HTTP 默认端口号是 80,HTTPS 默认端口号是 443。

HTTPS 协议需要向 CA(证书权威机构)申请数字证书,来保证服务器的身份是可信的。

HTTP 由于是明文传输,所以安全上存在以下三个风险:

  • 窃听风险,通信使用明文(不加密),内容可能会被窃听
  • 篡改风险,无法证明报文的完整性,所以有可能已遭篡改
  • 冒充风险,不验证通信方的身份,因此有可能遭遇伪装

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

  • 信息加密:混合加密的方式实现信息的机密性,解决了窃听的风险。
  • 校验机制:摘要算法的方式来实现完整性,它能够为数据生成独一无二的「指纹」,指纹用于校验数据的完整性,解决了篡改的风险。
  • 身份证书:将服务器公钥放入到数字证书中,解决了冒充的风险。

混合加密

HTTPS 采用的是对称加密和非对称加密结合的「混合加密」方式:

在通信建立前采用非对称加密的方式交换会话秘钥(这个会话密钥就是对称密钥),后续就不再使用非对称加密。
在通信过程中全部使用 会话秘钥 来加密明文数据。

采用混合加密的原因:

  • 对称加密只使用一个密钥,运算速度快,密钥必须保密,无法做到安全的密钥交换。
  • 非对称加密使用两个密钥:公钥和私钥,公钥可以任意分发而私钥保密,解决了密钥交换问题但速度慢。

摘要算法 + 数字签名

为了保证传输的内容不被篡改,需要对内容hash出一个「指纹」,然后同内容一起传输给对方。

对方收到后,先是对内容也hash出一个「指纹」,然后跟发送方发送的「指纹」做一个比较,如果「指纹」相同,说明内容没有被篡改,否则就可以判断出内容被篡改了。

通过哈希算法可以确保内容不会被篡改,但是并不能保证「内容 + 哈希值」不会同时被替换,因此就有了数字签名。

这里一般会用非对称加密算法来解决,共有两个密钥:

  • 公钥,可以公开给所有人;
  • 私钥,必须由本人管理,不可泄露。

这两个密钥可以双向加解密的,比如可以用公钥加密内容,然后用私钥解密,也可以用私钥加密内容,公钥解密内容。流程的不同,意味着目的也不相同:

  • 公钥加密,私钥解密。这个目的是为了保证内容传输的安全,因为被公钥加密的内容,其他人是无法解密的,只有持有私钥的人,才能解密出实际的内容;但是这种方式效率低,一般还是用对称密钥加密内容
  • 私钥加密,公钥解密。这个目的是为了保证消息不会被冒充,因为私钥是不可泄露的,如果公钥能正常解密出私钥加密的内容,就能证明这个消息是来源于持有私钥身份的人发送的。

所以非对称加密的用途主要在于通过「私钥加密,公钥解密」的方式,来确认消息的身份,常说的数字签名算法,就是用的是这种方式,不过私钥加密内容不是内容本身,而是对内容的哈希值加密。

私钥是由服务端保管,然后服务端会向客户端颁发对应的公钥。如果客户端收到的信息,能被公钥解密,就说明该消息是由服务器发送的。

数字证书

以上流程如下:

  1. 通过哈希算法来保证消息的完整性;
  2. 再通过数字签名来保证消息的指纹不被篡改(用服务器私钥加密hash值,客户端用公钥解密,保证消息是由私钥方发送的);

虽然服务器持有私钥,客户端能通过服务器的公钥解密来确认这个hash消息是不是来源于服务器。但如果有黑客同时伪造公私钥,并将公钥发送给客户端,之后的会话密钥协商也用这个公钥来协商,那之后的消息发送黑客都能解密。因此需要保证公钥是来自于服务器的

权威的机构是 CA (数字证书认证机构),将服务器公钥放在数字证书(由数字证书认证机构颁发)中,只要证书是可信的,公钥就是可信的。

数字证书的工作流程:

通过数字证书的方式保证服务器公钥的身份,解决冒充的风险。

数字证书的验证过程

如下图图所示,为数字证书签发和验证流程:

CA 签发证书的过程:

  1. 首先 CA 会把持有者(一般是服务器)的公钥、用途、颁发者、有效时间等信息打成一个包,然后对这些信息进行 Hash 计算,得到一个 Hash 值;
  2. 然后 CA 会使用自己的私钥将该 Hash 值加密,生成 Certificate Signature,也就是 CA 对证书做了签名;
    最后将 Certificate Signature 添加在文件证书上,形成数字证书;

客户端校验服务端的数字证书的过程,如上图右边部分:

  1. 首先客户端会使用同样的 Hash 算法把持有者(一般是服务器)的公钥、用途、颁发者、有效时间等信息进行计算得到 Hash 值 H1;
  2. 通常浏览器和操作系统中集成了 CA 的公钥信息,浏览器收到证书后可以使用 CA 的公钥解密 Certificate Signature 内容,得到一个 Hash 值 H2 ;
  3. 最后比较 H1 和 H2,如果值相同,则为可信赖的证书,否则则认为证书不可信。

但事实上,证书的验证过程中还存在一个证书信任链的问题,因为向 CA 申请的证书一般不是根证书签发的,而是由中间证书签发的,比如百度的证书,从下图你可以看到,证书的层级有三级:

对于这种三级层级关系的证书的验证过程如下:

  1. 客户端收到 baidu.com 的证书后,发现这个证书的签发者不是根证书,就无法根据本地已有的根证书中的公钥去验证 baidu.com 证书是否可信。于是,客户端根据 baidu.com 证书中的签发者,找到该证书的颁发机构是 “GlobalSign Organization Validation CA - SHA256 - G2”,然后向 CA 请求该中间证书。
  2. 请求到证书后发现 “GlobalSign Organization Validation CA - SHA256 - G2” 证书是由 “GlobalSign Root CA” 签发的,由于 “GlobalSign Root CA” 没有再上级签发机构,说明它是根证书,也就是自签证书。应用软件会检查此证书有否已预载于根证书清单上,如果有,则可以利用根证书中的公钥去验证 “GlobalSign Organization Validation CA - SHA256 - G2” 证书,如果发现验证通过,就认为该中间证书是可信的。
  3. “GlobalSign Organization Validation CA - SHA256 - G2” 证书被信任后,可以使用 “GlobalSign Organization Validation CA - SHA256 - G2” 证书中的公钥去验证 baidu.com 证书的可信性,如果验证通过,就可以信任 baidu.com 证书。

总括来说,由于用户信任 GlobalSign,所以由 GlobalSign 所担保的 baidu.com 可以被信任,另外由于用户信任操作系统或浏览器的软件商,所以由软件商预载了根证书的 GlobalSign 都可被信任。

操作系统里一般都会内置一些根证书,这样的一层层地验证就构成了一条信任链路,整个证书信任链验证流程如下图所示:

小结

HTTPS是如何保证安全性的:

  1. 无法保证内容是安全的,因此通过对称加密算法加密传输内容
  2. 无法保证整个传输内容不会被篡改,因此hash内容,来保证内容的完整性
  3. 无法保证 内容+hash值 不会被同时替换,因此使用数字签名算法,使用服务端私钥加密hash值,保证hash来自私钥方
  4. 无法保证公钥私钥的分发来自服务器,因此引入数字证书,引入CA确保可信

TLS握手

SSL/TLS 协议基本流程:

  • 客户端向服务器索要并验证服务器的公钥。
  • 双方协商生产「会话秘钥」。
  • 双方采用「会话秘钥」进行加密通信。

前两步也就是 SSL/TLS 的建立过程,也就是 TLS 握手阶段。TLS 的握手阶段涉及四次通信,使用不同的密钥交换算法,TLS 握手流程也会不一样的,现在常用的密钥交换算法有两种:RSA 算法 (opens new window)和 ECDHE 算法 (opens new window)。

RSA算法

基于 RSA 算法的握手过程如下图:

TLS 协议建立的详细流程:

  1. ClientHello:首先,由客户端向服务器发起加密通信请求,也就是 ClientHello 请求。在这一步,客户端主要向服务器发送以下信息:
    • 客户端支持的 TLS 协议版本,如 TLS 1.2 版本。
    • 客户端生产的随机数(Client Random),后面用于生成「会话秘钥」条件之一。
    • 客户端支持的密码套件列表,如 RSA 加密算法。
  2. SeverHello:服务器收到客户端请求后,向客户端发出响应,也就是 SeverHello。服务器回应的内容有如下内容:
    • 确认 TLS 协议版本,如果浏览器不支持,则关闭加密通信。
    • 服务器生产的随机数(Server Random),也是后面用于生产「会话秘钥」条件之一。
    • 确认的密码套件列表,如 RSA 加密算法。
    • 服务器的数字证书。
  3. 客户端回应:客户端收到服务器的回应之后,首先通过浏览器或者操作系统中的 CA 公钥,确认服务器的数字证书的真实性。如果证书没有问题,客户端会从数字证书中取出服务器的公钥,然后使用它加密报文,向服务器发送如下信息:
    • 一个随机数(pre-master key)。该随机数会被服务器公钥加密。
      • 上面的随机数pre-master key是整个握手阶段的第三个随机数,会发给服务端,所以这个随机数客户端和服务端都是一样的。
      • 客户端有了这三个随机数(Client Random、Server Random、pre-master key),接着就用双方协商的加密算法,各自生成本次通信的「会话秘钥」。
    • 加密通信算法改变通知,表示随后的信息都将用「会话秘钥」加密通信。
    • 客户端握手结束通知,表示客户端的握手阶段已经结束。这一项同时把之前所有内容的发生的数据做个摘要,用来供服务端校验。
  4. 服务器的最后回应:服务器收到客户端的第三个随机数(pre-master key)之后,也就有了三个随机数,通过协商的加密算法,计算出本次通信的「会话秘钥」。然后,向客户端发送最后的信息:
    • 加密通信算法改变通知,表示随后的信息都将用「会话秘钥」加密通信。
    • 服务器握手结束通知,表示服务器的握手阶段已经结束。这一项同时把之前所有内容的发生的数据做个摘要,用来供客户端校验。

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

RSA算法的不足

使用 RSA 密钥协商算法的最大问题是不支持前向安全性。

因为客户端传递随机数(用于生成对称加密密钥的条件之一)给服务端时使用的是公钥加密的,服务端收到后,会用私钥解密得到随机数。所以一旦服务端的私钥泄漏了,过去被第三方截获的所有 TLS 通讯密文都会被破解。

前向安全和后向安全:
前向安全Forward Security:前向安全能保证了当前密钥被攻击者获取后,历史的密钥仍然是安全的,也就是说,历史的通讯密文都是安全的。
后向安全Backward Security:后向安全性是指能保证当前密钥被攻击者获取后,未来的密钥仍然是安全的,也就是说,以后的通讯密文都是安全的

ECDHE 算法

ECDHE 密钥协商算法是由 DH 算法演进来的。

DH算法

DH算法解决了密钥在双方不直接传递密钥的情况下完成密钥交换

算法步骤如下:

  1. Alice计算A
    • 选择1个素数p,比如509,底数g 比如5,选择一个随机数a = 123;
    • 然后计算 A = g^a (mod p)= 5^a (mod 509) = 215
    • Alice现在有[p=509,g=5,a=123,A=215], 把p,g,A发送给Bob,随机数a私有
  2. Bob计算B和密钥s
    • 收到 p = 509,g = 5 后,选择一个随机数b = 456
    • 计算 B = g^b (mod p) = 5^456 (mod 509) = 181
    • 计算密钥 S = A^b (mod p)= 215^456 (mod 509) = 121
    • Bob现在有[p=509,g=5,b=456,B=181,s=121,A=125],把B=181发送给Alice,随机数b私有
  3. Alice计算密钥s
    • Alice现在有[p,g,a,A,B]
    • Alice计算 S = B^a (mod p) = 181^123 (mod 509)=121

最终双方协商出的密钥S是121。注意到这个密钥s并没有在网络上传输。而通过网络传输的p,g,A和B是无法推算出s的,因为根据离散对数的原理,从真数(A 和 B)反向计算对数 a 和 b 是非常困难的,并且实际算法选择的素数是非常大的。

DHE 算法

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

  • static DH 算法(废弃)
  • DHE 算法

static DH 算法里有一方的私钥是静态的,也就说每次密钥协商的时候有一方的私钥都是一样的,一般是服务器方固定,即 随机数a 不变,客户端的私钥则是随机生成的。

假设Alice是服务器端,Bob是客户端,那么DH 交换密钥时就只有客户端的公钥(即B)在变化,而服务端公钥(即A)是不变的,那么随着时间延长,黑客就会截获海量的密钥协商过程的数据,因为密钥协商的过程有些数据是公开的,黑客就可以依据这些数据暴力破解出服务器的私钥(即a),然后就可以计算出会话密钥了,于是之前截获的加密数据会被破解,所以 static DH 算法不具备前向安全性。

DHE 算法,E 全称是 ephemeral(临时性的)。即让双方的私钥(即a、b)在每次密钥交换通信时,都进行随机生成

ECDHE 算法

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

ECDHE 密钥交换算法的过程:

  1. 双方事先确定好使用哪种椭圆曲线,和曲线上的基点 G,这两个参数都是公开的;
  2. 双方各自随机生成一个随机数作为私钥d,并与基点 G相乘得到公钥Q(Q = dG),此时Alice的公私钥为 Q1 和 d1,Bob的公私钥为 Q2 和 d2;
  3. 双方交换各自的公钥,最后Alice计算点(x1,y1) = d1Q2,Bob计算点(x2,y2) = d2Q1,由于椭圆曲线上是可以满足乘法交换和结合律,所以 d1Q2 = d1d2G = d2d1G = d2Q1 ,因此双方的 x 坐标是一样的,所以它是共享密钥,也就是会话密钥。

这个过程中,双方的私钥d都是随机、临时生成的,都是不公开的,即使根据公开的信息(椭圆曲线、公钥、基点 G)也是很难计算出椭圆曲线上的离散对数(私钥)

ECDHE 握手过程

基于ECDHE算法的握手流程图如下:

  1. 第一次握手
    • ClientHello:首先,由客户端向服务器发起加密通信请求,也就是 ClientHello 请求。在这一步,客户端主要向服务器发送以下信息:
      • 客户端支持的 TLS 协议版本(Version),如 TLS 1.2 版本。
      • 客户端生产的随机数(Client Random),后面用于生成「会话秘钥」条件之一。
      • 客户端支持的密码套件列表。
  2. 第二次握手
    • SeverHello:服务器收到客户端请求后,向客户端发出响应,也就是 SeverHello。服务器回应的内容有如下内容:
      • 确认 TLS 协议版本(Version),如果浏览器不支持,则关闭加密通信。
      • 服务器生产的随机数(Server Random),也是后面用于生产「会话秘钥」条件之一。
      • 确认的密码套件列表,如 TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384。
    • Certificate:服务器为了证明身份,会给客户端发送数字证书
      • 包括CA机构为服务器颁发的公钥、CA机构签名等信息
    • Server Key Exchange:这步是ECDHE算法与RSA算法的不同之处,服务器会在发送证书后,再发送 Server Key Exchange 消息给客户端,包括:
      • 椭圆曲线公钥 Server Params,用来实现密钥交换(密钥协商)
      • 再加上自己的私钥签名认证(签名算法为RSA)
    • Server Hello Done :通知客户端所有消息已经发送完毕
  3. 第三次握手
    • 客户端收到服务器的 Certificate 消息后,使用操作系统内置的CA机构的公钥对证书解密,如果解密成功,得到 数据原文 及 摘要值 H1,然后客户端使用与CA机构相同的摘要算法(散列算法,SHA或MD5)对数据原文进行计算得到 摘要值 H2,比较 H1 与 H2,若完全相同则说明证书合法且未被其他人篡改,从而拿到服务器的RSA公钥。随后,客户端将自身的椭圆曲线公钥(Pubkey)使用服务器RSA公钥加密后,通过 Client Key Exchange 消息发给服务器
    • Change Cipher Spec:客户端 首先根据 服务器的椭圆曲线公钥Server Params 及自身的椭圆曲线私钥计算出第三个随机数 Pre-Master,然后再使用 Client Random、Server Random、Pre-Master 这三个随机数计算出 主密钥 Master Secret,并使用 Change Cipher Spec 消息将主密钥使用服务器的RSA私钥加密后发给服务器,通知服务器开始使用对称加密的方式进行通信。
      • Sever Params ^ 客户端椭圆曲线私钥 % P = pre-master
      • client random + server random + pre-master = master secret
    • Encrypted Handshake Message:
      • 客户端发送 Encrypted Handshake Message 消息,使用主密钥Master Secret 将之前的握手消息加密后发给服务器,一来验证新生成的对称密钥是否正确,二来让服务器验证之前的握手数据是否被篡改过
  4. 第四次握手:
    • Change Cipher Spec:服务器收到客户端的 Client Key Exchange 消息后,使用私钥解密得到客户端的椭圆曲线公钥 Client Params,至此服务器也可以计算出pre-master
      • Client Params ^ 服务器椭圆曲线私钥 % P = pre-master
      • client random + server random + pre-master = master secret
        Encrypted Handshake Message:使用生成的主密钥 Master Secret 对之前的握手数据进行对称加密,然后通过 Encrypted Handshake Message 消息发送给客户端进行验证。

参考链接

来源:https://www.xiaolincoding.com/ ,Seven进行了部分补充完善

seven97官方微信公众号
seven97官方微信公众号