Transport Layer Security for UDPTCP(TLS/DTLS1.2)

news/2024/11/15 1:07:37/文章来源:https://www.cnblogs.com/elegantcloud/p/18334711

参考文章:https://blog.csdn.net/alwaysrun/article/details/89076492

  https://www.jianshu.com/p/fd0a624d0912

  https://cloud.tencent.com/developer/article/1928677

文档:https://www.rfc-editor.org/rfc/rfc6347

   https://www.rfc-editor.org/rfc/rfc5246

1.SSL/TLS 协议

1.1背景

首先从我们比较熟悉的 SSL/TLS 开始讲起。SSL(Secure Socket Layer) 和 TLS(Transport Layer Security) 简单理解就是同一件东西的两个演进阶段,同样都是在应用层和传输层之间加入的安全层,最早的时候这个安全层叫做 SSL,由 Netscape 公司推出,后来被 IETF 组织标准化并称之为 TLS。

TLS的动机从HTTPS讲起。HTTP 本身不具备加密的功能,所以也无法做到对通信整体(使用 HTTP 协议通信的请求和响应的内容)进行加密。按传输层 TCP/IP 协议族的工作机制,通信内容在所有的通信线路上都有可能遭到窥视。而HTTP 在传输数据的过程中,所有的数据都是明文传输,非常奔放,自然没有安全性可言。数据在公网上传输,容易被第三方获取,尤其特别是一些敏感数据,比如用户密码和信用卡信息等,一旦被第三方获取后果不堪设想。HTTPS 主要用于解决数据安全传输的问题,通过加密套件,让数据在网络传输过程中对第三方“不可见”(看见的是无意义的乱码信息)。在 HTTPS 中,原有的 HTTP 协议会得到 TLS (安全传输层协议) 或其前辈 SSL (安全套接层) 的加密。因此 HTTPS 也常指 HTTP over TLS 或 HTTP over SSL,即HTTPS = HTTP + SSL / TLS。

 

SSL/TLS 的作用是为了解决互联网通信中存在的三种风险:

  1. 窃听风险:第三方可以获知通信内容;
  2. 篡改风险:第三方可以修改通信内容;
  3. 冒充风险:第三方可以冒充他人身份参与通信。

SSL/TLS 协议能够做到以下这几点,从而解决上述的三种风险:

  1. 所有信息通过加密传播,第三方无法窃听;
  2. 具有数据签名及校验机制,一旦被篡改,通信双方立刻可以发现;
  3. 具有身份证书,防止其他人冒充。

1.2协议细则

(1)架构

SSL/TLS协议有一个高度模块化的架构,分为很多子协议,如下图所示。也可以简单地理解为,TLS协议分为两层,一层是记录层,一层是握手层。

  • TLS记录层负责从更高层接收数据并对其进行处理。具体来说,记录层接收要传输的消息,将数据分成可管理的块,可选地压缩数据,应用MAC(消息认证码),加密,然后传输结果。接收到的数据被解密、验证、解压缩、重新组装,然后传递给更高层的客户端。 另外,为了允许TLS协议的扩展,记录层可以支持额外的记录内容类型。
  • 在TLST握手层,中有三个子协议使用到了记录: handshake protocol、alert protocol、changecipher spec protocol。

SSL握手协议:包括协商安全参数和密码套件、服务器身份认证(客户端身份认证可选)、密钥交换;
SSL握手密钥参数更换协议:一条消息表明握手协议已经完成;
SSL告警协议:对握手协议中一些异常的错误提醒,分为fatal和warning两个级别,fatal类型的错误会直接中断SSL链接,而warning级别的错误SSL链接仍可继续,只是会给出错误警告;

(2)流程

SSL/TLS协议的执行过程被设计为两阶段:握手阶段和应用阶段。

  • 握手阶段也称协商阶段,在这一阶段,客户端和服务器端会认证对方身份(依赖于PKI体系,利用数字证书进行身份认证),并协商通信中使用的安全参数、密码套件以及MasterSecret。后续通信使用的所有密钥都是通过MasterSecret生成。
  • 在握手阶段完成后,进入应用阶段。在应用阶段通信双方使用握手阶段协商好的密钥进行安全通信。

随机数

生成方

生成报文

含义

A

Client

ClientHello

C = pre-master-key

master-key = function(A,B,pre-master-key)

B

Server

ServerHello

C

Client

——

1.3协议实现

(1)记录层

记录层将接收到的数据分片成大小不超过2^14字节的TLSPlaintext记录。这个分片过程是为了使数据块更易于管理和传输。重要的一点是,客户端的消息边界在记录层中并不保留,这意味着:

