https与TLS/SSL 握手协议、record protocol简介

950 阅读8分钟

https即 HTTP Secure,HTTP的通信接口部分用SSL和TLS协议代替,并非是一种新的协议。

TLS协议是在SSL3.0的基础上开发的协议,以下统一用TLS协议来说明

http的问题

  • 通信使用明文,内容被窃听后存在安全问题
  • 不验证通信方的身份,可能遭到伪装
  • 无法验证报文的完整性,内容可能遭到篡改

http问题解决思路

明文不行,考虑先加密再传输呢?比如我传输过程中使用一种加密算法,在浏览器端自己加密和解密,服务端也提供对应的策略来加密和解密。前端代码基本属于完全暴露在所有人的面前,这种自己实现加密和解密的机制都会被别人知晓(秘钥都会被看到),毫无安全性可言,另外如果每个人都要这么搞一套,那就是重复造轮子,时间成本巨大,而且还不一定能做到很安全。

当然还包括性能、兼容性等等问题。

通信加密秘钥的安全性问题

秘钥肯定不能硬编码写到代码中,一种解决方式是在每次通信的过程中先生成秘钥,然后的信息再用这个秘钥进行加密通信,但是初次传输过程中,仍然会出现明文传输秘钥的问题,一旦被窃听,后续所有的加密都都白费

初次秘钥传输的问题

密码学中的非对称加密可以解决这种场景,非对称加密拥有两个秘钥:公钥和私钥。公钥可以解开私钥加密的内容,私钥可以解开公钥加密的内容,那么只要私钥不泄密,通过公钥加密的内容就算被截取,现有的技术手段,是很难通过截取的内容和公钥得到原有的内容

公钥能否信任

如果获取的公钥是窃听人的公钥,而不是真正服务提供方的公钥,那么后续的通信加密都是使用的窃听人的公钥,窃听人也自然使用自己的私钥可以进行解密。因此获取的公钥必须是能够信任的。
解决方式是把公钥放到数字证书中,这个证书由受信任的第三方机构进行颁发,并通过三方的私钥进行加密。客户端发起请求首先会向服务端请求三方的证书,客户端通过三方的公钥进行解密后,就安全拿到了服务端的公钥。

第三方的公钥本身则是由浏览器和操作系统自己去维护

证书被替换的风险

窃听人也可以自己去申请个证书,放上自己的公钥,这样客户端同样也可以通过三方的公钥解密,但是解密出来的却是窃听人的公钥。 解决方式是使用数字签名,证书上涵盖如何根据证书来生成数字签名的方法,与通过第三方机构的公钥解析到数字签名想比较,验证数字签名是否一样,一样则表明证书确是要访问的服务的。

比如证书上会写所代表的网站,校验的时候加上访问的网站,就可以得到对应的信息

https的通信过程

https是建立在TLS协议之上的,它的通信过程也是以TLS为基础。首先进行"握手",通过之后再进行通信

TLS握手协议概述

  1. 客户端发送 ClientHello 信息,包含

    • 一个随机数
    • 客户端所支持的协议版本
    • 客户端支持的对称加密算法
    • key_share(表明使用Diffie-Hellman) 或者是 pre_shared_key 或者这两者都有
  2. 服务端收到 ClientHello 之后,返回一个 ServerHello 信息,包含:

    • 协议的版本,比如TLS1.3
    • 一个随机数
    • 使用的加密算法
    • 如果决定使用 (EC)DHE key,那么会包含 "key_share" ;如果使用 PSK key,就会包含 "pre_shared_key"
  3. 服务端发送证书

    如果客户端也需要验证,会再发送一个要证书的请求给客户端

  4. 服务端发送 Server Hello Done 给客户端,表示Server Hello结束

    如果客户端收到了证书请求,会先发送客户端证书

  5. 客户端对服务器的证书进行校验,没通过则发送警告给使用者,确认是否继续,通过则返回 Pre master secret(这也是客户端产生的一个随机数),这个 Pre master secret 本身会使用证书中的公钥进行加密

  6. 客户端发送 Change Cipher Spec 报文,表示后续通信都会采用双方商定的加密方法和秘钥发送。

  7. 客户端会根据之前传递的随机数(2个)以及 Pre master secret 这三个随机数生成一个master_ key,然后从master_key中提取会话用的秘钥,用它加密一段内容,涵盖在这里客户端发送Finished报文中,表示客户端握手阶段结束同时也用来校验加密通道

  8. 服务器发送 Change Cipher Spec ,表示服务端也切换到位

  9. 服务端拿到公钥加密后的 Pre master secret 后,通过私钥解密,使用与客户端相同的方法,以及步骤7中的3个随机数,生成会话用的秘钥,使用这个加密秘钥发送一个Finished报文给客户端,验证加密通道,同时服务端握手结束

