为什么要有 HTTPS

为什么要有 HTTPS?简单的回答是:“因为 HTTP 不安全”。HTTP 怎么不安全呢?

  • 通信的消息会被窃取,无法保证机密性(保密性):由于 HTTP 是 “明文” 传输,整个通信过程完全透明,其他人能够窃取到传输的明文信息。
  • 通信的消息会被篡改,无法保证完整性:使用 HTTP 通信,任何人都能够在通信的过程中截获并篡改请求报文、响应报文,但消息接收者无法识别报文是否被篡改。
  • 通信的消息会被伪造,无法确认消息发送者的真实身份(身份认证):使用 HTTP 通信,任何人都能够给一个接收者发送消息,但是消息接收者无法确认消息发送者的真实身份。也就是说,无法进行身份认证。
  • 无法保证不可否认性(不可抵赖):使用 HTTP 通信,消息接收者收到一个消息后,通信的一方可以否认(抵赖)消息不是他发送的。也就是说,消息接收者无法证明这一消息的确是由通信的一方发送的。

只有同时具备了机密性、完整性、身份认证、不可否认这四个特性,才能算得上是安全的通信。

HTTPS 使用 HTTP 进行通信,并使用 SSL/TLS 为 HTTP 增加了机密性、完整性、身份认证、不可否认这四大安全特性。

介绍 SSL/TLS

SSL 即安全套接层(Secure Sockets Layer)。

SSL 发展到 v3 时已经证明了它是一个非常好的安全通信协议,于是互联网工程组 IETF 在 1999 年把 SSL 改名为 TLS(传输层安全,Transport Layer Security),正式标准化,版本号从 1.0 重新算起,所以 TLS1.0 实际上就是 SSLv3.1。

至今,TLS 已经发展出了三个版本,分别是 2006 年的 1.1、2008 年的 1.2 和 2018 的 1.3,每个新版本都紧跟密码学的发展和互联网的现状,持续强化安全和性能。目前应用最广泛的 TLS 版本是 1.2,而之前的版本(TLS1.1 / 1.0、SSLv3 / v2)都已经被认为是不安全的。

TLS 综合使用了对称加密、非对称加密、身份认证等许多密码学前沿技术。非对称加密在这个场景中发挥的作用是 “密钥协商”,通信的双方协商得到会话密钥。会话密钥用于 HTTP 报文的加解密,以实现机密性。


TLS 由记录协议、握手协议、警报协议、变更密码规范协议、扩展协议等几个子协议组成:

  • 记录协议(Record Protocol)规定了 TLS 收发数据的基本单位是:记录(record)。它有点像是 TCP 里的 segment,所有其他的子协议都需要通过记录协议发出。多个记录数据可以在一个 TCP 包里一次性发出。
  • 握手协议(Handshake Protocol)是 TLS 里最复杂的子协议。通信的双方在 TLS 握手的过程中协商 TLS 的版本号、密码套件,交换随机数、数字证书和密钥参数,最终通信的双方协商得到会话密钥。
  • 警报协议(Alert Protocol)的职责是向对方发出警报信息。收到警报的一方可以选择继续连接,也可以立即终止连接。它有点像是 HTTP 里的状态码,比如 protocol_version 就是不支持旧版本,bad_certificate 就是证书有问题。
  • 变更密码规范协议(Change Cipher Spec Protocol)就是一个“通知”,告诉对方:后续传输的都是对称密钥加密的密文。也就是说,“Change Cipher Spec” 消息之前传输的都是明文,之后传输的都是对称密钥加密的密文。

TLS 的密钥套件

通信的双方在 TLS 握手的过程中会协商使用的密码套件(cipher suite,也被称为加密套件)。