多个相同类型的客户端消息可以合并成一个TLSPlaintext记录。

一个消息可以被分片成多个记录。

struct {
    uint8 major;
    uint8 minor;
} ProtocolVersion;

enum {
    change_cipher_spec(20), alert(21), handshake(22),
    application_data(23), (255)
} ContentType;

struct {
    ContentType type;
    ProtocolVersion version;
    uint16 length;
    opaque fragment[TLSPlaintext.length];
} TLSPlaintext;

 (2)握手层

ChangeCipherSpec

更改密码规范协议(Change Cipher Spec Protocol)用于标志加密策略的转换。它通过一个单字节的消息来通知对方,后续的通信将使用新协商的加密算法和密钥。

struct {
    enum { change_cipher_spec(1), (255) } type;
} ChangeCipherSpec;

Alert

警报消息传达消息的严重性(警告或致命)和警报的描述。严重性为致命的警报消息会立即终止连接。

enum { warning(1), fatal(2), (255) } AlertLevel;
//warning:警告级别的警报,表示可能存在问题,但不需要立即终止连接。
//fatal:致命级别的警报,表示严重问题,必须立即终止连接。
enum {
    close_notify(0),
    unexpected_message(10),
    bad_record_mac(20),
    decryption_failed_RESERVED(21),
    record_overflow(22),
    decompression_failure(30),
    handshake_failure(40),
    no_certificate_RESERVED(41),
    bad_certificate(42),
    unsupported_certificate(43),
    certificate_revoked(44),
    certificate_expired(45),
    certificate_unknown(46),
    illegal_parameter(47),
    unknown_ca(48),
    access_denied(49),
    decode_error(50),
    decrypt_error(51),
    export_restriction_RESERVED(60),
    protocol_version(70),
    insufficient_security(71),
    internal_error(80),
    user_canceled(90),
    no_renegotiation(100),
    unsupported_extension(110),
    (255)
} AlertDescription;

struct {
    AlertLevel level;
    AlertDescription description;
} Alert;

Handshake

TLS握手协议的任务是生成会话状态的加密参数,该协议在TLS记录层之上运行。当TLS客户端和服务器首次开始通信时,它们会协商协议版本,选择加密算法,可选地相互认证,并使用公钥加密技术生成共享的秘密。

enum {
    hello_request(0), client_hello(1), server_hello(2),
    certificate(11), server_key_exchange(12),
    certificate_request(13), server_hello_done(14),
    certificate_verify(15), client_key_exchange(16),
    finished(20), (255)
} HandshakeType;

struct {
    HandshakeType msg_type;    /* 握手类型 */
    uint24 length;             /* 消息的字节数 */
    select (HandshakeType) {
        case hello_request:       HelloRequest;
        case client_hello:        ClientHello;
        case server_hello:        ServerHello;
        case certificate:         Certificate;
        case server_key_exchange: ServerKeyExchange;
        case certificate_request: CertificateRequest;
        case server_hello_done:   ServerHelloDone;
        case certificate_verify:  CertificateVerify;
        case client_key_exchange: ClientKeyExchange;
        case finished:            Finished;
    } body;
} Handshake;

 ①HelloRequest

HelloRequest消息是由服务器发送给客户端的一个简单通知,指示客户端应该重新开始协商过程。

服务器可以在任何时间发送HelloRequest消息,但不应在客户端初次连接时立即发送。

HelloRequest消息结构非常简单,仅包含一个空的结构体。

struct { } HelloRequest;

②ClientHello

当客户端首次连接到服务器时,必须发送ClientHello作为其第一条消息。客户端还可以在收到HelloRequest后或出于自身需要重新协商现有连接的安全参数时发送ClientHello。

struct {
    uint32 gmt_unix_time;
    opaque random_bytes[28];
} Random;

enum { null(0), (255) } CompressionMethod;

uint8 CipherSuite[2]; /* 加密套件选择器 */

struct {
    ProtocolVersion client_version;
    Random random;
    SessionID session_id;
    CipherSuite cipher_suites<2..2^16-2>;
    CompressionMethod compression_methods<1..2^8-1>;
    select (extensions_present) {
        case false:
            struct {};
        case true:
            Extension extensions<0..2^16-1>;
    };
} ClientHello;

