CN.0a1b.HTTPS

HTTPS

针对 HTTP 存在的部分缺点进行改进形成的扩展协议,HTTP+ 加密(SSL) + 认证 + 完整性保护=HTTPS(超文本传输安全协议)
HTTPS 通过 SSL(安全套接层)/TLS(安全层传输协议)加密 HTTP 的通信内容

TSL 是以 SSL 为原型开发的协议,有时会统一称该协议为 SSL/TLS

HTTP
TCP
IP
HTTP
HTTP
SSL
TCP
IP
HTTPS

HTTP 的安全问题

按TCP/IP 协议族的工作机制,通信内容在所有的通信线路上都有可能遭到窥视

HTTP 协议中的请求和响应不会对通信方进行确认,导致问题:

请求或响应在传输途中,遭攻击者拦截并篡改内容的攻击称为中间人攻击(MITM)
使用 HTTP 协议确定报文完整性常用的是 哈希算法生成散列值进行校验,以及用来确认文件的以 PGP创建的数字签名校验
HTTP 下用户需要亲自使用上述方法进行验证,同时无法意识到针对 PGP 和 MD5的篡改

HTTPS 安全保证

SSL/TLS 协议可以很好地解决上述风险:

具体的操作方式:

混合加密

HTTPS 采用共享密钥加密和公开密钥加密两者并用混合加密机制

摘要算法&数字签名

应用层发送数据时会附加用摘要算法(哈希函数)生成的报文摘要
通过比对报文摘要能够查知报文是否遭到篡改,从而保护报文的完整性

但是摘要算法不保证报文内容和哈希值没有被中间人整体替换,可以通过私钥加密报文摘要,公钥解密的方法确认消息来源可信,这种方法又被称为数字签名算法

身份证书

公开密钥的有效性通过由数字证书认证机构和其相关机关颁发的公开密钥证书来验证

数字证书认证机构(CA)为可信赖的第三方机构

  1. 首先 CA 会把持有者的公钥、用途、颁发者、有效时间等信息打包,然后对这些信息进行 Hash 计算,得到一个 Hash 值
  2. 然后 CA 会使用自己的私钥将该 Hash 值加密,生成 Certificate Signature,也就是数字签名
  3. 最后将 Certificate Signature 添加在文件上,形成数字证书,然后分配该公开密钥
  4. CA 使用自己的私钥对服务端申请的公开密钥做数字签名,将该公开密钥放入公钥证书后绑定在一起

多数浏览器内部事先植入常用CA的公开密钥

  1. 客户端使用 CA 的公开密钥验证服务端数字证书上的签名
  2. 验证成功后客户端从数字证书获取服务端公钥,加密报文后发送
  3. 服务端使用私钥解密报文获取报文

证书的验证过程中还存在一个证书信任链的问题,因为我们向 CA 申请的证书一般不是根证书签发的,而是由中间证书签发的
证书链的目的是为了确保根证书的绝对安全性,将根证书隔离地越严格越好,不然根证书如果失守了,那么整个信任链都会有问题

证书链.png (1478×452) (xiaolincoding.com)

安全性极高的认证机构可颁发客户端证书但仅用于特殊用途的业务,如网银系统
客户端证书只能用来证明客户端实际存在,而不能用来证明用户本人的真实有效性

EV SSL 证书可确认对方服务器背后运营的企业是否真实存在
每个人都可以用开源程序OpenSSL构建属于自己的认证机构,从而自己给自己颁发服务器证书,由自认证机构颁发的证书称为自签名证书

TLS 握手流程

基本流程:

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

TLS1.2

TLS1.2 的握手阶段涉及四次通信,使用不同的密钥交换算法的流程不同,现在常用的密钥交换算法有两种:RSA 算法ECDHE 算法

RSA

服务器和客户端用双方协商的加密算法对过程中交换的三个随机数 Client RandomServer Randompre-master key 进行加密,各自生成相同的会话秘钥(共享密钥) 用于本次通信的对称加密

