Https之(一)TLS介绍及握手过程详解

文章目录

    • 简介
    • TLS
      • TLS第一次握手
      • 1.Client Hello
      • TLS第二次握手
        • 2.Server Hello
        • 3.Certificate
        • 4.Server Hello Done
      • TLS第三次握手
        • 5.Client Key Exchange
        • 6.Change Cipher Spec
        • 7.Encrypted Handshake Message
      • TLS第四次握手
        • 8.New Session Ticket
        • 9.Change Cipher Spec
        • 10.Encrypted Handshake Message
    • 总结

简介

我们知道http传输数据是明文传输,明文传输存在三个问题:

  1. 窃听风险:由于是明文传输,到达目标之前的所有链路都可以看到传输的内容。
  2. 篡改风险:如果传输过程中间数据被修改,接收方也无法得知。
  3. 冒充风险:由于知道传输的内容,中间人可以冒充接收方。

在计算机发展的早期只是使用http传输简单的数据,发展到现在绝大部分数据传输都是基于http协议,如果还使用明文传输显然不太安全,特别是涉及账号密码相关的内容,https就是在http的基础上添加了安全传输层,其中s代表SSL(Secure Sockets Layer)或者TLS(Transport Layer Security),SSL是早期的版本,由网景公司在1990年代早期开发。TLS是其后续版本,由互联网工程任务组(IETF)开发,SSL有SSL1.0、SSL2.0和SSL3.0,TLS有TLS1.0、TLS1.1、TLS1.2和TLS1.3,目前主流的版本是TLS1.2和TLS1.3。下面我们来介绍TLS是怎么实现安全传输的。我们以目前主流的TLS1.2作为介绍对象。

TLS

我们先看下TLS的流程:

在这里插入图片描述

根据上图我们可以把TLS分为以下几步:

1.服务端生成一对非对称加密的密钥对,把自己的公钥交给CA机构生成一个证书,什么是CA呢?因为非对称加密通过公钥加密数据,通过私钥解密数据,服务端拥有公钥私钥,但是客户端什么都不知道,所以需要将公钥传给客户端,但是直接发给客户端可能会被中间人拦截替换,TLS通过引入一个双方可以信任的第三方即CA来解决这个问题。

  • CA会将服务端的公钥、颁发者、有效时间等信息打成一个包,然后对这些信息进行 Hash 计算,得到一个 Hash 值(也称证书指纹)
  • 然后 CA 会使用自己的私钥将该 Hash 值加密,生成 Certificate Signature(证书签名)
  • 最后将 Certificate Signature 添加在文件证书上,形成数字证书。由于证书签名使用CA的私钥加密,解密自然只能用CA的公钥。我们的客户端(Android,Windows,iOS等)都会集成全球主流的CA的公钥信息到操作系统中。

2.当客户端向服务端请求数据的时候,服务端把这个证书发送给客户端,客户端拿到证书后可以得到服务端的公钥、颁发者、有效时间、证书签名和所属的CA等信息。

  • 首先客户端会使用同样的 Hash 算法获取该证书的 Hash 值 H1
  • 再从操作系统中寻找这个CA的公钥,通过公钥解密证书里的签名数据得到Hash值H2
  • 最后比较 H1 和 H2,如果值相同,则为可信赖的证书。

通过CA客户端可以验证服务端的身份,防止有人冒充。

3.客户端已经拿到了可以用来加密的公钥,正常来说现在已经可以进行加密通讯了,但是由于非对称加密较复杂,加密耗时较久,而且加密后内容明显变大,所以在频繁的通讯中使用是非常不划算的,所以这里并没有直接用公钥加密传输数据,而是引入了对称加密,在客户端随机生成一个对称加密密钥,并使用公钥加密后传给服务器,由于只有服务器有私钥,所以中间拦截也没用,服务器接收到数据后解密拿到对称加密密钥,后续的通讯就使用对称加密进行加密。(虽然对称加密的安全性不如非对称加密,但是由于每次连接都会生成一个随机的密钥,所以安全性上也是可以接受的。)

上面只是大致的流程,实际实现和上面说的还是有很大区别的,下面我们分析一次实际中TLS握手的完整过程,什么是TLS的握手呢?其实就是通讯双方通过上面的方法协商一个共同的密钥的过程,他的完整流程是这样的:

请添加图片描述

上图有多次通信过程,可以分成4次握手,下面我们通过抓包看一下实际的TLS的握手过程,首先看一下wireshark中完整的TLS握手记录:

请添加图片描述