TLS 的密码套件命名非常规范。固定的格式是:“密钥交换算法 + 签名算法 + 对称加密算法 + 分组模式 + 消息摘要算法”,例如 “ECDHE-RSA-AES256-GCM-SHA384” 密码套件的意思就是:

  • 密钥交换算法使用的是:ECDHE。通信的双方在 TLS 握手的过程中协商 TLS 的版本号、密码套件,交换随机数、数字证书和密钥参数,通信的双方使用 ECDHE 算法算法 "Pre Master Secret"。

  • 签名算法使用的是:RSA。TLS 握手的过程中,使用 RSA 签名算法进行数字签名。服务器给浏览器发送 "Server Key Exchange" 消息,服务器对密钥参数(消息中的 Public 参数)进行数字签名,然后把签名值一并发送给浏览器。浏览器收到 "Server Key Exchange" 消息后,使用数字证书中的公钥对密钥参数(消息中的 Public 参数)进行验签。

  • 对称加密算法使用的是:AES-256。TLS 握手后的通信使用 AES 对称加密算法进行加密,以实现机密性。对称密钥的长度 256 位

  • 分组模式使用的是:GCM。加密明文的长度不固定,而一次对称加密只能处理特定长度的一块数据,这就需要进行迭代,以便将一段很长的数据全部加密,而迭代的方法就是分组模式。

  • 消息摘要算法使用的是:SHA-384。TLS 握手的过程中,两次用到了该消息摘要算法。一次是:“PRF” 通过消息摘要算法,根据三个随机数(Client Random、Server Random 和 Pre Master Secret)计算主密钥 "Master Secret" 的值。另一次是:通信的双方给对方发送 "Finished" 消息。一方对之前发送的数据做摘要,再使用会话密钥对摘要进行对称加密,让对方进行验证(类似数字签名的验签)。TLS 握手后的通信使用该消息摘要算法进行消息认证,防止消息被篡改。

TLS1.2 握手的过程

使用 HTTPS 协议通信,通信的双方会先建立 TCP 连接,然后执行 TLS 握手,之后就可以在安全的通信环境里收发 HTTP 请求和响应了。

执行 TLS 握手的目的是:通信的双方安全的协商会话密钥。会话密钥用于 HTTP 报文的加解密,以实现机密性。


TLS1.2 握手可以划分为两种方式:使用 RSA 算法实现密钥交换 和 使用 ECDHE 算法实现密钥交换。

下面说的是使用 ECDHE 算法实现密钥交换的 TLS 握手过程。

TLS 握手过程的简要描述:通信的双方在 TLS 握手的过程中协商 TLS 的版本号、密码套件,交换随机数、数字证书和密钥参数,最终通信的双方协商得到会话密钥。"Hello" 消息交换随机数,"Key Exchange" 消息交换密钥参数。

  • 浏览器给服务器发送 "Client Hello" 消息,服务器给浏览器发送 "Server Hello" 消息。通信的双方协商 TLS 的版本号、密码套件,并交换随机数。
  • 交换数字证书:服务器为了向浏览器证明自己的身份,服务器给浏览器发送 "server Certificate" 消息,以发送数字证书链,其中包含了两个证书。一个是 CA 机构颁发的数字证书,另一个是 CA 机构的数字证书。
  • 服务器给浏览器发送 "Server Key Exchange" 消息,浏览器给服务器发送 "Client Key Exchange" 消息。通信的双方交换密钥参数(Client Params 和 Server Params),然后通信的双方使用 ECDHE 算法算出 "Pre Master Secret"。
  • 通信的双方根据自己已知的参数(Client Random、Server Random 和 Pre Master Secret)算出主密钥 "Master Secret",并使用主密钥拓展出更多的密钥(会话密钥),避免只用一个密钥带来的安全隐患。
  • 浏览器给服务器发送 "Change Cipher Spec" 消息,服务器也给浏览器发送 "Change Cipher Spec" 消息。告诉对方:后续传输的都是对称密钥加密的密文。
  • 浏览器给服务器发送 "Finished" 消息,服务器也给浏览器发送 "Finished" 消息。通信的双方把之前发送的数据做摘要,再使用会话密钥对摘要进行对称加密,让对方进行验证(类似数字签名的验签)。
  • 双方都验证成功,握手正式结束,之后就可以正常收发被加密的 HTTP 请求和响应了。