RSA 算法握手具体流程:

  1. 第一次握手,客户端向服务器发起加密通信  Client Hello  请求
    - 客户端支持的 TLS 协议版本
    - 客户端生产的随机数 Client Random
    - 客户端支持的密码套件列表,如 RSA 加密算法
  2. 第二次握手,服务端响应请求,返回服务器数字证书(包含服务器公钥)
    • Sever Hello
      • 确认支持 TLS 协议的版本(不支持时关闭加密通信)
      • 服务器生产的随机数 Server Random
      • 确认的密码套件,如 RSA 加密算法
    • Server Hello Done
      • 告知客户端内容发送完毕
    • Server Certificate
      • 服务器的数字证书
  3. 客户端通过 CA 公钥验证数字证书,取出服务器公钥,生成一个随机数 pre-master,进而用双方协商的加密算法对过程中交换的三个随机数 Client RandomServer Randompre-master key 进行加密
  4. 第三次握手,客户端向服务器发送以服务器公钥加密的随机数
    • Cilent Key Exchange
      • 以服务器公钥加密的随机数 pre-master
    • Change Cipher Spec
      • 加密通信算法改变通知,表示随后的信息都将用会话秘钥加密通信
    • Encrypted Handshake Message(Finishd)
      • 客户端握手结束通知,表示客户端的握手阶段已经结束,同时将之前所有内容生成摘要,用会话密钥加密供服务端校验
  5. 服务器通过协商的加密算法计算出本次通信的会话秘钥
  6. 第四次握手,服务器发送响应报文确认 TLS 握手完成
    • Change Cipher Spec
      • 加密通信算法改变通知,表示随后的信息都将用会话秘钥加密通信
    • Encrypted Handshake Message
      • 服务器握手结束通知,表示服务器的握手阶段已经结束,同时将之前所有内容生成加密摘要供客户端校验

基于 RSA 算法的 HTTPS 存在前向安全问题如果服务端的私钥泄漏了,过去被第三方截获的所有 TLS 通讯密文都会被破解

ECDHE

DH

离散对数.png (692×227) (xiaolincoding.com)
通过离散对数,确认 a 与 p 值后,以 i 为私钥可以计算出公钥 b,目前的计算机能力无法做到由 b 反推 i
客户端与服务端交流确认相同的 a 与 p 值,各自生成私钥 icis,进而计算出各自公钥 bcbs,交换公钥后可以计算出相同的结果 K

K=bsic(mod p)=(ais)ic(mod p)=(aic)is(mod p)=bcis(mod p)

K 即为客户端与服务端之间的对称加密密钥,可以作为会话密钥使用

为实现前向安全每次通信需要随机生成私钥,但计算量大,性能不佳
ECDHE 算法通过 ECC 椭圆曲线特性,可以用更少的计算量计算出公钥,以及最终的会话密钥

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

ECDHE 算法握手具体流程:

  1. 第一次握手, 客户端向服务器发起加密通信 Client Hello 请求
    • 客户端支持的 TLS 协议版本
    • 客户端生产的随机数 Client Random
    • 客户端支持的密码套件列表
  2. 第二次握手,服务器生成随机数作为服务端椭圆曲线的私钥,并将服务端公钥发送给客户端
    • Sever Hello
      • 确认支持 TLS 协议的版本(不支持时关闭加密通信)
      • 服务器生产的随机数 Server Random
      • 确认的密码套件
    • Server Certificate
      • 服务器的数字证书
    • Server Key Exchange
      • 选择的椭圆曲线类型(同时确定了基点G)
      • 根据基点 G 和私钥计算出的服务端的椭圆曲线公钥(用 RSA 签名算法进行数字签名)
    • Server Hello Done
      • 告知客户端内容发送完毕
  3. 客户端通过 CA 公钥验证服务器身份,生成一个随机数作为客户端椭圆曲线的私钥,进而生成客户端的椭圆曲线公钥,同时通过协商的加密算法生成会话密钥
  4. 第三次握手,客户端向服务器发送客户端公钥
    • Cilent Key Exchange
      • 客户端椭圆曲线公钥
    • Change Cipher Spec
      • 加密通信算法改变通知,表示随后的信息都将用会话秘钥加密通信
    • Encrypted Handshake Message(Finishd)
      • 客户端握手结束通知,表示客户端的握手阶段已经结束,同时将之前所有内容生成摘要,用会话密钥加密供服务端校验
  5. 服务器通过协商的加密算法计算出本次通信的会话秘钥
  6. 第四次握手,服务器发送响应报文确认 TLS 握手完成
    • Change Cipher Spec
      • 加密通信算法改变通知,表示随后的信息都将用会话秘钥加密通信
    • Encrypted Handshake Message
      • 服务器握手结束通知,表示服务器的握手阶段已经结束,同时将之前所有内容生成加密摘要供客户端校验

