我们应该使用 TLS1.3 吗

Python038

我们应该使用 TLS1.3 吗,第1张

SSL(Socket Layer Security)和 TLS(Transport Layer Security) 都是属于安全协议,主要作用是保证客户端和服务端之间能安全通讯。SSL是较早的协议,TLS 是 SSL的替代者。

SSL 版本 1.0、2.0 和 3.0,TLS 版本 1.0、1.2 和 1.3。SSL协议和TLS1.0 由于已过时被禁用,目前TLS 1.3 是互联网上部署最多的安全协议,它是TLS最新版本 ,它增强了过时的安全性,并增加了更多的触控性。通过下面几点可以有个简单认识:

现代浏览器支持 TLS 1.2 和 TLS 1.3 协议,但 1.3 版本要好得多。 TLS 1.3 对早期版本进行了多项改进,最明显的是简化了TLS握手操作,使得握手时间变短、网站性能得以提升、改善了用户体验,另外支持的密码套件更安全和简单。

密码套件

TLS/SSL 使用一种或多种密码套件。 密码套件是身份验证、加密和消息身份验证的算法组合。TLS 1.2 版使用的算法存在一些弱点和安全漏洞。在 TLS 1.3 中删除了这些算法:

另外一个很重要的更新是TLS1.3 支持 perfect-forward-secrecy (PFS)算法。

向前保密 (PFS)是特定密钥协商协议的一项功能,如果一个长周期的会话密钥被泄露,黑客就会截获大量数据,我们可以为每个会话生成唯一的会话密钥,单个会话密钥的泄露不会影响该会话之外的任何数据。

TLS在早期版本的握手期间可以使用两种机制之一交换密钥:静态 RSA密钥和 Diffie-Hellman 密钥。 在 TLS1.3 中,RSA 以及所有静态(非 PFS)密钥交换已被删除,只保留了DHE、ECDHE

可以查看网站的安全详情来确认它是否使用"ECDHE"或"DHE"。

AES (Advanced Encryption Standard) 对称加密,它是 高级加密 标准。早期的加密标准DES(Data Encryption Standard) 已被弃用。

AES选择合适的 加密模式 很重要,应用比较多的两种模式 CBC 和 GCM。

CBC 密码分组链接模式

明文分块,第一个块使用初始化向量,后面的每个明文块在加密前与前一个密文块进行异或运算。

这种模式存在的问题:

CTR 计数模式

明文分块按顺序编号,通过加密"计数器"的连续值来生成下一个密钥流块。CTR 模式非常适合在多核处理器上运行,明文块可以并行加密。

GCM 伽罗瓦/计数器模式

GCM = CTR + Authentication。其加密过程,明文块是按顺序编号的,然后这个块号与初始向量 组合并使用块密码E加密,然后将此加密的结果与明文进行异或以生成密文。

简单来说,GCM 是 CTR 身份验证的组合,它更快、更安全。它将接受流水线和并行化实现,并具有最小的计算延迟,所以它的应用更加广泛。

客户端最低版本

客户端最低版本

一般建议同时兼容1.2和1.3

测试是否支持 TLS 1.2

测试是否支持 TLS 1.3

TLS 的目的便是解决数据的

一、Record 记录协议 (对称加解密)

二、HandShake 握手,挥手

验证通讯双方身份

交换加解密的安全套件

协商加密解密参数

当一个TLS会话建立好之后,会使用对称加密的密钥去通信,那么如何实现事先将对称加密的密钥传递给TLS会话的另一方呢。利用的就是非对称加密。分对称加密比对称加密慢数千倍,所以只是使用对称加密传递之后加密使用的对称加密的密钥。之后的加密安全性靠的是对称加密来解决。

非对称加密是有一把公钥和一把私钥,公钥可以公开,而私钥不能。

用公钥加密成密文,再将密文用私钥解密就能实现加解密过程。

而用私钥加密,公钥解密就是签名认证过程。

常见的非对称加密方式分为两大类

RSA 没有向前安全性,也就是需要每次的对称加密密钥的传递都是基于 公钥加密,服务端私钥解密。如果服务端的私钥丢失了,那几年前的通信数据都有可能被解密。所以这是极度不安全的,私钥的地位太重了,如果每次的加解密都是临时生成的密码来解决安全性,才不会对私钥的安全性有如此强的依赖。在2013年的棱镜门事件中,某个CA机构迫于美国政府压力向其提交了CA的私钥,这就是十分危险的。如果向前不安全,那么之前利用该CA私钥都会全部遭殃。所以这里说的是更安全的 DH类非对称加密。

下图就是DH密钥交换的TLS握手过程

