5 个版本 (3 个重大更新)

0.4.0 2022年11月27日
0.3.0 2021年7月25日
0.2.1 2021年7月3日
0.2.0 2021年5月17日
0.1.0 2021年5月10日

#1254 in 密码学

MIT/Apache

40KB
742

quinn quic 实现的 Noise 加密库

握手模式

使用可选的 psk 与 IK 握手模式相结合。psk 允许使用预共享密钥构建私有 P2P 网络。在 P2P 环境中,静态密钥是已知的,IK 握手允许 0-rtt 加密。在许多 P2P 网络中,身份隐藏不是问题。

IKpsk1:
    <- s
    ...
    -> e, es, s, ss, psk  || client transport parameters || 0rtt-data
    <- e, ee, se          || server transport parameters || 1rtt-data

身份和密钥交换

签名密钥在 P2P 网络中用作身份。由于 IK 握手需要提前知道握手密钥,因此签名密钥被用于密钥交换。使用与 libsodium 实现的相同算法,ed25519 密钥被转换为 x25519 密钥。

注意:虽然重用密钥进行签名和 Diffie-Hellman 可能是可行的,但强烈建议不要将密钥用于其他协议,如 VRF 或门限签名。

加密算法

使用 xoodyak(NIST 轻量级加密竞赛的决赛选手),执行以下操作以推导 0rtt-key、1rtt-key 和 next-1rtt-key。为了快速认证加密,使用 chacha8poly1305 密文。

会话

会话转储初始化为协议标识符。将客户端临时密钥和服务器静态公钥以及 es dh 吸收到会话转储中。从该会话转储中提取会话标识符,该标识符用于根据 xoodyak 论文第 3.3 节初始化密钥会话转储,以使用公共密钥进行认证加密。将加密的客户端静态公钥、ss dh 和 psk(如果没有提供,默认为 [0; 32])添加到会话转储中。然后将用于标识应用程序协议的加密 ALPN 字符串和根据 quic 规范定义的加密客户端传输参数添加到转储中。常见的 ALPN 字符串是 h3(用于 Web)或 libp2p(用于 libp2p 应用程序)。最后,从加密的密钥帧和 0-rtt 密钥中提取认证标签。

初始数据包的加密帧包含协议标识符、客户端临时公钥、加密的客户端静态公钥、加密的 ALPN 标识符、加密的客户端传输参数和认证标签。在初始数据包之后,可以使用提取的 0-rtt 密钥发送 0-rtt 数据包,而不必等待服务器响应。

Initial:
  | Cyclist({}, {}, {})
p | Absorb("Noise_IKpsk1_Edx25519_ChaCha8Poly")
p | Absorb(e)
  | Absorb(s)
  | Absorb(es)
  | key = Squeeze(32)
  | Cyclist(key, {}, {})
c | Encrypt(s)
  | Absorb(ss)
  | Absorb(psk)
c | Encrypt(alpn)
c | Encrypt(client_transport_parameters)
t | Squeeze(16)
  | initiator-0rtt-key = SqueezeKey(32)
  | responder-0rtt-key = SqueezeKey(32)

在接收到初始数据包后,服务器生成一个握手数据包,包含加密的服务器临时公钥和加密的服务器传输参数。在握手数据包之后,可以发送1-rtt数据包。一旦所有0-rtt数据包都被确认,则丢弃密钥。

Handshake:
c | Encrypt(e)
  | Absorb(ee)
  | Absorb(se)
c | Encrypt(server_transport_parameters)
t | Squeeze(16)
  | initiator-1rtt-key = SqueezeKey(32)
  | responder-1rtt-key = SqueezeKey(32)

在传输会话期间,可能需要轮换1-rtt密钥。这发生在接近发送u64::MAX个数据包或连接强制要求时。有关详细信息,请参阅QUIC规范。

Key rotation:
  | Ratchet()
  | initiator-next-1rtt-key = SqueezeKey(32)
  | responder-next-1rtt-key = SqueezeKey(32)

QUIC版本

quinn-noise保留的版本是0xf0f0f2f[0-f] [0]。目前只有0xf0f0f2f0是有效的quinn-noise版本。

头部保护

头部保护/混淆旨在防止中间盒子读取头部。由于头部作为关联数据传递给加密算法,因此修改是不可能的。设想在未来的QUIC版本中,如果头部发生变化,中间盒子可能会丢弃数据包,因为它们无法读取头部。但是头部保护/混淆只是使其更难,而不是不可能。由于对它是否达到目的存在疑问,因此决定不应用头部混淆。

重试机制

重试机制与quic-tls规范中指定的机制相同。

许可证

MIT OR Apache-2.0

依赖项

~13MB
~330K SLoC