ExWapp.Signal.Encryption (ExWapp v0.1.2)

Copy Markdown View Source

High-level Signal encryption/decryption for WhatsApp messages.

Handles the full flow of:

  1. Fetching prekeys for new recipients
  2. Creating/using Signal sessions
  3. Encrypting outgoing messages
  4. Decrypting incoming messages

Summary

Functions

Decrypts an incoming message without GenServer calls (safe inside Session handlers).

Encrypts a message for a recipient.

Encrypts a message for a recipient (synchronous version - no GenServer calls).

Pads plaintext according to WhatsApp's padding scheme.

Unpads a decrypted message.

Functions

decrypt_from_sender(session, jid, ciphertext, enc_type)

@spec decrypt_from_sender(pid(), String.t(), binary(), atom()) ::
  {:ok, binary()} | {:error, term()}

Decrypts an incoming message.

decrypt_from_sender_sync(store, signal_sessions, jid, ciphertext, enc_type)

@spec decrypt_from_sender_sync(
  any(),
  any(),
  String.t(),
  binary(),
  atom() | String.t()
) ::
  {:ok, binary(), any()} | {:error, term()}

Decrypts an incoming message without GenServer calls (safe inside Session handlers).

encrypt_for_recipient(session, jid, plaintext)

@spec encrypt_for_recipient(pid(), String.t(), binary()) ::
  {:ok, binary(), :prekey | :whisper} | {:error, term()}

Encrypts a message for a recipient.

Will fetch prekeys and create a session if needed. Returns the encrypted payload and whether it's a prekey message.

encrypt_for_recipient_sync(store, signal_sessions, jid, plaintext, remote_bundle \\ %{})

@spec encrypt_for_recipient_sync(any(), any(), String.t(), binary(), map()) ::
  {:ok, binary(), :prekey | :whisper, any()} | {:error, term()}

Encrypts a message for a recipient (synchronous version - no GenServer calls).

This avoids deadlock when called from within a GenServer handle_call.

pad_message(plaintext)

@spec pad_message(binary()) :: binary()

Pads plaintext according to WhatsApp's padding scheme.

WhatsApp uses PKCS7-like padding with random suffix to obscure message length.

unpad_message(padded)

@spec unpad_message(binary()) :: binary()

Unpads a decrypted message.

unpad_message(padded, version)

@spec unpad_message(binary(), integer() | String.t() | nil) :: binary()