ClientHello消息包含以下主要部分:

  • Random:一个包含当前时间和28字节随机数的结构,用于生成后续的加密参数。
  • SessionID:一个可变长度的会话标识符,用于指示客户端希望重用的会话。
  • CipherSuite:一个加密套件列表,按客户端的偏好顺序排列。
  • CompressionMethod:一个压缩方法列表,按客户端的偏好顺序排列。
  • Extensions:一个可选的扩展字段,用于请求服务器提供扩展功能。

加密套件列表包含客户端支持的加密算法组合,每个加密套件定义一个密钥交换算法、一个批量加密算法(包括密钥长度)、一个MAC算法和一个PRF算法。

③ClientKeyExchange

此消息总是由客户端发送。如果发送了客户端证书消息,它必须紧跟在客户端证书消息之后。否则,它必须是客户端在接收到ServerHelloDone消息后发送的第一条消息。

通过此消息,设置预主密钥,方法是直接传输RSA加密的秘密或传输Diffie-Hellman参数,使双方能够达成相同的预主密钥。

struct {
    select (KeyExchangeAlgorithm) {
        case rsa:
            EncryptedPreMasterSecret;// RSA加密的预主密钥
        case dhe_dss:
        case dhe_rsa:
        case dh_dss:
        case dh_rsa:
        case dh_anon:
            ClientDiffieHellmanPublic;// 客户端的Diffie-Hellman公钥值
    } exchange_keys;
} ClientKeyExchange;
  • 计算主密钥

  对于所有密钥交换方法,使用相同的算法将pre_master_secret转换为master_secret。一旦计算出master_secret,pre_master_secret应从内存中删除。

master_secret = PRF(pre_master_secret, "master secret",
                    ClientHello.random + ServerHello.random)//伪随机函数
                    [0..47];
  • RSA

当使用RSA进行服务器认证和密钥交换时,客户端生成一个48字节的pre_master_secret,使用服务器的证书中的公钥加密,并发送给服务器。服务器使用其私钥解密得到pre_master_secret。然后双方按照上述规定将pre_master_secret转换为master_secret。此结构是ClientKeyExchange消息的变体,不是独立消息。

PreMasterSecret中的版本号是客户端在ClientHello.client_version中提供的版本,而不是为连接协商的版本。此功能设计用于防止回滚攻击。

struct {ProtocolVersion client_version;opaque random[46];
} PreMasterSecret;

struct {
    public-key-encrypted PreMasterSecret pre_master_secret;//由客户端生成的随机值,用于生成主密钥
} EncryptedPreMasterSecret;
  • Diffle-Herman

如果客户端使用了Diffie-Hellman密钥交换方法,客户端需要向服务器传递其Diffie-Hellman公钥值(Yc)。根据情况不同,Yc的传递可以是显式的或隐式的。

enum { implicit, explicit } PublicValueEncoding;
//implicit:客户端已经发送了包含Diffie-Hellman密钥的证书,因此不需要再次发送Yc。客户端密钥交换消息将被发送,但内容为空。
//explicit:需要发送Yc。
struct {
    select (PublicValueEncoding) {
        case implicit: struct { };
        case explicit: opaque dh_Yc<1..2^16-1>;
    } dh_public;//客户端的Diffie-Hellman公钥值(Yc)
} ClientDiffieHellmanPublic;

④CertificateVerify

此消息用于对客户端证书进行显式验证。此消息仅在客户端证书具有签名能力(即,除包含固定Diffie-Hellman参数的证书外的所有证书)后发送。发送时,它必须紧跟在客户端密钥交换消息之后。

struct {
    digitally-signed struct {
        opaque handshake_messages[handshake_messages_length];
    }
} CertificateVerify;

 这里的handshake_messages指的是从客户端hello开始到(但不包括)此消息为止发送或接收的所有握手消息,包括握手消息的类型和长度字段。这是迄今为止交换的所有握手结构(如第7.4节所定义)的连接。注意,这要求双方要么缓存消息,要么为所有潜在的哈希算法计算运行哈希,直到CertificateVerify计算时。服务器可以通过在CertificateRequest消息中提供有限的摘要算法集合来最小化此计算成本。

⑤Finished

完成消息(Finished)是TLS握手过程中的最后一个握手消息,用于确认整个握手过程的完整性和正确性。它是第一个使用刚协商的加密算法、密钥和秘密进行保护的消息。

完成消息总是在更改密码规范消息(ChangeCipherSpec)之后立即发送。这个顺序是必须的,因为完成消息是用新协商的加密算法和密钥保护的。

