rfc8446是关于TLS1.3 协议的标准
TLS1.3的流程
注:
+:上一消息的扩展消息
*:可选发送
{}:用握手层流密钥加密
[]:用流密钥加密
这张彩图也不错
client hello
client hello的格式如下所示:
uint16 ProtocolVersion;
opaque Random[32];
uint8 CipherSuite[2]; /* Cryptographic suite selector */
struct {
ProtocolVersion legacy_version = 0x0303; /* TLS v1.2 */
Random random;
opaque legacy_session_id<0..32>;
CipherSuite cipher_suites<2..2^16-2>;
opaque legacy_compression_methods<1..2^8-1>;
Extension extensions<8..2^16-1>;
} ClientHello;
通过wireshark,抓取到了连接测试网站1的client hello包,如图1所示,后续分析将和图1对照分析。
legacy version和supported_versions
在TLS1.3之前的版本中,legacy version用于进行版本协商,并代表客户端支持的最高版本。在TLS1.3中客户端在supported_versions扩展名中添加客户端所支持的TLS版本列表,与此同时,legacy_version必须设置为0x0303,即TLS1.2的版本号。
如图1所示,这是一个TLS 1.3 的client hello,其version是0x0303,它有一个supported_versions的扩展字段,里面支持的最高协议是TLS1.3(0x0304).
legacy_session_id
TLS1.3中不再使用SessionID进行会话恢复,这一特性已经和预共享密钥PSK合并了,设置这个字段的意义,主要也是为了兼容之前版本,如果 Client 有 TLS 1.3 版本之前的 Server 设置的缓存 Session ID,那么这个字段要填上这个 ID 值。兼容模式下,这个值必须是非空的,所以如果Client不能提供之前版本的值,那么需要重新生成一个32字节的值。
密钥交换
客户端在“Client Hello”消息里直接用“supported_groups”带上支持的曲线,比如 P-256、x25519,
enum {
/* Elliptic Curve Groups (ECDHE) */
secp256r1(0x0017), secp384r1(0x0018), secp521r1(0x0019),
x25519(0x001D), x448(0x001E),
/* Finite Field Groups (DHE) */
ffdhe2048(0x0100), ffdhe3072(0x0101), ffdhe4096(0x0102),
ffdhe6144(0x0103), ffdhe8192(0x0104),
/* Reserved Code Points */
ffdhe_private_use(0x01FC..0x01FF),
ecdhe_private_use(0xFE00..0xFEFF),
(0xFFFF)
} NamedGroup;
struct {
NamedGroup named_group_list<2..2^16-1>;
} NamedGroupList;
用“key_share”带上曲线对应的客户端公钥参数,
struct {
NamedGroup group;
opaque key_exchange<1..2^16-1>;
} KeyShareEntry;
用“signature_algorithms”带上签名算法。
除此以外,TLS1.3 还引入了“0-RTT”握手,用“pre_shared_key”和“early_data”扩展,在 TCP 连接后立即就建立安全连接发送加密消息,不过这需要有一些前提条件。在图1的抓包中没有这两项,这里提一下。
server hello
server hello 的格式如下所示:
struct {
ProtocolVersion legacy_version = 0x0303; /* TLS v1.2 */
Random random;
opaque legacy_session_id_echo<0..32>;
CipherSuite cipher_suite;
uint8 legacy_compression_method = 0;
Extension extensions<6..2^16-1>;
} ServerHello;
通过访问测试网站使用wireshark抓包,得到了server hello的包
小结
TLS 1.3 中优化握手:
client发送clientHello(extension)消息,extension中的support_groups中携带client支持的椭圆曲线的类型,并且在扩展key_share中计算出了相对应的公钥,一起发送给server.
server收到clientHello后会首先选择相应的椭圆曲线参数计算自身的公钥,从key_share扩展中提取相应的公钥作为密钥协商的参数,计算主密钥,并且把自身计算出的公钥放到serverHello的扩展key_share中,然后发送serverHello等消息给client,Client从key_share中取出公钥计算主密钥。
TLS1.2和TLS1.3 对比
1、密钥协商机制改变
TLS1.3借助扩展进行密钥交换,TLS1.3只需要三次握手交互,TLS1.2则需要四次握手。
首先看TLS1.2,它通过KeyExchange进行密钥协商,即ServerKeyExchange和ClientKeyExchange,那么密钥交换本身就需要一个交互来回,所以总共有四次握手交互。
再看TLS1.3,通过ClientHello和ServerHello的扩展进行密钥交换,那么就省去了1.2版本中KeyExchange的过程,也就省去了一次握手。
2、添加0-RTT模式,以某些安全属性为代价。
当client和server共享一个预共享密钥PSK(从外部获得或通过一个以前的握手获得)时,TLS 1.3允许client在第一个发送出去的消息的early data中携带数据,client使用这个PSK来认证server并加密early data。即在握手之前就有了PSK时,在第一次发送ClientHello时就可以发送加密数据,达到0-RTT数据传输的目的。
但是,0-RTT数据的安全性会降低(缺少前向安全)。
3、ServerHello之后的所有握手消息都被加密,引入了加密扩展EncryptedExtension。
4、全面使用ECC密码算法,删除不具有前向安全的密码套件。
5、其他还包括新的密钥派生函数,删除多余的报文消息(ChangeCipherSpec,但我抓包测试时还是有),以及其他算法的改进。
参考文章:
https://blog.csdn.net/qq_35324057/article/details/105366368
https://zhuanlan.zhihu.com/p/55911409
https://zhuanlan.zhihu.com/p/28850798
https://halfrost.com/tls1-3_start/
https://blog.csdn.net/qq_36058927/article/details/105918388
https://www.liaoxuefeng.com/wiki/1252599548343744/1304227905273889(DH算法入门案例)
测试地址:https://halfrost.com/tls1-3_start/ ↩︎