在TLS1.3中,只保留了一种加密和保护完整性的方法就是AEAD(具有关联数据的加密认证)
许多密码应用程序既需要保密又需要消息认证。机密性是一项安全服务,确保数据仅对获得授权的人可用,通常是通过加密实现的。确保数据不会被更改或伪造,可以通过使用消息验证码来实现(MAC)。此服务也称为数据诚信,许多应用程序使用加密方法和MAC一起提供这两种安全服务,使用独立密钥的算法。最近使用单个密码算法提供两种安全服务被接受。在此概念中,密码和MAC被替换为带关联数据的认证加密(AEAD)算法。出于实现两者相组合的目的,产生了几个方案:
慢慢的业内开始提出,这样实现的AEAD算法都存在安全问题,所以从2008年起,业内开始提出,需要在一个算法内同时实现加密和认证。
而TLS1.3支持的加密组件:
我们可以发现TLS1.3中支持的算法只有AEAD。
密码学中的高级加密标准,用来替代原先的DES(Data Encryption Standard) ,经过五年的甄选流程,高级加密标准由美国国家标准与技术研究院 (NIST)于2001年11月26日发布于FIPS PUB 197,并在2002年5月26日成为有效的标准。2006年,高级加密标准已然成为对称密钥加密中最流行的算法之一。
对于128位的AES算法,在对明文加密的时候,不是一次性的对整个明文加密,而是将明文分块加密,每一块的大小就是128bit,经过AES加密器的处理,成为一个个独立的密文块,然后把它们拼接起来就形成了最终的加密结果。
如果分块过程中有的块是不满的,则需要填充—Padding。
它存在多种工作模式,下面具体来看一种。
在计数器模式下,我们不再对密文进行加密,而是对一个逐次累加的计数器进行加密,用加密后的比特序列与明文分组进行 XOR得到密文。
注:
GMAC就是利用伽罗华域(Galois Field,GF,有限域)乘法运算来计算消息的MAC值。
其中的Mh,指的是将输入与秘钥h在有限域GF(例:2^128)上做乘法
字母G指的是GMAC
字母C指的是CTR
所以就是在TLS1.3中AEAD算法使用的模式是GTR
模式,其中的消息验证码的计算方式采用的是GMAC
。
是加密分组密码的一种操作模式。
CCM
模式将众所周知的CBC-MAC
与众所周知的加密计数器模式结合在一起。这两个原语以“认证然后加密”的方式应用,也就是说,首先在消息上计算CBC-MAC
,以获得标签t
;然后使用计数器模式对消息和标签进行加密。
这种模式下,同样是将明文进行分组,然后每一小段与初始块或者上一段的密文段进行异或运算后,再与密钥进行加密。
注:
HKDF
中的salt
这样我们最终可以得到一个result
有关具体计算,现在还没有搞懂。。。
CCMP(CTR with CBC-MAC Protocol) 是 IEEE 802.11i 中推出使用基于 AES 的 CCM 模式的安全加密协议。与原来脆弱的 WEP 算法及临时补救措施 TKIP 协议相比,它具有更好的安全性,在 WiFi 中得到广泛的应用。是基于AES(Advanced Encryption Standard)加密算法和CCM(Counter-Mode/CBC-MAC)的认证方式
IEEE 802.11i(无线安全标准)是IEEE为了弥补802.11脆弱的安全加密功能(WEP,Wired Equivalent Privacy)而制定的修正案,于2004年7月完成。其中定义了基于AES的全新加密协议CCMP(CTR with CBC-MAC Protocol)。
CCM(Counter with CBC-MAC) 定义在 RFC 3610 中,它是一种使用分组算法(例如 AES)进行数据认证和加密的通用模式。
CCM对明文m
,其长度定义为l(m)
,进行分组加密和认证,处理结果同时包括密文和认证字段。
专门用于 block size 为 128 位的分组加密算法,如 AES。
M
– 输出的认证字段长度(单位:字节),取值范围:4, 6, 8, 10, 12, 14, and 16。L
– 代表l(m)
值得字节数,取值范围:2-8CCMP 协议规定:M = 8 L = 2, 即 m 最长为 65535 字节,认证字段为 8 字节
将 M 和 L 转换为 M’ 和 L’(以便容纳在一个字节中),转换关系如下
Name Description Size Encoding
---- ---------------------------------------- ------ --------
M' Number of octets in authentication field 3 bits (M-2)/2
L' Number of octets in length field 3 bits L-1
write_key
)(15-L)bytes
长度的Nonce
随机数。在任何加密密钥K 的范围内,随机数值必须唯一。也就是说,与任何给定键一起使用的随机数值集不得包含任何重复值。对使用同一密钥加密的两个不同的消息使用相同的随机数会破坏此模式的安全性。m
The inputs are summarized as:
Name Description Size
---- ----------------------------------- -----------------------
K Block cipher key/分组加密密钥 Depends on block cipher
N Nonce/随机数 15-L octets
m Message to authenticate and encrypt l(m) octets
a Additional authenticated data/附加认证数据 l(a) octets
首先定义块B_0,B_1,…,B_n 的序列,然后计算每一个块的CBC-MAC。
我们来看一下第一个块的结构,因为第一个块需要输入IV参数,也就是一个随机数。我们看一下在RFC 3610
中相关的描述:
Octet Number Contents
------------ ---------
0 Flags 1 字节
1 ... 15-L Nonce N 15-L 字节
16-L ... 15 l(m) L 字节(L 的值见 Flags 字节)
Within the first block B_0, the Flags field is formatted as follows:
分组 B_0 中的首字节 Flags 构成如下
Bit Number Contents
---------- ----------------------
7 Reserved (always zero)
6 Adata
5 ... 3 M' (1--7) = (M-2)/2 (M:4--16)
2 ... 0 L' (1--7) = L-1 (L:2--8)
Another way say the same thing is: Flags = 64*Adata + 8*M' + L'.
B_0的构成如下:
长度 1 15-L L
+----+-----+-----------+------------+
|字节 | 0 | 1 .. 15-L | 16-L .. 15 |
+----+-----+-----------+------------+
|内容 |Flags| Nonce N | m 的长度 |
+----+-----+-----------+------------+
/ \ ^
/ \ |
/ \ L -- m 的长度表示范围
/ \ (L 越大,m 可以越长)
/ Flags 展开后 \ |
+----+-+-----+-+-+-+-+-+-+ |L'(L) 决定
|位 |7| 6 |5|4|3|2|1|0| |Nonce 的长度
+----+-+-----+-+-+-+-+-+-+ |
|内容 |0|Adata| M' | L' | ---+
+----+-+-----+-+-+-+-+-+-+
注:
Bit Number
第七位一直是0
Bit Number
第零到第五位分别表示L'
、M'
Flags
的Bit Number
第六位表示是否有附加数据,若 = 0
则表示具有附加数据,需要在B_0
之后添加附加数据块。下面我们来看一下它的构成情况。在TLS1.3中的附加数据是指PLaintext
中的ContentType、Version、length
,这三个字段:
additional_data = TLSCiphertext.opaque_type ||
TLSCiphertext.legacy_record_version ||
TLSCiphertext.length
在RFC3610中规定:
If 0 < l(a) < (2^16 - 2^8), then the length field is encoded as two
octets which contain the value l(a) in most-significant-byte first
order.
也就是说附加数据a
的长度 < 65536-256
又因为type(1) + version(2) + length(2) = 5bytes
所以我们遵循这条规定,给定2byte
就可以了。下面构造块。
主要由l(a)
和a
构成:
block[0] = ( add_len >> 8 ) & 0xFF ;
block[1] = ( add ) & 0xFF ;
必要时最后一个分组添加 0x00 补齐,这些分组依次添加到 B_0 后面(记为 B_1、B_2……)
将 m 分成 16 字节长的分组,必要时最后一个分组补 0 对齐(如果 m 为空串,则此步省略)。
最终得到:B_0||附加认证分组||明文分组
,按下列公式计算CBC-MAC
X_1 := E( K, B_0 )
X_i+1 := E( K, X_i XOR B_i ) for i=1, ..., n
T := first-M-bytes( X_n+1 ) -- T 作为 MAC 值
B_0 B_1 B_2 B_n
| | | |
| V V V
| +-->XOR +-->XOR +-->XOR
| | | | | | |
V | V | V | V
+----+ | +----+ | +----+ | +----+
K-->|加密 | | |加密| | |加密 | ... | |加密|
+----+ | +----+ | +----+ | +----+
| | | | | | |
+----+ +----+ +--> ->-+ |
| | | X_n |
V V V V
X_1 X_2 X_3 X_n+1
主要是采用Counter (CTR) 模式加密,首先计算如下密钥流,我们知道这个模式首先会对count
加密:
S_i := E( K, A_i ) for i=0, 1, 2, ...
其中的A_i
是对应每个计数的块,其结构与上面定义的块是类似的:
The values A_i are formatted as follows, where the Counter field i is
encoded in most-significant-byte first order:
Octet Number Contents
------------ ---------
0 Flags
1 ... 15-L Nonce N
16-L ... 15 Counter i
The Flags field is formatted as follows:
Bit Number Contents
---------- ----------------------
7 Reserved (always zero)
6 Reserved (always zero)
5 ... 3 Zero
2 ... 0 L'
Another way say the same thing is: Flags = L'.
其中的L
就是指输入的长度即counter i_length
我们再看一下构成:
A_i 构成如下
长度 1 15-L L
+----+-----+-----------+------------+
|字节 | 0 | 1 .. 15-L | 16-L .. 15 |
+----+-----+-----------+------------+
|内容 |Flags| Nonce N | Counter i | -- Counter i 的值能够在 L 字节内表示
+----+-----+-----------+------------+ (因为 i <= l(m))
/ \ ^
/ \ |
/ \ |
/ \ |
/ Flags 展开后 \ |
+----+-+-----+-+-+-+-+-+-+ |L'(L) 决定
|位 |7|Adata|5|4|3|2|1|0| |Nonce 的长度
+----+-+-----+-+-+-+-+-+-+ |
|内容 |0| 0 |M'=0 | L' | ---+
+----+-+-----+-+-+-+-+-+-+
|
M' 不同于 B_0(B_0 中始终不为 0)
最终明文与密钥流异或得到密文,其中s_0
不用于加密,但参与数据校验
A_0 A_1 A_2 A_n
| | | |
V V V V
+----+ +----+ +----+ +----+
K-->|加密 | |加密| | 加密| ... |加密|
+----+ +----+ +----+ +----+
| | | |
| |S_1 |S_2 |S_n
| | | | 密钥: S_1 | S_2 | ... | S_n
| V V V XOR
| M_1-->XOR M_2-->XOR M_n-->XOR 明文: M_1 | M_2 | ... | M_n
| | | | |
V V V V V
S_0 C_1 C_2 C_n 密文: C_1 | C_2 | ... | C_n
使用CBC-MAC
计算出的T
与 S_0
的异或结果取前M
字节,得到认证字段。
U := T XOR first-M-bytes( S_0 )
取前 l(m) 字节 取前 M 字节
================================= ============
S_1/E(K,A_1) | S_2/E(K,A_2) | ... || S_0/E(K,A_0)
XOR m || X_n+1
-----------------------------------------------------
= 最终输出 c
在TLS1.3中除了支持上面提到的两种模式,还有这一种模式,chacha20是一种流密码,而上面提到的AES是分组密码,这是加密算法的两大分类,poly1305同理也是一种计算消息认证码的算法,主要的目的是进行消息认证。
首先使用chacha20密码中的核函数对256位的密钥进行扩展,扩展成明文长度的密钥,然后与明文异或得到密文,之后使用poly1305对附加数据进行计算其认证码,认证码的长度是128位,在TLS中输入的密钥是一次性密钥,在进行密钥扩充时保留的前256位扩充密钥。
https://www.cryptrec.go.jp/exreport/cryptrec-ex-2601-2016.pdf
https://www.cnblogs.com/aquar/p/8437172.html
https://tools.ietf.org/id/draft-agl-tls-chacha20poly1305-03.html
wiki salsa20
https://github.com/pts/chacha20/blob/master/chacha20.py
随缘打赏!