【学习笔记】TLS/SSL握手
前言:本篇将介绍TLS握手的实际握手过程,TLS握手创建了Client和Server之间“被保护的通道”,2个单向通道用来保护批量数据的传输(通过Confidentiality、Integrity和Authentication),一个通道是从Client到Server,另一个是从Server到Client。本篇将介绍最基础的握手 - 即握手采用的是RSA密钥交换,并通过追条记录(Record)的形式来阐述该过程。
在整个握手的过程中,Client和Server会交换并计算特定的值。上图两侧的框是双方所拥有的信息。开始时,Server已经拥有了证书、公钥和私钥,
1、Handshake:Client Hello
第一条Record是Client Hello,里面包含5个部分
- Version
- 包含了Client所支持的TLS/SSL的最高版本
- Random Number - 32 bytes / 256 bits
- 前4个字节编码时间戳(防止两个拥有相同随机数的不同的Client Hello相互发送信息)
- Session ID - 8 bytes / 32 bits
- 00000...本篇中Client Hello的初始会话ID都是0
- Cipher Suites
- Client会发送它所支持的密码套件的列表,Server会从中挑选
- Extensions
- 如果有扩展的话会包含在握手中,本篇不包含扩展
2、Handshake:Server Hello
收到Client Hello后,Server会发出Server Hello,和Client Hello一样,包含5部分
- Version
- 包含了Server所支持的TLS/SSL的最高版本
- Random Number - 32 bytes / 256 bits
- 前4个字节编码时间戳
- Session ID - 8 bytes / 32 bits
- Server生成的用于识别后续会话密钥的值
- Cipher Suites
- Server(从Client发送的列表中)挑选的密码套件
- Extensions
- 如果有扩展的话会包含在握手中,本篇不包含扩展
在Client Hello和Server Hello之后,Client和Server都获得了额外的信息
- 两者都知道了互相支持的TLS版本。如果Client发送说它支持TLS 1.3,Server返回说它支持TLS 1.2,这就表明两者互相支持的最高的版本是TLS 1.2,两者将用TLS 1.2协议进行握手
- 两者都知道了互相的随机数(Client Random、Server Random)
- 两者也知道未来会用来参考本次会话的ID
- 互相同意的用来保护这次TLS会话的密码套件
3、Handshake:Certificate
这条记录包含了Server证书和完整的证书链,Client会收到证书和公钥。Client收到证书后会问自己2个问题:证书是否合法?(用CA公钥进行的签名可以验证其合法性,在此处Client拥有了其所需要的东西来验证该签名);Server是否是该证书的真正拥有者?(验证Server拥有与证书匹配的私钥,会由Key Exchange Record所验证)
4、Handshake:Server Hello Done
这是一条空的Record,表明Server此时没有更多信息进行发送;然而,握手的其他变体可能会要求Server发送更多信息。
5、Handshake:Client Key Exchange
Client Key Exchange有2个主要目的
- 创建相互的密钥材料(例如,SEED Value种子值,Client和Server两者都用来生成会话密钥)
- 证明Server确实是该证书的拥有者
2个目的都将由特殊的值所达成,即 Pre Master Secret,预主密钥。上图中用红色虚线框描述,表明该值是加密发送的
- Pre Master Secret 的生成
- Client生成 Pre-Master-Secret (包含48个字节)
- 2 bytes - TLS/SSL Version
- 46 bytes - Random(随机生成的)
- 之后,Pre-Master-Secret 会被Server的公钥进行加密(Client已经有了,因为前面的Record中Server已经发送了)
- Pre-Master-Secret 被加密后进行在线传输,唯一能提取该加密信息的,是拥有与之相匹配的私钥的一方,即有对应私钥的Server
- 现在,两者就都拥有了 Pre-Master-Secret
- Client生成 Pre-Master-Secret (包含48个字节)
- Pre Master Secret 的生效(在本例中,该值被用作种子值,来生成TLS会话密钥)
- 双方都有了匹配的SEED Value
- 种子值被用来生成会话密钥
- 预主密钥被用来生成主密钥(Master Secret)[ 将其他值与PreMasterSecret相结合,这些值是“master secret”文字字符串(包含在RFC里了)、Client Random和Server Random,这4个值会相互结合来生成Master Secret ]
- 主密钥被用来生成会话密钥 [ 将其他值与Master Secret相结合,这些值是“Key expansion”文字字符串、Client Random和Server Random,这4个值会相互结合来生成会话密钥 ]
- 至少生成4个会话密钥(2套不同的密钥):
- 保护Client发送信息的Client Encryption Key和Client HMAC Key
- 保护Server发送信息的Server Encryption Key和Server HMAC Key
- 至少生成4个会话密钥(2套不同的密钥):
- 特定加密协议需要 I.V. 即 Initializational Vector,初始化向量,这是(PRF)计算必要的I.V.的步骤
- 计算涉及PRF - Pseudo Random Function,伪随机数函数
- 生成任意长度的摘要的哈希算法
- 双方都有了匹配的SEED Value
到此,Client和Server双方都有了完全相同的会话密钥;但是,Client或Server并不知道另一方拥有相同的密钥。
因而,余下的握手将给双方证明:另一方拥有正确的会话密钥。
6、Change Cipher Spec(不是Handshake Record)
该记录表明Client已做好安全通话的一切准备(意味着它可以计算出会话密钥了)。我们可以阅读该记录,Client在说,它做好准备去更改由Client和Server所指定的密码。
7、Handshake:Finished
- 向Server证明:Client有正确的会话密钥
- 这会由特定的值(Encrypted Verification)来完成,过程如下
- Client计算出之前所有握手记录(5个)的哈希,这5个记录会一起被哈希,生成Handshake Hash
- 然后,Handshake Hash会与其他值(“client finish”字符串和Master Secret)相结合来生成验证数据(Verification Data)
- 最终,验证数据会被Client Session Keys加密,生成加密验证
- Server用自己的Client会话密钥副本进行验证
- 验证Client和Server“看见”相同的握手记录
-
- 理论上,Server也看见了之前5个握手记录(即Handshake Hash),“client finished”字符串,同时Server也有Mater Secret,这表明Server能合并得到相同的Verification Data;之后,Server收到加密验证后,用Client Session Key副本去进行解密,如果得到的结果和Server自己合并得到的验证数据相同,这就向Server表明,Client拥有相同的会话密钥。如果有人在Client发送出Client Hello后,Server接受到之前,进行篡改,两边的Verification Data会不匹配
8、Change Cipher Spec(不是Handshake Record)
该记录表明Server已做好安全通话的一切准备(意味着它可以计算出会话密钥了)
9、Handshake:Finished
- 向Client证明:Server有正确的会话密钥
- 类似的过程
- Client计算出之前所有握手记录(6个)的哈希,得到Handshake Hash
- Handshake Hash会与其他值(“server finish”字符串和Master Secret)相结合来生成验证数据(Verification Data)
- 验证数据会被Server Session Keys加密,生成加密验证
- Client用自己的Server会话密钥副本进行验证
-
在此刻的握手中,Client和Server都计算出相同的会话密钥,并且相互向对方证明自己有正确的会话密钥。这意味着两者可以开始分享批量数据了,并用协商好的会话密钥保护该数据。
以上就是TLS握手(我们阐述的是basic handshake)的全部过程
需要知道的是,TLS握手发生在我们每次访问HTTPS网站的时候,或者每次我们链接SSL VPN(Virtual Private Network)的时候
参考文献
1、网站:https://www.practicalnetworking.net/:practical TLS
相关文章:

