pub trait ActiveKeyExchange: Send + Sync {
// Required methods
fn complete(
self: Box<Self>,
peer_pub_key: &[u8],
) -> Result<SharedSecret, Error>;
fn pub_key(&self) -> &[u8] ⓘ;
fn group(&self) -> NamedGroup;
// Provided methods
fn complete_for_tls_version(
self: Box<Self>,
peer_pub_key: &[u8],
tls_version: &SupportedProtocolVersion,
) -> Result<SharedSecret, Error> { ... }
fn hybrid_component(&self) -> Option<(NamedGroup, &[u8])> { ... }
fn complete_hybrid_component(
self: Box<Self>,
_peer_pub_key: &[u8],
) -> Result<SharedSecret, Error> { ... }
fn ffdhe_group(&self) -> Option<FfdheGroup<'static>> { ... }
}展开描述
An in-progress key exchange originating 从 一个 SupportedKxGroup。
必需方法§
Sourcefn complete(self: Box<Self>, peer_pub_key: &[u8]) -> Result<SharedSecret, Error>
fn complete(self: Box<Self>, peer_pub_key: &[u8]) -> Result<SharedSecret, Error>
Completes the key exchange, given the peer’s 公钥.
This method must return an error if peer_pub_key is invalid: either
mis-encoded, 或 an invalid 公钥 (such as, but not limited 到, being
in 一个 small order subgroup)。
If the key exchange 算法 is FFDHE, 结果 must be left-padded with zeros,
as required by RFC 8446
(see complete_for_tls_version() 用于 more details)。
此 shared secret is returned as 一个 SharedSecret which can be constructed
从 一个 &[u8]。
This consumes 并 so terminates the ActiveKeyExchange。
Sourcefn pub_key(&self) -> &[u8] ⓘ
fn pub_key(&self) -> &[u8] ⓘ
返回正在使用的公钥
对于 ECDHE,所需的编码在 RFC8446 section 4.2.8.2。
对于 FFDHE,所需的编码在 RFC8446 section 4.2.8.1。
Sourcefn group(&self) -> NamedGroup
fn group(&self) -> NamedGroup
返回正在使用的组
提供方法§
Sourcefn complete_for_tls_version(
self: Box<Self>,
peer_pub_key: &[u8],
tls_version: &SupportedProtocolVersion,
) -> Result<SharedSecret, Error>
fn complete_for_tls_version( self: Box<Self>, peer_pub_key: &[u8], tls_version: &SupportedProtocolVersion, ) -> Result<SharedSecret, Error>
Completes the key exchange 用于 the given TLS version, given the peer’s 公钥.
Note that finite-field Diffie–Hellman key exchange has different requirements 用于 the derived shared secret in TLS 1.2 并 TLS 1.3 (ECDHE key exchange 是 same in TLS 1.2 并 TLS 1.3):
In TLS 1.2, the calculated secret is required 到 be stripped of leading zeros (RFC 5246)。
In TLS 1.3, the calculated secret is required 到 be padded with leading zeros 到 be the same byte-length as the group modulus (RFC 8446)。
此 default implementation of this method delegates 到 complete() assuming it is
implemented 用于 TLS 1.3 (i.e., 用于 FFDHE KX, removes padding as needed)。 Implementers of this trait
are encouraged 到 just implement complete() assuming TLS 1.3, 并 let 默认
implementation of this method handle TLS 1.2-specific requirements.
This method must return an error if peer_pub_key is invalid: either
mis-encoded, 或 an invalid 公钥 (such as, but not limited 到, being
in 一个 small order subgroup)。
此 shared secret is returned as 一个 SharedSecret which can be constructed
从 一个 &[u8]。
This consumes 并 so terminates the ActiveKeyExchange。
Sourcefn hybrid_component(&self) -> Option<(NamedGroup, &[u8])>
fn hybrid_component(&self) -> Option<(NamedGroup, &[u8])>
For hybrid key exchanges, returns the NamedGroup 并 key share
用于 the classical half of this key exchange.
There is no requirement 用于 一个 hybrid scheme (或 any other!) 到 implement
hybrid_component()。 It only enables an optimization; described below.
“Hybrid” means 一个 key exchange 算法 which is constructed 从 two (或 more) independent component algorithms. Usually one is post-quantum-secure, 并 the other is “classical”。 See https://datatracker.ietf.org/doc/draft-ietf-tls-hybrid-design/11/
§Background
Rustls always sends 一个 presumptive key share in its ClientHello, using
(absent any other information) the first item in CryptoProvider::kx_groups。
If the server accepts the client’s selection, it can complete the handshake
using that key share. If not, the server sends 一个 HelloRetryRequest instructing
the client 到 send 一个 different key share instead.
This request costs an extra round trip, 并 wastes the key exchange computation
(in SupportedKxGroup::start()) the client already did. We would
like 到 avoid those wastes if possible.
It is early days 用于 post-quantum-secure hybrid key exchange deployment.
This means (commonly) continuing 到 offer both the hybrid 并 classical
key exchanges, so the handshake can be completed without 一个 HelloRetryRequest
用于 servers that support the offered hybrid 或 classical schemes.
Implementing hybrid_component() enables two optimizations:
-
Sending both the hybrid 并 classical key shares in the
ClientHello。 -
Performing the classical key exchange setup only once. This is important because the classical key exchange setup is relatively expensive. This optimization is permitted 并 described in https://www.ietf.org/archive/id/draft-ietf-tls-hybrid-design-11.html#section-3.2
Both of these only happen if the classical 算法 appears separately in
the client’s CryptoProvider::kx_groups, 并 if the hybrid 算法 appears
first in that list.
§How it works
This function is only called by rustls 用于 clients. It is called when
constructing the initial ClientHello。 rustls follows these steps:
- If the return value is
None, nothing further happens. - If the given
NamedGroupdoes not appear inCryptoProvider::kx_groups, nothing further happens. - The given key share is added to the
ClientHello, after the hybrid entry.
Then, one of three things may happen when the server replies 到 the ClientHello:
- The server sends a
HelloRetryRequest. Everything is thrown away and we start again. - The server agrees to our hybrid key exchange: rustls calls
ActiveKeyExchange::complete()consumingself. - The server agrees to our classical key exchange: rustls calls
ActiveKeyExchange::complete_hybrid_component()which discards the hybrid key data, and completes just the classical key exchange.
Sourcefn complete_hybrid_component(
self: Box<Self>,
_peer_pub_key: &[u8],
) -> Result<SharedSecret, Error>
fn complete_hybrid_component( self: Box<Self>, _peer_pub_key: &[u8], ) -> Result<SharedSecret, Error>
Completes the classical component of the key exchange, given the peer’s 公钥.
This is only called if hybrid_component returns Some(_)。
This method must return an error if peer_pub_key is invalid: either
mis-encoded, 或 an invalid 公钥 (such as, but not limited 到, being
in 一个 small order subgroup)。
此 shared secret is returned as 一个 SharedSecret which can be constructed
从 一个 &[u8]。
,请参见 documentation on Self::hybrid_component() 用于 explanation.
Sourcefn ffdhe_group(&self) -> Option<FfdheGroup<'static>>
fn ffdhe_group(&self) -> Option<FfdheGroup<'static>>
FFDHE group the ActiveKeyExchange is operating in.
Return None if this group is not 一个 FFDHE one.
此 default implementation calls FfdheGroup::from_named_group: 此函数
is extremely linker-unfriendly so it is recommended all key exchange implementers
provide 此函数.
rustls::ffdhe_groups contains suitable values 到 return 从 this,
用于 example rustls::ffdhe_groups::FFDHE2048。