DH 密钥交换协议,Diffile-Hellman key Exchange,简称 DH 或 DHE 。它可以让双方在完全没有对方任何预先信息的条件下通过一个不安全的信道创建一个密钥。

1、客户端浏览器随机生成一个值Ra,计算Pa(x,y) = Ra*Q(x,y), Q(x,y)为全世界公认的某个椭圆曲线算法的基点。将Pa(x,y)发送至服务器。

2、服务器随机生成一个值Rb,计算 Pb(x,y) = Rb * Q(x,y)。将Pb(x,y)发送到客户端浏览器。

3、客户端计算Sa(x,y) = Ra * Pb(x,y),服务器计算Sb(x,y)=Rb*Pa(x,y)

4、算法保证了Sa=Sb=S, 提取其中的S的x向量作为密钥。

为了解决上述DH的问题,引入了ECC椭圆曲线,进而进化为 ECDHE 算法,称为 Elliptic Curve Diffie-Hellman Key Exchange。ECC和RSA 在288字节的长度下,破解RSA需要煮沸一勺水的能量,而破解相同位数的ECC 就需要煮沸整个地球水的能量。RSA 为了提高安全性,只能靠增大密钥位数。尴尬的是现在的超算越来越厉害。量子计算下秀尔算法可8h内轻松破解2048位的RSA。RSA只能再增大密钥位数,但是再增大位数,移动端设备就惨了,你增大的密钥是运营商要收取流量费用的,而且加解密太费电。

ECC 的数学原理是椭圆曲线和离散对数。椭圆曲线很复杂。为了提升性能,还需要选择一个椭圆曲线,但是它不是真正的椭圆形,下面有图可以看到,只是运算上用到了椭圆算法。

但是ECC也有很多问题,1、ECC 可能有后门,如NSA(美国国家安全局发布的一套算法),这个算法就是被怀疑被植入后门了。2、而且ECC很多的算法都被注册专利了,一不小心就要吃官司,其专利大部分都被黑莓注册。

ECC 椭圆曲线的定义

ECC 的算法原理过于复杂,这里表示我也看不懂。点到为止吧。(以后看懂了再来补充)

这里的抓包结果就是用的EC DH E 算法来进行密钥交换的。这里选择的曲线是 secp256r1, 在这个曲线中,基点和参数已经给出了,PubKey 也给出了。

在 TLS1.3 中,一般使用的 X25519 曲线 (蒙哥马利曲线)

import "workname/packetfolder"

导入多个包

方法调用 包名.函数//不是函数或结构体所处文件或文件夹名

packagename.Func()

前面加个点表示省略调用,那么调用该模块里面的函数,可以不用写模块名称了:

当导入一个包时,该包下的文件里所有init()函数都会被执行,然而,有些时候我们并不需要把整个包都导入进来,仅仅是是希望它执行init()函数而已。下划线的作用仅仅是为了调用init()函数,所以无法通过包名来调用包中的其他函数

import _ package

变量声明必须要使用否则会报错。

全局变量运行声明但不使用。

func 函数名 (参数1,参数2,...) (返回值a 类型a, 返回值b 类型b,...)

func 函数名 (参数1,参数2,...) (返回值类型1, 返回值类型2,...)

func (this *结构体名) 函数名(参数 string) (返回值类型1, 返回值类型2){}

使用大小来区分函数可见性

大写是public类型

小写是private类型

func prifunc int{}

func pubfunc int{}

声明静态变量

const value int

定义变量

var value int

声明一般类型、接口和结构体

声明函数

func function () int{}

go里面所有的空值对应如下

通道类型

内建函数 new 用来分配内存,它的第一个参数是一个类型,不是一个值,它的返回值是一个指向新分配类型零值的指针

func new(Type) *Type

[这位博主有非常详细的分析] https://www.01hai.com/note/av133981

Go 语言支持并发,我们只需要通过 go 关键字来开启 goroutine 即可。

goroutine 是轻量级线程,goroutine 的调度是由 Golang 运行时进行管理的。

同一个程序中的所有 goroutine 共享同一个地址空间。

语法格式如下:

通道(channel)是用来传递数据的一个数据结构。

通道的声明

通道可用于两个 goroutine 之间通过传递一个指定类型的值来同步运行和通讯。操作符 <- 用于指定通道的方向,发送或接收。如果未指定方向,则为双向通道。

[这里有比较详细的用例] https://www.runoob.com/go/go-interfaces.html

go里面的空接口可以指代任何类型(无论是变量还是函数)

声明空接口

go里面的的强制类型转换语法为:

int(data)

如果是接口类型的强制转成其他类型的语法为:

go里面的强制转换是将值复制过去,所以在数据量的时候有比较高的运行代价