struct {opaque verify_data[verify_data_length];
} Finished;
//verify_data是一个通过伪随机函数(PRF)计算的验证数据
PRF(master_secret, finished_label, Hash(handshake_messages))[0..verify_data_length-1];
/*
finished_label:客户端发送的完成消息使用字符串:"client finished"。服务器发送的完成消息使用字符串:"server finished"。
*/
/*
handshake_messages:这是到目前为止交换的所有握手消息的哈希值,不包括HelloRequest消息和记录层头。
*/

2.DTLS(1.2)

2.1背景

DTLS 的全称为 Datagram Transport Layer Security,从名字上就可以看出它和 TLS 的区别就在于多了一个“Datagram”,因为我们把使用 UDP 传输的报文叫做 “Datagram”,所以这个名字也就意味着 DTLS 是适用于 UDP 传输过程的加密协议。
TLS 1.2 及之前都没有尝试解决 DoS 攻击的问题,直到 TLS 1.3 才通过加入了 HelloRetryRequest 和 Cookie 来解决 DoS 攻击的问题。而相对 TCP 来说,UDP对 DoS 攻击更加敏感,因此 DTLS 在 1.0 版本就加入了 HelloVerifyRequest 和 Cookie,用于服务端对客户端的二次校验。
单对比 TLS 1.2,DTLS 1.2 大部分步骤都是一样的,只是在服务端多了一步 HelloVerifyRequest,客户端因此也多了第二次的 ClientHello

2.2协议细则

(1)架构

(2)流程

DTLS使用与TLS相同的所有握手消息和流程,但有三个主要变化:

  1. 添加了无状态的cookie交换,以防止拒绝服务攻击。
  2. 修改了握手头部以处理消息丢失、重新排序和DTLS消息分片(为了避免IP分片)。
  3. 为了处理消息丢失而设置了重传定时器。

 

服务端在首次收到客户端发送的 Client Hello 之后,只会生成一个 Cookie,不进行任何其他的操作,并给客户端发送 HelloVerifyRequest 消息,带上这个 Cookie。只有当客户端重新发送一次 Client Hello,并带上服务端发送的这个 Cookie 后,服务端才会继续握手过程。

2.3协议实现

(1)记录层

(2)握手层

为了支持消息丢失、重新排序和消息分片,DTLS修改了TLS 1.2的握手头部结构:

enum {
  hello_request(0), client_hello(1), server_hello(2),
  hello_verify_request(3),                          // 新字段
  certificate(11), server_key_exchange(12),
  certificate_request(13), server_hello_done(14),
  certificate_verify(15), client_key_exchange(16),
  finished(20), (255) } HandshakeType;