上图中有多个握手过程,我把其中一个握手的完整过程标记出来了,下面我们来详细介绍每一步的作用。

TLS第一次握手

1.Client Hello

请添加图片描述

上图是client hello的所有内容,我们重点关注红框中的内容:

1.Version是客户端的TLS版本,我们看到是1.2

2.Random是客户端生成的一个随机数,用于生成加密密钥,前面我们说过客户端拿到服务端公钥后会生成一个随机数当作后续通讯加密的密钥,并把这个密钥用公钥加密后发送给服务端,其实这个密钥不止一个随机数,而是三个随机数拼成的,其一就是这里的随机数,其二是服务端server hello时也会传过来的一个服务端生成的随机数,最后才是之前说的随机数,通过三个随机数生成最终的密钥是为了保证随机性和安全性。

3.Cipher Suites是客户端支持的加密套件,我们上面说的对称加密和非对称加密并没有固定的加密算法,这个有很多选择,我们看下客户端支持的加密套件有哪些:
请添加图片描述

这个密码套件看起来真让人头晕,好一大串,但是其实它是有固定格式和规范的。基本的形式是「密钥交换算法 + 签名算法 + 对称加密算法 + 摘要算法」, 一般 WITH 单词前面有两个单词,第一个单词是约定密钥交换的算法,第二个单词是约定证书的验证算法。比如我们目前分析的这个TLS_RSA_WITH_AES_128_GCM_SHA256密码套件的意思就是:

  • 由于 WITH 单词只有一个 RSA,则说明握手时密钥交换算法和签名算法都是使用 RSA;
  • 握手后的通信使用 AES 对称算法,密钥长度 128 位,分组模式是 GCM;
  • 摘要算法 SHA256 用于消息认证和产生随机数;

4.support_versions是客户端支持的所有TLS版本,前面的version是客户端想要使用的版本,但是服务端不一定支持,所以需要把支持所有版本给到服务端,如果服务端不支持version的版本,就在support_versions选一个。

5.session_ticket是用于复用之前的TLS连接用的,这个后面会介绍。

TLS第二次握手

2.Server Hello

请添加图片描述

1.Version是服务端选择的TLS版本

2.Random是服务端生成的一个随机数,用于生成加密密钥

3.Cipher Suites是服务端选择的加密套件

3.Certificate

请添加图片描述

这一步是将服务器的证书发送给客户端,客户端拿到证书后会去进行验证,并拿到公钥。

上图中服务器给了两个证书,这是为什么呢?这就要说到CA的证书链机制了,服务端的证书并不一定是CA根证书签发的,而可能是CA的二级证书签发的,CA下面会有二级三级乃至多级代理,如果是二级代理签发的证书,就要先用根证书验证二级代理的证书,二级代理的证书没问题,再用二级代理的证书验证服务器的证书。

所以上图的第一个证书是服务器证书,第二个证书是二级代理的证书,先找到二级代理所属的CA,去验证二级证书,验证无误后再用二级证书去验证服务器证书。

请添加图片描述

4.Server Hello Done

请添加图片描述

服务端已经完成hello,为什么需要这一步呢?

Server Hello之后,服务器通常会发送一系列消息,包括:

  • Certificate (包含服务器的证书链)
  • Server Key Exchange (如果证书不包含足够的信息进行密钥交换,例如使用DHE/ECDHE算法时)
  • Certificate Request (可选,如果服务器要求客户端认证)
  • ... (其他可能的扩展消息)

这些消息的数量和类型是可变的,取决于协商的加密套件、服务器配置和是否要求客户端认证。

Server Hello Done 的唯一作用就是清晰、明确地告诉客户端:“我已经发送完所有我这边在握手这一阶段需要发送的信息了,没有更多这类消息了。”

TLS第三次握手

5.Client Key Exchange

请添加图片描述

将用公钥加密的pre-master传递给服务端,服务端拿到直接用私钥解密就可以拿到pre-master,加上client的random和server的radom就可以得到回话密钥。

客户端随机数 + 服务端随机数 + 预主密钥 = 主密钥 ==> 会话密钥

6.Change Cipher Spec

请添加图片描述

告诉服务端开始用会话密钥进行加密通讯了

7.Encrypted Handshake Message

请添加图片描述
把客户端之前所有发送的数据做个摘要,再用会话密钥(master secret)加密一下,让服务器做个验证,验证加密通信是否可用和之前握手信息是否有被中途篡改过。

TLS第四次握手

8.New Session Ticket