TLS1.3

TLS 1.3 把 Hello 和公钥交换这两个消息合并成了一个消息,只需 1 RTT 就能完成 TLS 握手

tls1.2and1.3.png (1832×1290) (xiaolincoding.com)|600

具体做法:

  1. 客户端在第一次握手时的 Client Hello 消息里带上了支持的椭圆曲线以及这些椭圆曲线对应的公钥
  2. 服务端收到后,选定一个椭圆曲线等参数,然后返回消息时,带上服务端生成的公钥
  3. 二者生成会话密钥进行加密通信

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

TLS 优化

会话复用

Session ID
客户端和服务器首次 TLS 握手连接后,双方会在内存缓存会话密钥,并用唯一的 Session ID 来标识
当客户端再次连接时,hello 消息里会带上 Session ID,服务器收到后从内存查询,有则直接用该会话密钥恢复会话状态,跳过其余的过程,只用一个 RTT 就可以建立安全通信
同时为了安全性,内存中的会话密钥会定期失效

缺点:

Session Ticket
服务器不再缓存每个客户端的会话密钥,而是把缓存的工作交给客户端
客户端与服务器首次建立连接时,服务器会加密「会话密钥」作为 Ticket 发给客户端,交给客户端缓存该 Ticket
客户端再次连接服务器时,客户端会发送 Ticket,服务器解密后就可以获取上一次的会话密钥,然后验证有效期,如果没问题,就可以恢复会话了,开始加密通信

对于集群服务器的话,要确保每台服务器加密会话密钥的密钥是一致的,这样客户端携带 Ticket 访问任意一台服务器时,都能恢复会话

Session ID 和 Session Ticket 都不具备前向安全性,一旦加密会话密钥的密钥被破解或者服务器泄漏会话密钥,前面劫持的通信密文都会被破解

同时应对重放攻击也很困难

Pre-shared Key

重连时,客户端会把 Ticket 和 HTTP 请求一同发送给服务端

Pre-shared Key 也有重放攻击的危险

重放攻击

重放攻击|600
假设 Alice 想向 Bob 证明自己的身份。 Bob 要求 Alice 的密码作为身份证明,爱丽丝应尽全力提供(可能是在经过如哈希函数的转换之后)
与此同时,Eve 窃听了对话并保留了密码(或哈希)
交换结束后,Eve(冒充 Alice )连接到 Bob。当被要求提供身份证明时,Eve 发送从 Bob 接受的最后一个会话中读取的 Alice 的密码(或哈希),从而授予 Eve 访问权限
重放攻击的危险之处在于,如果中间人截获了某个客户端的 Session ID 或 Session Ticket 以及 POST 报文,而一般 POST 请求会改变数据库的数据,中间人就可以利用此截获的报文,不断向服务器发送该报文,这样就会导致数据库的数据被中间人改变了,而客户是不知情的
避免重放攻击的方式就是需要对会话密钥设定一个合理的过期时间

应用数据完整性

TLS 在实现上分为握手协议记录协议两层:

具体流程:

  1. 首先,消息被分割成多个较短的片段,然后分别对每个片段进行压缩
  2. 接下来,经过压缩的片段会被加上消息认证码(哈希值)以保证完整性并进行数据的认证,通过附加消息认证码的 MAC 值,可以识别出篡改,与此同时,为了防止重放攻击,在计算消息认证码时,还加上了片段的编码
  3. 再接下来,经过压缩的片段再加上消息认证码会一起通过对称密码进行加密
  4. 最后,上述经过加密的数据再加上由数据类型、版本号、压缩后的长度组成的报头就是最终的报文数据

HTTPS存在的问题