TLS 握手的过程如下图所示,其中每一个框都是一个记录,多个记录组合成一个 TCP 包发送。所以,最多经过两次消息往返(4 个消息,或者说 4 个 TCP 包)就可以完成 TLS 握手。

第一个消息往返

浏览器与服务器建立 TCP 连接之后,浏览器会首先给服务器发送 "Client Hello" 消息。"Client Hello" 消息携带几个参数:Version、Random、Cipher Suites。

  • Version:TLS 的版本号
  • Random:浏览器生成的随机数(Client Random)。随机数用于后续生成主密钥
  • Cipher Suites:浏览器支持的密码套件
Handshake Protocol: Client Hello
Version: TLS 1.2 (0x0303)
Random: 1cbf803321fd2623408dfe…
Cipher Suites (17 suites)
Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xc02f)
Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (0xc030)

服务器收到浏览器发送的 "Client Hello" 消息后,服务器给浏览器发送 "Server Hello" 消息。"Server Hello" 消息携带几个参数:Version、Random、Cipher Suite。

  • Version:TLS 的版本号
  • Random:服务器生成的随机数(Server Random)。随机数用于后续生成主密钥
  • Cipher Suite:服务器选择使用的密码套件(服务器从浏览器发送的 "Client Hello" 消息的 Cipher Suites 参数中选)
Handshake Protocol: Server Hello
Version: TLS 1.2 (0x0303)
Random: 0e6320f21bae50842e96…
Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (0xc030)

服务器为了向浏览器证明自己的身份,服务器给浏览器发送一个证书链,包含了两个证书。一个是 CA 机构颁发的数字证书,另一个是 CA 机构的数字证书。

通过引入数字证书,实现了服务器的身份认证功能,这样即便黑客伪造了服务器,但是由于数字证书是没有办法伪造的,所以黑客依然无法欺骗用户。


由于服务器选择了使用 ECDHE 密钥交换算法,因此服务器需要给浏览器发送【服务端的椭圆曲线的公钥】(Server Params)。为了防止公钥被第三方篡改、被黑客冒充,服务器会对公钥进行数字签名,然后把签名值一并发送给浏览器。浏览器收到后,使用数字证书中的公钥对密钥参数(消息中的 Public 参数)进行验签。

服务器给浏览器发送 "Server Key Exchange" 消息。"Server Key Exchange" 消息携带几个参数:Curve Type、Named Curve、Pubkey、Signature Algorithm、Signature。

  • Curve Type、Named Curve:使用的椭圆曲线的类型
  • Pubkey:根据【服务端的椭圆曲线的私钥】和 基点 G 计算出的【服务端的椭圆曲线的公钥】(Server Params),用于后续计算 “Pre Master Secret”
  • Signature Algorithm、Signature:使用的签名算法、签名值
Handshake Protocol: Server Key Exchange
EC Diffie-Hellman Server Params
Curve Type: named_curve (0x03)
Named Curve: x25519 (0x001d)
Pubkey: 3b39deaf00217894e...
Signature Algorithm: rsa_pkcs1_sha512 (0x0601)
Signature: 37141adac38ea4...

服务器给浏览器发送 "Server Key Exchange" 消息之后,服务器发送信息完毕。服务器给浏览器发送 "Server Hello Done" 消息,服务器向浏览器说明:服务器发送信息完毕了。

至此,第一个消息往返就结束了(2 个消息,或者说 2 个 TCP 包)。结果是:通信的双方通过明文传输共享了如下信息:浏览器生成的随机数(Client Random)、服务器生成的随机数(Server Random)、使用的椭圆曲线的类型、服务端的椭圆曲线的公钥(Server Params)。

验证数字证书

浏览器收到服务器发送的数字证书之后,浏览器需要验证数字证书是否合法、有效。

