Amarula.Protocol.Signal.SessionCipher (amarula v0.1.0)

View Source

Signal v3 Double-Ratchet decryption, ported from node_modules/libsignal/src/session_cipher.js (decrypt path only).

Operates on a SessionRecord plus a session store (for our identity / prekeys). Threads the record through and returns the updated record so the caller can persist the ratchet advance.

v3 message framing: first byte is (VERSION<<4)|VERSION = 0x33. WhisperMessage = [0x33][protobuf][8-byte MAC] PreKeyWhisperMessage = [0x33][PreKeyWhisperMessage protobuf] whose .message field is itself a full (version-tupled, MAC'd) WhisperMessage.

Summary

Functions

Decrypt a PreKeyWhisperMessage. Builds the responder session from the prekey message if needed, then decrypts the embedded WhisperMessage.

Decrypt a WhisperMessage, trying each session in the record until one works.

Encrypt plaintext for the open session in record, ported from session_cipher.js encrypt.

Functions

decrypt_pre_key_whisper_message(record, arg, store)

@spec decrypt_pre_key_whisper_message(
  Amarula.Protocol.Signal.SessionRecord.t() | nil,
  binary(),
  map()
) ::
  {:ok, binary(), Amarula.Protocol.Signal.SessionRecord.t(),
   non_neg_integer() | nil}

Decrypt a PreKeyWhisperMessage. Builds the responder session from the prekey message if needed, then decrypts the embedded WhisperMessage.

Returns {:ok, plaintext, updated_record, used_pre_key_id}.

decrypt_whisper_message(record, data, store)

@spec decrypt_whisper_message(
  Amarula.Protocol.Signal.SessionRecord.t(),
  binary(),
  map()
) ::
  {:ok, binary(), Amarula.Protocol.Signal.SessionRecord.t()}

Decrypt a WhisperMessage, trying each session in the record until one works.

Returns {:ok, plaintext, updated_record}.

encrypt(record, plaintext, store)

Encrypt plaintext for the open session in record, ported from session_cipher.js encrypt.

Returns {:ok, type, body, updated_record} where type is :pkmsg (the session still has a pending prekey, so we wrap the WhisperMessage in a PreKeyWhisperMessage) or :msg. body is the full wire payload.