密码学提供者
rustls 的握手状态机、记录层、密钥日程都不直接调用任何密码学库。它们拿到的是一个 Arc<CryptoProvider>:五个公开字段,分别是密码套件列表、密钥交换组列表、证书和握手签名的校验算法表、随机数源、私钥加载器。0.23.46 自带两个实现,crypto::ring::default_provider() 和 crypto::aws_lc_rs::default_provider(),由同名的 crate feature 打开;默认 feature 只开 aws-lc-rs。这一部分讲这个结构怎么被消费、默认值从哪里来,以及两个内置实现在套件和密钥交换组上的差异。
代码分布(tag v/0.23.46,.rs 行数,含模块内的单元测试):rustls/src/crypto/ 顶层 2231 行,是 trait 和公共胶水;crypto/ring/ 2967 行;crypto/aws_lc_rs/ 4263 行,其中 hpke.rs(ECH 用)1216 行、后量子的 pq/ 375 行。aws-lc-rs 的 API 大体照着 ring 设计,所以 aws_lc_rs/mod.rs 用 #[path = "../ring/kx.rs"] 直接复用了 ring 目录下的 hash.rs、hmac.rs、kx.rs、quic.rs,两边的 X25519、P-256、P-384 是同一份 rustls 代码,只是 ring_like 指向不同的库。
- CryptoProvider:五个字段各被谁读;
ClientConfig::builder()背后的进程级默认值,ring和aws_lc_rs同时打开时它直接 panic(含 panic 原文和复现);builder_with_provider;照着provider-example看一个自定义 provider 要实现哪些 trait。 - 套件与密钥交换:两个 provider 的默认套件顺序和密钥交换组顺序;服务端按客户端的顺序选组;后量子混合组
X25519MLKEM768在默认 feature 下排第一,ClientHello 从 246 字节涨到 1466 字节;ring 不支持它;fipsfeature 改了哪些列表;两个 provider 的握手耗时。
flowchart TB feat["crate feature"] --> dp["default_provider"] dp --> pd["进程级默认"] dp --> bwp["builder_with_provider"] pd --> cb["ClientConfig builder"] bwp --> cfg["ClientConfig 与 ServerConfig"] cb --> cfg cfg --> hs["握手状态机"] hs --> kx["kx_groups"] hs --> cs["cipher_suites"] hs --> rnd["secure_random"] cfg --> ver["签名校验算法"] cfg --> kp["key_provider"]
provider 在构建配置时就定下来,之后每条连接都从 config.provider 读。密码套件里装着的哈希、HKDF 和 AEAD 实现怎么在密钥日程和记录层里被调用,分别见密钥日程和加密与序列号;签名校验算法表交给 rustls-webpki 之后的事,见服务器证书。