浏览器验证完数字证书合法、有效后,浏览器再用数字证书中的公钥验证【服务器给浏览器发送的 "Server Key Exchange" 消息】的签名,以确认服务器的身份。

浏览器确认了服务器的身份之后,就开始了第二个消息往返。

第二个消息往返

由于通信的双方协商的使用 ECDHE 密钥交换算法。因此浏览器需要给服务器发送【客户端的椭圆曲线的公钥】(Client Params)。浏览器给服务器发送 "Client Key Exchange" 消息。

Handshake Protocol: Client Key Exchange
EC Diffie-Hellman Client Params
Pubkey: 8c674d0e08dc27b5eaa…

至此,通信的双方都获取到了 ECDHE 密钥交换算法需要的两个参数(Client Params、Server Params),于是通信的双方就使用 ECDHE 算法算出一个随机数,这个随机数被叫做 "Pre Master Secret"。

ECDHE 算法可以保证:即使黑客截获了之前的参数,黑客也绝对算不出这个 “Pre Master Secret” 随机数,因为 "Pre Master Secret" 的计算还使用了椭圆曲线的私钥。

目前,通信的双方已知三个随机数:Client Random、Server Random 和 Pre Master Secret。通信的双方使用这三个随机数作为原始信息,通过 PRF 算出主密钥(Master Secret)。因为黑客拿不到 "Pre Master Secret",所以黑客也就无法得到主密钥。

主密钥 "Master Secret" 的计算:这里的 “PRF” 就是伪随机数函数,它基于密码套件里的最后一个参数(消息摘要算法),比如 SHA384。“PRF” 通过 SHA384 消息摘要算法再一次强化 "Master Secret" 的随机性。

master_secret = PRF(pre_master_secret, "master secret", ClientHello.random + ServerHello.random)

主密钥的长度为 48 字节,但是主密钥并不是最终用于通信的会话密钥,还会再用 PRF 扩展出更多的密钥,比如浏览器发送用的会话密钥(client_write_key)、服务器发送用的会话密钥(server_write_key)等,避免只用一个密钥带来的安全隐患。有了主密钥和派生的会话密钥,TLS 握手就快结束了。


浏览器给服务器发送 "Change Cipher Spec" 消息。浏览器告诉服务器:浏览器后续传输的都是对称密钥加密的密文。浏览器给服务器发送 "Finished" 消息。浏览器对之前发送的数据做摘要,再使用会话密钥对摘要进行对称加密,让服务器进行验证(类似数字签名的验签)。

服务器也进行和浏览器同样的操作。

  • 服务器给浏览器发送 "Change Cipher Spec" 消息。服务器告诉浏览器:服务器后续传输的都是对称密钥加密的密文。
  • 服务器给浏览器发送 "Finished" 消息。浏览器对之前发送的数据做摘要,再使用会话密钥对摘要进行对称加密,让浏览器进行验证。

双方都验证成功,握手正式结束,之后就可以正常收发被加密的 HTTP 请求和响应了。

使用 RSA 的 TLS 握手

TLS1.2 握手可以划分为两种方式:使用 RSA 算法实现钥交换 和 使用 ECDHE 算法实现密钥交换。

上面说了【使用 ECDHE 算法实现密钥交换的 TLS 握手过程】,下面说【使用 RSA 算法实现密钥交换的 TLS 握手过程】。