struct {
  HandshakeType msg_type;
  uint24 length;
  uint16 message_seq;                               // 新字段
  uint24 fragment_offset;                           // 新字段
  uint24 fragment_length;                           // 新字段
  select (HandshakeType) {
    case hello_request: HelloRequest;
    case client_hello:  ClientHello;
    case server_hello:  ServerHello;
    case hello_verify_request: HelloVerifyRequest;  // 新字段
    case certificate: Certificate;
    case server_key_exchange: ServerKeyExchange;
    case certificate_request: CertificateRequest;
    case server_hello_done: ServerHelloDone;
    case certificate_verify:  CertificateVerify;
    case client_key_exchange: ClientKeyExchange;
    case finished: Finished;
  } body;
} Handshake;
  • 消息序列号(message_seq:每条握手消息都有一个序列号,以确保消息的完整性和顺序。序列号从0开始,每发送一条消息递增。这有助于在消息重传时维持顺序。

  在每次握手中,每方传输的第一条消息的message_seq总是为0。每当生成新消息时,message_seq的值增加1。

  • 片段偏移(fragment_offset)和片段长度(fragment_length:这两个新字段允许将较大的握手消息分成多个片段进行传输。这是因为UDP等数据报协议不保证单一消息的完整性,所以需要手动处理消息的分片和重组。

  • 新的握手类型(hello_verify_request:这是DTLS特有的消息类型,用于验证客户端,作为防止DoS攻击的一部分。

 ①ClientHello

struct {
  ProtocolVersion client_version;
  Random random;
  SessionID session_id;
  opaque cookie<0..2^8-1>;                             // 新字段
  CipherSuite cipher_suites<2..2^16-1>;
  CompressionMethod compression_methods<1..2^8-1>;
} ClientHello;

②Certificate

 

随机数

生成方

生成报文

A

Client

ClientHello

B

Server

ServerHello

C

Client

——

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

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

相关文章

代码随想录Day1

704.二分查找 给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。 示例 1: 输入: nums = [-1,0,3,5,9,12], target = 9 输出: 4 解释: 9 出现在 nums 中并且下标为 4 …

P2119 [NOIP2016 普及组] 魔法阵

P2119 [NOIP2016 普及组] 魔法阵 传送门 1 我们可以先写出\(O(m^4)\)的暴力 #include <bits/stdc++.h> #define int long long #define PII pair<int, int> using namespace std; const int inf = 0x3f3f3f3f; const int MOD = 1e9 + 7, N = 4e4 + 5; …

Tokitsukaze and Two Colorful Tapes

看这篇题解就好了 解释一下为什么山谷=山峰 证明加强结论:对于每个环,山谷=山峰 证:对于任何一种方案,这种方案下的任意一个环,我们断开某条边,他就会长成这个样子:起点和终点连起来,不难发现是山谷=山峰 再假设我们已经定下了山谷和山峰的个数\(a\),那么\(2(x-y)\)的…

从C++看C#托管内存与非托管内存

进程的内存 一个exe文件,在没有运行时,其磁盘存储空间格式为函数代码段+全局变量段。加载为内存后,其进程内存模式增加为函数代码段+全局变量段+函数调用栈+堆区。我们重点讨论堆区。进程内存函数代码段全局变量段函数调用栈堆区托管堆与非托管堆C# int a=10这种代码申请的内…

Magic-PDF:端到端PDF文档解析神器 构建高质量RAG必备!

项目结构流程解析 预处理的作用是判断文档内容是否需要进行OCR识别,如果是普通可编辑的PDF文档,则使用PyMuPDF库提取元信息。 模型层除了常规的OCR、版面结构分析外,还有公式检测模型,可提取公式内容,用于后续把公式转化为Latex格式。但是目前暂无表格内容识别,官方预计1…

Windows系统常用端口详解

135端口135主要用于Microsoft的远程过程调用(RPC)服务。RPCSS(Remote Procedure Call Subsystem) 服务是 COM 和 DCOM 服务器的服务控制管理器。它执行 COM 和 DCOM 服务器的对象激活请求、对象导出程序解析和分布式垃圾回收。如果此服务被停用或禁用,则使用 COM 或 DCOM 的…

Albumentations库使用

介绍Albumentations的核心使用方法,提供对应测试代码1 Albumentations库介绍 一个好用的开源图像处理库,适用于对RGB、灰度图、多光谱图像,以及对应的mask、边界框和关键点同时变换。通常用于数据增广,是PyTorch生态系统的一部分。 主页:https://albumentations.ai/ 2 核心…

LinkAI RAG知识库平台优化之路

LinkAI RAG知识库平台支持无结构文档、Q&A问答对、多列表格以及网站内容自动导入,并加入了自研的增强解析功能支持对文档中图片以及表格的自动解析。支持基于语义的向量检索和基于关键词的全文检索的增强混合检索功能,生成的回复可以标注答案来源,同时可以在使用记录中查…

14. 迭代器、生成器、模块与包、json模块

1.迭代器 1.1 迭代器介绍 迭代器是用来迭代取值的工具 每一次迭代得到的结果会作为下一次迭代的初始值,单纯的重复并不是迭代# while循环实现迭代取值 a = [1, 2, 3, 4, 5, 6] index = 0 while index < len(a):print(a[index])index += 1 1.2 可迭代对象 内置有_ _iter_ _方…

# 代码随想录二刷(哈希表)

代码随想录二刷(哈希表) 三数之和思路反正对于我来说是真的难想出来。若这道题还是采用哈希表的思路去做,非常麻烦,并且还要考虑去重的操作。所以这道题其实用双指针,是更方便的。具体程序如下: class Solution:def threeSum(self, nums: List[int]) -> List[List[int]]…

ctfshow-web入门-nodejs系列

web334 下载源码后缀改为zip打开即可 先对源码经行一个简单的分析 login.js// 引入Express框架 var express = require(express);// 创建一个路由实例 var router = express.Router();// 引入用户数据,假设user模块导出的是一个包含用户项的对象 var users = require(../modul…

2021年我因为Tab Session Manager丢失数据,好像是研究过一次leveldb的查看/解码方式 但是当时好像因为时间关系没能成功 / chrome .ldb文件

Default\Local Storage\leveldb .ldb2023年下半年我因为chatmindai修改域名,又研究过一次,因为时间关系也没有细究最近,我想查看一下anki的devtool的Local Storage,即https://ankiweb.net/shared/info/31746032这个插件产生的 C:\Users\xxx\AppData\Local\Anki\QtWebEngine…