客户端和服务端都能对Finished信息正常解密且消息被验证,说明通道建立,后续通过上面产生的会话秘钥对数据进行加密传输

非对称加密与对称加密的混合使用

握手过程中,有一个随机数是使用非对称秘钥加密后传输的,传输成功之后,二者生成的最后一个会话秘钥用来通话,这是因为非对称秘钥加密和解密处理速度相对对称秘钥要慢,因此仅在握手阶段使用非对称秘钥传递,通信的时候使用握手阶段生成的会话秘钥进行加密

3个随机数

在握手的阶段首先是客户端随机生成了一个随机数,这是明文传输的,接着服务端返回了一个随机数,也是明文传输的,最后客户端使用了一个pre_master_key通过非对称加密的方式加密传输的,为什么用到了3个随机数再经过计算得到一个master_key,然后才提取会话key?

首先说一下 pre_master_key,在握手的过程中,会先约定好到底使用按个 Cipher Suit,比如约定使用RSA或者是(EC)DH suites 【(elliptic curve) Diffie-Hellman】,RSA会发送一个随机的48字节的 pre_master_key给服务端,但是 (EC)DH却不是,它产生的可能比48字节要长,也有可能要短,而且分布并不均衡。虽然通过RSA或者是(EC)DH是保证了pre_master_key本身的保密性,但是根据情况的不同,产生的秘钥格长度(格式)不一致,而多数情况下,保持一样长度的秘钥会有很好的结果,比如一样的长度允许将秘钥交换端与加密端区分开来(打个比方,不能根据长度猜到到底是用的那个非对称算法),某种程度上来说也就具备更好的随机性。因而最好处理下pre_master_key保证最终输出的key的一致性

另外从安全性考虑,pre_master_key一旦使用后需要删掉

而对于产生pre_master_key的算法对于rsa来说每次是随机的,但是对于dh,包括ecdh算法(不考虑匿名dh和瞬时dh),就只有hello消息中的两个随机数因子了。但是ssl协议本身并不信任每个主机都能产生完全随机的数字,如果随机数不随机,被猜出来就不合适了,因此选用3个随机数来达到更好的随机效果

随机带来的好处一个是当前的通信不容易被才出来,另外每次都会不一样,就是说就算当前的被才出来了,历史上的也无法解出正确的密文(也叫前向保护)。
最终通过PRF算法计算出一个固定长度为48字节的master_key,从中再提取出对应的会话key,提取规则如下:

 client_write_MAC_key[SecurityParameters.mac_key_length]
      server_write_MAC_key[SecurityParameters.mac_key_length]
      client_write_key[SecurityParameters.enc_key_length]  //会话key
      server_write_key[SecurityParameters.enc_key_length] //会话key
      client_write_IV[SecurityParameters.fixed_iv_length]
      server_write_IV[SecurityParameters.fixed_iv_length]

TLS的数据发送 - Record Protocol

record protocol负责数据的发送,它会把数据分割成可处理的几块(每块2的14方字节或者更少),然后进行压缩,添加MAC(用于校验数据的完整性),加密,然后扔给底层的协议去处理;接收方则是进行数据的解密,校验,解压缩和重新聚合,再发送给上层的协议

HTTPS能够被信任的前提

  • 浏览器正确的实现了HTTPS且操作系统中安装了正确且受信任的证书颁发机构(想想盗版的操作系统==)
  • 证书颁发机构仅信任合法的网站
  • 被访问的网站提供了有效的证书,即这个证书是由操作系统信任的证书机构签发的
  • 证书正确的验证了被访问的网站
  • 协议的加密层能够有效的提供认证和高强度的加密

引用

rfc1.2中关于record protocol部分
rfc1.2中关于master_key计算与会话key提取
Diffie-Hellman运作
3个随机数的意义-来自csdn dog250
pre_master_key讨论
master_key,session_key,pre_master_key的解释
数字签名简介
也许这样理解https更容易
讨论http加密数据和使用https详情戳这里
SSL/TLS原理详解
HTTPS被信任
图解HTTP