SSL.Fingerprint (ex_ssl v0.16.7)

Copy Markdown View Source

JA3 and JA4 observation of exact, naked ClientHello handshake bytes.

Transport is explicitly :tcp or :quic; it is never inferred from ALPN. Unknown IDs and original ordering are retained in observation. Only the analytical projections omit GREASE and sort JA4 fields. Observation does not validate a profile's negotiability or authenticate a peer. ECH bytes, if present, describe the visible outer hello only, never an encrypted inner hello.

new/1 and feed/2 observe one fragmented ClientHello, bounded to 65,535 body bytes. Completion emits one result; trailing input is rejected. Empty input and terminal empty feeds emit nothing. Errors discard the observer; start a new observer for another ClientHello.

Summary

Types

result()

@type result() :: %{
  transport: :tcp | :quic,
  source: :visible_client_hello,
  observation: map(),
  ja3: %{raw: binary(), hash: binary()},
  ja4: %{
    prefix: binary(),
    cipher_raw: binary(),
    extension_raw: binary(),
    raw: binary(),
    hash: binary()
  }
}

t()

@opaque t()

Functions

client_hello(bytes, transport)

@spec client_hello(binary(), :tcp | :quic) :: {:ok, result()} | {:error, term()}

feed(state, bytes)

@spec feed(t(), binary()) :: {:ok, t(), [result()]} | {:error, term()}

new(transport)

@spec new(:tcp | :quic) :: {:ok, t()} | {:error, :invalid_transport}