TLS 握手过程的简要描述:通信的双方在 TLS 握手的过程中协商 TLS 的版本号、密码套件,交换随机数、数字证书和密钥参数,最终通信的双方协商得到会话密钥。"Hello" 消息交换随机数,"Key Exchange" 消息交换 "Pre Master Secret"。

  • 浏览器给服务器发送 "Client Hello" 消息,服务器给浏览器发送 "Server Hello" 消息。通信的双方协商 TLS 的版本号、密码套件,并交换随机数。
  • 交换数字证书:服务器为了向浏览器证明自己的身份,服务器给浏览器发送 "server Certificate" 消息,以发送数字证书链,其中包含了两个证书。一个是 CA 机构颁发的数字证书,另一个是 CA 机构的数字证书。
  • 服务器给浏览器发送 "Server Hello Done" 消息,服务器向浏览器说明:服务器发送信息完毕了。
  • 浏览器验证数字证书合法、有效后,获取数字证书中【服务器的公钥】。浏览器生成随机数 "Pre Master Secret",使用【服务器的公钥】对生成的 "Pre Master Secret" 进行加密。然后,浏览器给服务器发送 "Client Key Exchange" 消息,把加密后的 "Pre Master Secret" 发送给服务器。
  • 服务器收到浏览器发送的 "Client Key Exchange" 消息后,使用【服务器的私钥】解密出随机数 "Pre Master Secret"。
  • 通信的双方根据自己已知的参数(Client Random、Server Random 和 Pre Master Secret)算出主密钥 "Master Secret",并使用主密钥拓展出更多的密钥(会话密钥),避免只用一个密钥带来的安全隐患。
  • 浏览器给服务器发送 "Change Cipher Spec" 消息,服务器也给浏览器发送 "Change Cipher Spec" 消息。告诉对方:后续传输的都是对称密钥加密的密文。
  • 浏览器给服务器发送 "Finished" 消息,服务器也给浏览器发送 "Finished" 消息。通信的双方把之前发送的数据做摘要,再使用会话密钥对摘要进行对称加密,让对方进行验证(类似数字签名的验签)。
  • 双方都验证成功,握手正式结束,之后就可以正常收发被加密的 HTTP 请求和响应了。

【使用 RSA 算法实现钥交换的 TLS 握手过程】的大体流程没有变,只是 "Pre Master Secret" 不再需要通信的双方根据密钥参数使用算法算出,而是由浏览器生成,浏览器再使用服务器的公钥对生成的 "Pre Master Secret" 进行加密。然后,浏览器给服务器发送 "Server Key Exchange" 消息,把加密后的 "Pre Master Secret" 发送给服务器。服务器收到浏览器发送的 "Server Key Exchange" 消息后,使用服务器的私钥解密出随机数 "Pre Master Secret"。

这样通信的双方也已知三个随机数:Client Random、Server Random 和 Pre Master Secret,就可以生成主密钥了。

参考资料

23 | HTTPS是什么?SSL/TLS又是什么? (geekbang.org)

26 | 信任始于握手:TLS1.2连接过程解析 (geekbang.org)

3.4 HTTPS ECDHE 握手解析 | 小林coding (xiaolincoding.com)