请添加图片描述
将session_ticket发送给客户端保存,session_ticket是用于复用之前的TLS连接用的,由于TLS的握手比较繁琐,自然就比较耗时,所以当握手完成后服务器端将本次的会话数据进行加密(会话标识符、证书、密码套件和主密钥等),加密后生成一个ticket票据(只有服务器可以解密),并将票据通过NewSessionTicket子消息发送给客户端,客户端保存这个ticket。当连接断开后重新连接的时候就可以在client hello中将这个ticket发送给服务端,服务器端解密校验无误后拿到主密钥,将主密钥和client hello中的random以及服务端生成的即将在server hello中传输的random三个数据生成一个新的密钥,然后server hello的时候客户端也用同样的三个数据生成这个密钥,这样就协商了一个相同的密钥,后续就用这个密钥进行加密通讯,如此恢复上一次会话就可以省掉之后的很多步骤。

9.Change Cipher Spec

和客户端发送的Change Cipher Spec操作相同,告诉客户端我准备好使用会话密钥了

10.Encrypted Handshake Message

把服务端之前所有发送的数据做个摘要,再用会话密钥(master secret)加密一下,让客户端做个验证,验证加密通信是否可用和之前握手信息是否有被中途篡改过。

总结

到这里TLS的流程就介绍完了,我们再看看开头说的http的三个问题是怎么解决的:

  1. 窃听风险:通过会话密钥加密数据。
  2. 篡改风险:通过CA对证书进行签名,对TLS握手过程进行摘要计算。
  3. 冒充风险:向CA验证证书。

虽然解决了这三个问题,但是现在的TLS还是有缺陷的,那就是不支持前向保密,因为客户端传递pre-master(用于生成对称加密密钥的条件之一)给服务端时使用的是公钥加密的,服务端收到后,会用私钥解密得到随机数。所以一旦服务端的私钥泄漏了,过去被第三方截获的所有 TLS 通讯密文都会被破解。

为了解决这一问题,于是就有了 DH 密钥协商算法TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,和我们上面介绍的TLS_RSA_WITH_AES_128_GCM_SHA256区别就是使用了ECDHE的密钥协商算法,后面我们介绍一下这个算法。

下一篇:Https之(二)TLS的DH密钥协商算法

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/94047.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/94047.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【WEB 】从零实现一个交互轮播图(附源码)

