Skip to main content
Experimental Crate: codec

seleniumbase_rs_codec::tls_spec holds the TLS specification a client should reproduce. A TlsSpec is a whole TLS profile as plain data: the ids a ClientHello carries and the content of the extensions that have any. TlsSpec::from_client_hello records it from a parsed hello. A caller can layer a custom JA3, JA4 (as JA4_r or JA4_ro) or peetprint over a base spec; each overlay replaces what its fingerprint carries, takes the rest from the base, runs check_reproducible, and recomputes its own fingerprint to compare with the input, so an accepted input reproduces its own fingerprint and a spec BoringSSL cannot emit is refused before any client exists.

The lists never hold GREASE: the grease flag says BoringSSL adds its GREASE values. The per-extension flags of the design plan (ocsp_stapling, sct, session_ticket, renegotiation, ech_grease) are methods that read the extension list, so they cannot disagree with it. The table of what is refused is in Wire formats.

The measured spec carries the trust_anchors extension and the ML-DSA signature schemes, which BoringSSL cannot send, so its own check_reproducible fails; the spec without its known gaps passes.

TlsSpec#

struct

A whole TLS profile: what a ClientHello must carry for a client to look like this one.

legacy_versionu16#

The handshake client_version (771).

cipher_suitesVec<u16>#

Cipher suites in wire order, without GREASE.

extensionsVec<u16>#

Extension ids in wire order, without GREASE; SNI and ALPN are listed when sent.

permute_extensionsbool#

Whether the client shuffles the extension order on every connection, as Chrome does (the measured Chrome 155 spec has true).

Default: "false"

greasebool#

Whether GREASE values are added: a cipher, a group, a version and two extensions.

Default: "false"

supported_groupsVec<u16>#

Supported groups in preference order.

key_share_groupsVec<u16>#

Groups a key share is sent for, in order.

point_formatsVec<u8>#

EC point formats: [0] when the extension is sent.

signature_algorithmsVec<u16>#

Signature algorithms in preference order.

alpnVec<String>#

ALPN protocol names in preference order.

alpsOption<Alps>#

The application_settings extension, when sent.

delegated_credentialsVec<u16>#

delegated_credential signature schemes.

supported_versionsVec<u16>#

supported_versions, highest first, without GREASE.

psk_modesVec<u8>#

psk_key_exchange_modes.

cert_compressionVec<u16>#

compress_certificate algorithms.

record_size_limitOption<u16>#

record_size_limit.

TlsSpec::from_client_hello, with_observed_order#

method

from_client_hello records the profile a parsed hello shows; GREASE becomes the grease flag, and the extension order is taken as observed (permute_extensions is false). with_observed_order compares a second hello of the same client: a changed extension order sets permute_extensions. It returns SpecError::HellosDiffer when the cipher suites or the set of extensions differ.

Extension flags#

method

Whether the spec sends the extension with this id, status_request (OCSP stapling), signed_certificate_timestamp, session_ticket, renegotiation_info, encrypted_client_hello (as GREASE ECH) or extended_master_secret.

Fingerprints of a spec#

method

The JA3 this spec produces (extensions in the listed order); what JA4 reads from it; its JA4; the unhashed JA4 in the given order; and its peetprint, which with grease carries the GREASE tokens BoringSSL adds (one each in versions, groups and ciphers, two in the extensions). See JA3 and JA4.

TlsSpec::without_known_gaps#

method

Removes the listed known gaps: TrustAnchorsExtension drops extension 0xCA34; MlDsaSignatureAlgorithms drops 0x0904 to 0x0906 from the signature algorithms and the delegated credentials.

TlsSpec::check_reproducible#

method

Checks the spec against what BoringSSL can emit (plan section 3.8) and returns the first SpecError found, checking in this order: the version, the cipher suites, the extensions, the groups, the point formats, the signature algorithms, then extension content.

Overlays#

method
with_ja3method#

Replaces the version, ciphers, extensions, groups and point formats with a custom JA3. Everything JA3 does not carry (signature algorithms, ALPN, key shares, versions and the other extension bodies) comes from self; content of extensions the JA3 omits is dropped. Extension permutation is turned off, so the JA3 on the wire is exact.

with_signature_algorithmsmethod#

Replaces the signature algorithms. UnsupportedSigalg for a scheme BoringSSL cannot send, ExtensionContent when the list is empty or the extension is not sent.

with_ja4_rawmethod#

Replaces the ciphers, extensions and signature algorithms with a JA4_r (Ja4Order::Sorted) or JA4_ro (Ja4Order::Original). The sorted form carries no order: the ids keep the order they have in self, new ones follow in ascending order, and permute_extensions is kept. The original-order form pins ciphers and extensions and turns permutation off. The TLS version and the first ALPN name come from the a section; groups and the other bodies come from self. Ja4Mismatch when the result would not reproduce raw.

with_peetprintmethod#

Replaces the ciphers, extensions, groups, versions, ALPN, signature algorithms, PSK modes and certificate compression with a custom peetprint. The extension field is sorted, so extension order comes from self. GREASE tokens set the grease flag, and a layout BoringSSL would not produce is refused. PeetprintMismatch when the result would not reproduce peet.

Alps#

struct

The application_settings extension: the protocols it announces (such as h2) and whether it uses the new codepoint (0x44CD) rather than the old one (0x4469).

KnownGap#

enum

A known difference between a measured browser hello and what BoringSSL can send. The measured file records them in provenance.known_gaps.

KnownGapenum#

SpecError#

enum

Why a spec cannot be reproduced, or an overlay cannot be applied.

SpecErrorenum#