BaileysEx.Protocol.Noise (baileys_ex v0.1.0-alpha.9)

Copy Markdown View Source

WhatsApp Noise handshake and transport state aligned with the Baileys reference.

This module mirrors dev/reference/Baileys-master/src/Utils/noise-handler.ts: the WhatsApp-specific protobuf handshake, certificate validation, handshake hash mixing, and transport frame counters live in Elixir, while the expensive crypto primitives stay native via :crypto and narrow NIF helpers.

Summary

Functions

Build the client finish HandshakeMessage.

Encode the client hello HandshakeMessage.

Decode one or more inbound length-prefixed frames from a buffer chunk.

Return the trusted WhatsApp Noise certificate anchor used by default.

Encode an outbound length-prefixed frame.

Transition the Noise state into transport mode after the framed handshake has been sent.

Create a new initiator-side WhatsApp Noise state.

Return WhatsApp's Noise header.

Process a server hello HandshakeMessage and validate its certificate chain.

True once the handshake has transitioned into transport mode.

Types

cert_details()

@type cert_details() :: %{serial: non_neg_integer(), public_key: binary()}

key_pair()

@type key_pair() :: BaileysEx.Crypto.key_pair()

t()

@type t() :: %BaileysEx.Protocol.Noise{
  counter: non_neg_integer(),
  dec_key: binary(),
  enc_key: binary(),
  ephemeral_key_pair: key_pair(),
  hash: binary(),
  in_bytes: binary(),
  intro_header: binary(),
  pending_static: binary() | nil,
  salt: binary(),
  sent_intro?: boolean(),
  transport: BaileysEx.Protocol.Noise.TransportState.t() | nil,
  trusted_cert: cert_details()
}

Functions

client_finish(state, client_payload)

@spec client_finish(t(), binary()) :: {:ok, {t(), binary()}} | {:error, term()}

Build the client finish HandshakeMessage.

Transport mode does not begin until finish_init/1 is called after the framed handshake message has been sent on the wire.

client_hello(state)

@spec client_hello(t()) :: {:ok, {t(), binary()}}

Encode the client hello HandshakeMessage.

decode_frames(state, new_data)

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

Decode one or more inbound length-prefixed frames from a buffer chunk.

Returns all complete frame payloads in order and keeps any partial trailing bytes buffered in the returned state.

default_trusted_cert()

@spec default_trusted_cert() :: cert_details()

Return the trusted WhatsApp Noise certificate anchor used by default.

encode_frame(state, data)

@spec encode_frame(t(), binary()) :: {:ok, {t(), binary()}}

Encode an outbound length-prefixed frame.

On the first transport frame, this prepends WhatsApp's intro header exactly as Baileys does. Payload encryption only happens after the handshake is complete.

finish_init(state)

@spec finish_init(t()) :: {:ok, t()} | {:error, term()}

Transition the Noise state into transport mode after the framed handshake has been sent.

new(opts \\ [])

@spec new(keyword()) :: {:ok, t()}

Create a new initiator-side WhatsApp Noise state.

Options:

  • :ephemeral_key_pair - injected X25519 key pair for deterministic tests
  • :routing_info - optional WhatsApp routing info for the intro header
  • :header - custom Noise header, defaults to WhatsApp's <<87, 65, 6, 3>>
  • :trusted_cert - trusted certificate authority details for validation

noise_header()

@spec noise_header() :: binary()

Return WhatsApp's Noise header.

process_server_hello(state, server_hello_binary, noise_key_pair)

@spec process_server_hello(t(), binary(), key_pair()) :: {:ok, t()} | {:error, term()}

Process a server hello HandshakeMessage and validate its certificate chain.

The noise_key_pair is the client's long-term static Noise key pair that will be sent in the subsequent client finish message.

transport_ready?(noise)

@spec transport_ready?(t()) :: boolean()

True once the handshake has transitioned into transport mode.