传输安全HTTPS的更多相关文章

  1. 如何为网站启用HTTPS加密传输协议

    前言 当今时代对上网的安全性要求比以前更高,chrome和firefox也都大力支持网站使用HTTPS,苹果也从2017年开始在iOS 10系统中强制app使用HTTPS来传输数据,微信小程序也是要求 ...

  2. HTTPS加密传输过程

    HTTPS加密传输过程 HTTPS全称Hyper Text Transfer Protocol over SecureSocket Layer,是以安全为目标的HTTP通道,在HTTP的基础上通过传输 ...

  3. HTTPS简介

    一.简单总结 1.HTTPS概念总结 HTTPS 就是对HTTP进行了TLS或SSL加密. 应用层的HTTP协议通过传输层的TCP协议来传输,HTTPS 在 HTTP和 TCP中间加了一层TLS/SS ...

  4. HTTPS和HTTP的概念和区别

    HTPPS和HTTP的概念 HTTPS(全称:Hypertext Transfer Protocol over Secure Socket Layer),是以安全为目标的HTTP通道,简单讲是HTTP ...

  5. HTTPS和HTTP的区别

    (转自:http://www.php100.com/html/it/biancheng/2015/0209/8582.html) 总的来说,http效率更高,https安全性更高. 首先谈谈什么是HT ...

  6. 【转】Tomcat启用HTTPS协议配置过程

    转载请注明出处: http://blog.csdn.net/gane_cheng/article/details/53001846 http://www.ganecheng.tech/blog/530 ...

  7. https简介/原理/部署【转】

    转自: http://han.guokai.blog.163.com/blog/static/136718271201211631456811/ http://www.barretlee.com/bl ...

  8. HTTPS和HTTP的区别(转)

    HTTPS和HTTP的区别 超文本传输协议HTTP协议被用于在Web浏览器和网站服务器之间传递信 息.HTTP协议以明文方式发送内容,不提供任何方式的数据加密,如果攻击者截取了Web浏览器和网站服务器 ...

  9. 听大神说:https和http有何区别?(转)

    在做雅虎的时候,发现用第三方工具截取不到客户端与服务端的通讯,以前重来没碰到过这种情况,仔细看了看,它的url请求时基于https的,gg了下发现原来https协议和http有着很大的区别.总的来说, ...

  10. HTTPS----安全超文本传输协议

    HTTPS协议详解HTTPS以保密为目标研发,简单讲是HTTP的安全版.其安全基础是SSL协议,因此加密的详细内容请看SSL.全称Hypertext Transfer Protocol over Se ...

随机推荐

  1. idea引入ojdbc包报错

    网上下载或者让同事传两个jar过来,ojdbc6-11.2.0.7.0.jar 以及jconn3.0.jar 放入同一个文件夹中: 在此文件夹中cmd如下:回车,进入cmd控制台. 输入如下两个命令: ...

  2. mobx基础

    React 和 MobX 是一对强力组合.React 通过提供机制把应用状态转换为可渲染组件树并对其进行渲染.而MobX提供机制来存储和更新应用状态供 React 使用. 对于应用开发中的常见问题,R ...

  3. 记一次前端ajax禁止使用异步async的操作

    环境: 前端layui  jquery 情况: 页面在iframe里面, 然后点击按钮,弹出输入框.点击确认,弹出框发送内容到后台, 传送数据到后台后,然后根据返回一个map给前端.前端解析数据,返回 ...

  4. 如何保证RabbitMQ的消息按照顺序执行???

    可以采用单线程的消费保证消息的顺序性.对消息进行编号,1,2,3,4--消费时按照编号的顺序去消费消息.这样就可以保证消息 按照一定顺序执行.

  5. dos命令初学

    DOS命令 打开DOS命令方式 开始+系统+命令提示符 WIN键盘+R 输入CMD 打开控制台(推荐使用) 在任意文件夹下面,按住shift键加鼠标右键点击,在此处打开命令行窗口 自愿管理器的地址栏前 ...

  6. 1903021126 申文骏 Java 第四周作业 Java分支语句学习

    项目 内容 课程班级博客链接 19级信计班(本) 作业要求链接 Java第四周作业 博客名称 1903021126  申文骏  Java 第四周作业 Java分支语句学习 要求 每道题要有题目,代码( ...

  7. impdp,depdp 常用参数

    转载于:https://www.cnblogs.com/halberd-lee/p/7807032.html 1 导数据注意事项 检查数据库版本(用于决定导出时生成为哪个版本的dmp头文件) sele ...

  8. Hadoop编程——Java编写MapReduce:WordCount案例

    一.MapReduce简介 MapReduce是一种面向大数据平台的分布式并行计算框架,它允许使用人员在不会分布式并行编程的情况下,将程序运行在分布式系统上.它提供的并行计算框架,能自动完成计算任务的 ...

  9. char和int的类型转换

    char类型是16位的,底层采用unicode编码保存.char类型是可以直接赋值给int类型的,因为是16位到32位低到高.举个例子比如int i='1';打印i的值是49.char类型跟int类型 ...

  10. mybatis-plus 3.4.3.1 设置数据库字段为NULL

    实体字段注解配置 @TableField(jdbcType = JdbcType.VARCHAR, updateStrategy = FieldStrategy.IGNORED) private St ...