文章目录 一、轮播图整体功能规划二、HTML结构深度解析三、CSS样式实现细节1. 定位系统详解2. 显示/隐藏机制3. 按钮交互效果实现4. 纯CSS箭头实现5. 指示器:当前位置可视化 四、JavaScript逻辑深入解析1. 核心变量与DOM获取2. 图片切换函数(核心逻辑&am…

机器学习--PCA降维

一核心部分 1解决的问题:应对高维数据带来的计算量大、冗余信息多、易出现过拟合等问题,在减少数据维度的同时尽可能保留原始数据的关键信息。2核心思想&#xff1a…

leetcode 1277. 统计全为 1 的正方形子矩阵 中等

给你一个 m * n 的矩阵,矩阵中的元素不是 0 就是 1,请你统计并返回其中完全由 1 组成的 正方形 子矩阵的个数。示例 1:输入:matrix [[0,1,1,1],[1,1,1,1],[0,1,1,1] ] 输出:15 解释: 边长为 1 的正方形有…

知识蒸馏 - 各类概率分布

知识蒸馏 - 各类概率分布 flyfish一、离散概率分布 离散分布描述的是取值为离散值(如0,1,2,…)的随机变量的概率规律,通常用概率质量函数(PMF) 表示某一取值的概率。 1. 伯努利分布(Bernoulli Distribution…

软件测试-Selenium学习笔记

""" 目标: driver.find_element() 需求: 1. 使用driver.find_element()方法 2. 输入用户名:admin 3. 输入密码:123456 """ # 导包 from selenium import webdriver from time import …

知微传感3D相机上位机DkamViewer使用:给相机升级固件

写在前面 本人从事机器视觉细分的3D相机行业。编写此系列文章主要目的有: 1、便利他人应用相机,本系列文章包含公司所出售相机的SDK的使用例程及详细注释;2、促进行业发展及交流。 知微传感Dkam系列3D相机可以应用于定位分拣、焊接焊缝提取、…

CMake进阶: CMake Modules---简化CMake配置的利器

目录 1.简介 2.为什么需要 CMake Modules? 3.内置模块:开箱即用的工具 3.1.依赖查找模块(FindXXX.cmake) 3.2.功能检测模块(CheckXXX.cmake) 3.3.通用工具模块(如 FetchContent.cmake、CT…

【Docker】Ubuntu上安装Docker(网络版)

【Docker】Ubuntu上安装Docker注意:一、环境准备1. 系统要求2. 卸载旧版本二、安装步骤1.配置仓库源2.安装 Docker引擎3.验证安装情况三、解决报错1、检查网络连接2、检查Docker服务状态3、换源4.重载生效、重启服务、查看是否配置成功5.验证解决情况四、权限与配置…

Socket 编程 TCP

TCP 网络程序 和刚才 UDP 类似. 实现一个简单的英译汉的功能。TCP是面向字节流的可靠传输,如同前文的管道流,只要是流,它的操作就是文件的写出与读入。TCP socket API 详解下面介绍程序中用到的 socket API,这些函数都在 sys/socket.h 中。so…

使用AWS S3 + Lambda + MediaConvert 实现上传视频文件并自动转码

前言 最近团队在做短视频平台的技术调研,其中有一个环节便是音视频开发,即对用户上传的视频进行自适应转码。自适应的原理其实就是预先将视频转换为几个常用的分辨率,app端根据用户手机分辨率拉取相应分辨率的视频。 目前尝试了两种方案&…

QT之QWaitCondition降低cpu占用率,从忙等待到高效同步

在多线程编程中,线程间的同步是一个核心问题。在处理线程等待时,经常会写出高CPU占用率的代码,其中最典型的就是使用忙等待(busy waiting)。本文将详细介绍如何使用Qt框架中的QWaitCondition类来优雅地解决这一问题&am…

pcl求平面点云的边界凸包点

基本流程1,读入点云,并去除无效点2,拟合平面3,去除离平面距离较远的点4,对点云进行平面投影5,进行convex_hull运算初学者,暂时不知道能用来干嘛。练手还是非常不错的!#define _CRT_S…

Windows系统上使用GIT

首先破除一下畏惧心理:在Windows上使用git和在linux系统中的使用方法是一样的,只是安装方式没那么便捷,毕竟linux中安装git只需要一行命令 GIT下载地址 如果你的电脑的CPU是64位的,就点击: Git-2.50.1-64-bit.exe 如果…

《设计模式之禅》笔记摘录 - 17.模板方法模式

模板方法模式的定义模板方法模式(Template Method Pattern)是如此简单,以致让你感觉你已经能够掌握其精髓了。其定义如下:Define the skeleton of an algorithm in an operation, deferring some steps to subclasses.Template Method lets subclasses r…

SpreadJS 协同服务器 MongoDB 数据库适配支持

为了支持 SpreadJS 协同编辑场景,协同服务器需要持久化存储文档、操作、快照及里程碑数据。本文介绍了 MongoDB 数据库适配器的实现方法,包括集合初始化、适配器接口实现以及里程碑存储支持。 一、MongoDB 集合初始化 协同编辑服务需要以下集合&#x…

Ubuntu 主机名:精通配置与管理

主机名(hostname)是Linux系统中用于标识网络上特定设备的名称,它在网络通信、服务配置(如 Kubernetes 集群、数据库)以及日志记录中扮演着至关重要的角色。对于初学者来说,配置主机名似乎很简单&#xff0c…

C/C++ 协程:Stackful 手动控制的工程必然性

🚀 C/C 协程:Stackful 手动控制的工程必然性 引用: C/C 如何正确的切换协同程序?(基于协程的并行架构) #mermaid-svg-SXgplRf3WRYc8A7l {font-family:"trebuchet ms",verdana,arial,sans-serif;…

新手向:使用STM32通过RS485通信接口控制步进电机

新手向:使用STM32通过RS485通信接口控制步进电机 准备工作 本文使用的STM32芯片是STM32F407ZGTx,使用的电机是57步进电机,驱动器是用的是时代超群的RS485总线一体化步进电机驱动器(42 型:ZD-M42P-485)。使…

设计模式笔记_行为型_命令模式

1.命令模式介绍命令模式(Command Pattern)是一种行为设计模式,它将请求或操作封装为对象,使得可以用不同的请求对客户端进行参数化。命令模式的核心思想是将方法调用、请求或操作封装到一个独立的命令对象中,从而使得客…

详解MySQL中的多表查询:多表查询分类讲解、七种JOIN操作的实现

精选专栏链接 🔗 MySQL技术笔记专栏Redis技术笔记专栏大模型搭建专栏Python学习笔记专栏深度学习算法专栏 欢迎订阅,点赞+关注,每日精进1%,与百万开发者共攀技术珠峰 更多内容持续更新中!希望能给大家带来…