【学习笔记】TLS/SSL握手
前言:本篇将介绍TLS握手的实际握手过程,TLS握手创建了Client和Server之间“被保护的通道”,2个单向通道用来保护批量数据的传输(通过Confidentiality、Integrity和Authentication),一个通道是从Client到Ser…...
ESP32-TFT_eSPI.h文件的使用心得(包含画图相关函数)
目录 前言 环境:arduino 芯片:ESP32 一、Arduino中的使用 #include <TFT_eSPI.h> TFT_eSPI tft TFT_eSPI();tft.init();//初始化tft.setRotation(0); //屏幕旋转方向tft.fillScreen(TFT_BLACK);//底色tft.setTextSize(2); …...

vite分目录打包以及去掉默认的.gz 文件
1.vite打包情况介绍: 1.1vite在不进行任何配置的情况下,会将除开public的所有引用到资源打包编译添加哈希值至assets文件夹中(非引用文件以及行内样式图片未被打包编译资源会被treeSharp直接忽略不打包), 1.2w…...

Tensorflow 2.0 cnn训练cifar10 准确率只有0.1 [已解决]
cifar10 准确率只有0.1 问题描述踩坑解决办法 问题描述 如果你看的是北京大学曹健老师的tensorflow2.0,你在class5的部分可能会遇见这个问题 import matplotlib.pyplot as plt import tensorflow as tf from tensorflow.keras.layers import Dense, Dropout,MaxPooling2D,Fla…...

