seleniumbase_rs_codec::client_hello parses a captured TLS ClientHello
incrementally, from the record header onwards, without trusting its lengths.
ClientHello::needed_len tells a capture loop how many bytes make up the first
handshake message while it is still arriving, and ClientHello::parse decodes the
whole message, which may span several TLS records. Every length is checked against
the bytes that remain, so hostile or truncated input returns a
ClientHelloError and never panics. GREASE values (RFC 8701) are kept as
received; the JA3, JA4 and spec builders strip them.
ClientHello#
struct
A parsed ClientHello, with the typed fields the fingerprints read. Lists keep
GREASE values and wire order. When an extension occurs twice, the typed field
holds the value of its first occurrence; extensions keeps both.
Version in the record header of the first record.
The client_version field of the handshake message (771 for TLS 1.2 and 1.3 clients).
The 32 random bytes.
The legacy session id (at most 32 bytes).
Cipher suites in wire order.
Compression methods in wire order.
Every extension in wire order, with its raw body.
The first host name of server_name.
ALPN protocol names in wire order.
The two lists as sent.
ec_point_formats as sent.
signature_algorithms as sent.
psk_key_exchange_modes as sent.
compress_certificate algorithms as sent.
Protocols of application_settings, on either codepoint.
The value of record_size_limit.
delegated_credential signature schemes as sent.
ClientHello::needed_len#
method
How many bytes the first ClientHello occupies, as far as prefix shows.
Returns the byte length of all records that carry the message once the headers
seen so far make it known (it may exceed prefix.len()), and None while more
bytes are needed. A capture loop reads until the answer is at most the bytes it
holds. Each call costs at most MAX_HELLO_RECORDS record headers, however the
prefix arrived.
Fails as soon as the bytes cannot be a ClientHello: NotHandshake,
NotClientHello, Length for a bad record length, TooLarge and
TooManyRecords.
ClientHello::parse#
method
Parses the first ClientHello in records, reassembled across handshake records.
Bytes after the message (further records) are ignored. Returns
ClientHelloError::Truncated when the message is incomplete and another variant
when it is malformed; nothing in the input can make it panic.
ClientHello::extension, has_extension, extension_ids, has_grease#
method
The first extension with this id; whether the hello carries one; the extension ids in wire order, GREASE included; and whether a GREASE value appears in the ciphers, extensions, versions, groups or key shares.
Extension#
struct
One extension as it arrived.
The extension type.
The body, without the id and length prefix.
ClientHelloError#
enum
Why a byte stream is not a usable ClientHello.
without_grease#
fn
Returns values without its GREASE entries, in the same order.
is_grease#
fn
Whether id is a GREASE value (RFC 8701): both bytes are equal and the low
nibble is 0xA. Defined in ids and re-exported here.
Constants#
constThe largest ClientHello handshake message, header included, that the parser
accepts; and the most TLS records one ClientHello may span. A 64 KiB message
fits four full records, so the record limit allows any fragmentation a client
stack would use, and no peer can make the readers walk more than that many record
headers per call.
ext_id#
mod
The extension ids the parser decodes, plus the ones the spec layer reasons
about. ALPS_OLD and ALPS are application_settings on its old and new
codepoint; TRUST_ANCHORS is the extension that BoringSSL as vendored by btls
0.5.6 cannot emit.