828华为云征文 | 在华为云上通过Docker容器部署Elasticsearch并进行性能评测
目录 前言 1. 华为云X实例介绍及优势 1.1 柔性算力 1.2 vCPU和内存的灵活配比 1.3 成本效益与性能 2. 安装并运行 Docker 2.1 修改仓库配置文件 2.2 安装 Docker 2.3 启动 Docker 3. 使用Docker部署Elasticsearch 3.1 拉取Elasticsearch镜像 3.2 启动Elasticsearch…...
生态位模型降重创新专题系列【2025
本内容旨在丰富最大熵模型的分析内容,并针对目前文章存在的问题:(1)分析内容单一,重复度高和查重率高,(2)建模流程过于简单,结果可信度评估方法过于单一等;推…...

LeetCode234. 回文链表(2024秋季每日一题 26)
给你一个单链表的头节点 head ,请你判断该链表是否为回文链表。如果是,返回 true ;否则,返回 false 。 示例 1: 输入:head [1,2,2,1] 输出:true 示例 2: 输入:hea…...
项目(石头剪刀布游戏双循环)
while (true) { #region 猜拳游戏主题逻辑 // 定义猜拳次数 int count 3; //定义用户赢得次数 int winCount 0;// 初始值为零表示用户一次没饿赢 int sysCou…...

Linux 进程3
进程地址空间 CPU读取数据都需要地址,在计算机中所有东西都是一种数据,包括我们的进程。 这是一个进程空间示意图,操作系统通过task_struct结构体链表来管理每一个进程,结构体里面有一个指针指向操作系统为进程开辟的一段空间&am…...

R语言机器学习遥感数据处理与模型空间预测技术及实际项目案例分析
随机森林作为一种集成学习方法,在处理复杂数据分析任务中特别是遥感数据分析中表现出色。通过构建大量的决策树并引入随机性,随机森林在降低模型方差和过拟合风险方面具有显著优势。在训练过程中,使用Bootstrap抽样生成不同的训练集ÿ…...
shell linux cut 切割字符串
shell linux 切割字符串 在Shell脚本中,可以使用内置的cut命令来切割字符串。cut命令主要有三个选项 -c、-f和-d,分别表示按字符、按字段和指定分隔符来切割字符串。 按字符切割: echo "Hello World" | cut -c 1-5 # 输出&#…...
golang学习笔记31——golang 怎么实现枚举
推荐学习文档 golang应用级os框架,欢迎stargolang应用级os框架使用案例,欢迎star案例:基于golang开发的一款超有个性的旅游计划app经历golang实战大纲golang优秀开发常用开源库汇总想学习更多golang知识,这里有免费的golang学习笔…...
fastadmin本地安装插件提示”请从官网渠道下载插件压缩包(code:2)(code:1)“
这个问题主要是在fastadmin中为了保证安全性,不让你进行本地的一个安装(离线安装) 解决办法就是去把相应的代码注释掉,把相应的权限开启。 具体步骤 1.在后台的application\config.php文件下; 将这个unknownsources的…...

STM32基础学习笔记-Timer定时器面试基础题5
第五章、TIMER 常见问题 1、基本概念:什么是定时器 ?作用 ?分类 ? 2、时基单元 ?组成 ?计数模式 ?溢出条件 ? 溢出时间计算 ? 3、systick原理 ?代码讲解 &…...

CSS06-元素显示模式、单行文字垂直居中
一、什么是元素显示模式 1-1、块级元素 1-2、行内元素 1-3、行内块元素 1-4、小结 二、元素显示模式转换 三、单行文字垂直居中 CSS 没有给我们提供文字垂直居中的代码,这里我们可以使用一个小技巧来实现。 解决方案: 让文字的行高等于盒子的高度,就可…...

【车联网安全】车端网络攻击及检测的框架/模型
参考标准: 《汽车数据安全管理若干规定(试行)》ISO/SAE 21434《道路车辆 网络安全工程》威胁分析和风险评估(TARA)ISO/DIS 24089R155法规的国标转换:《汽车整车信息安全技术要求》(UN R155&…...

58.【C语言】内存函数(memcpy函数)
目录 1.memcpy *简单使用 翻译: *模拟实现 注意事项: *例题 1.memcpy *简单使用 memcpy:memory copy cplusplus的介绍 点我跳转 翻译: 函数 memcpy void * memcpy ( void * destination, const void * source, size_t num ); 复制内存块 直接从source指向的位置复制num…...
rust一些通用编程的概念
rust一些通用编程的概念 官网文档数据类型 - Rust 程序设计语言 中文版 (rustwiki.org) 变量,数据类型,条件判断,循环 变量 rust中变量的可变性是值得注意的 例如: fn main(){let number 1;number 2;println!("the number is {}&quo…...

SpringBoot基础知识
谈一谈你对SpringBoot的理解,它有哪些特性(优点)? SpringBoot用来快速开发Spring应用的一个脚手架,其目的是用来简化新Spring应用的初始搭建以及开发过程。 优点: 简化配置:提供了很多内置的…...
ubuntu配置libtorch CPU版本
配置环境:Ubuntu 20.04Date:2024 / 08 1、下载最新版本的libtorch wget https://download.pytorch.org/libtorch/nightly/cpu/libtorch-shared-with-deps-latest.zip unzip libtorch-shared-with-deps-latest.zip2、创建一个C工程文件夹,目…...
谷歌浏览器插件
项目中有时候会用到插件 sync-cookie-extension1.0.0:开发环境同步测试 cookie 至 localhost,便于本地请求服务携带 cookie 参考地址:https://juejin.cn/post/7139354571712757767 里面有源码下载下来,加在到扩展即可使用FeHelp…...

(十)学生端搭建
本次旨在将之前的已完成的部分功能进行拼装到学生端,同时完善学生端的构建。本次工作主要包括: 1.学生端整体界面布局 2.模拟考场与部分个人画像流程的串联 3.整体学生端逻辑 一、学生端 在主界面可以选择自己的用户角色 选择学生则进入学生登录界面…...
前端倒计时误差!
提示:记录工作中遇到的需求及解决办法 文章目录 前言一、误差从何而来?二、五大解决方案1. 动态校准法(基础版)2. Web Worker 计时3. 服务器时间同步4. Performance API 高精度计时5. 页面可见性API优化三、生产环境最佳实践四、终极解决方案架构前言 前几天听说公司某个项…...
【位运算】消失的两个数字(hard)
消失的两个数字(hard) 题⽬描述:解法(位运算):Java 算法代码:更简便代码 题⽬链接:⾯试题 17.19. 消失的两个数字 题⽬描述: 给定⼀个数组,包含从 1 到 N 所有…...

376. Wiggle Subsequence
376. Wiggle Subsequence 代码 class Solution { public:int wiggleMaxLength(vector<int>& nums) {int n nums.size();int res 1;int prediff 0;int curdiff 0;for(int i 0;i < n-1;i){curdiff nums[i1] - nums[i];if( (prediff > 0 && curdif…...
JavaScript 数据类型详解
JavaScript 数据类型详解 JavaScript 数据类型分为 原始类型(Primitive) 和 对象类型(Object) 两大类,共 8 种(ES11): 一、原始类型(7种) 1. undefined 定…...

代码规范和架构【立芯理论一】(2025.06.08)
1、代码规范的目标 代码简洁精炼、美观,可持续性好高效率高复用,可移植性好高内聚,低耦合没有冗余规范性,代码有规可循,可以看出自己当时的思考过程特殊排版,特殊语法,特殊指令,必须…...
提升移动端网页调试效率:WebDebugX 与常见工具组合实践
在日常移动端开发中,网页调试始终是一个高频但又极具挑战的环节。尤其在面对 iOS 与 Android 的混合技术栈、各种设备差异化行为时,开发者迫切需要一套高效、可靠且跨平台的调试方案。过去,我们或多或少使用过 Chrome DevTools、Remote Debug…...
用鸿蒙HarmonyOS5实现中国象棋小游戏的过程
下面是一个基于鸿蒙OS (HarmonyOS) 的中国象棋小游戏的实现代码。这个实现使用Java语言和鸿蒙的Ability框架。 1. 项目结构 /src/main/java/com/example/chinesechess/├── MainAbilitySlice.java // 主界面逻辑├── ChessView.java // 游戏视图和逻辑├──…...

CSS 工具对比:UnoCSS vs Tailwind CSS,谁是你的菜?
在现代前端开发中,Utility-First (功能优先) CSS 框架已经成为主流。其中,Tailwind CSS 无疑是市场的领导者和标杆。然而,一个名为 UnoCSS 的新星正以其惊人的性能和极致的灵活性迅速崛起。 这篇文章将深入探讨这两款工具的核心理念、技术差…...