signal_protocol

Types

Whether this party initiates (Alice) or responds (Bob) in the DR handshake.

pub type DrRole {
  Alice
  Bob
}

Constructors

  • Alice
  • Bob

Opaque Double Ratchet session state (~5.3 KB).

pub type DrSession {
  DrSession(state: BitArray)
}

Constructors

  • DrSession(state: BitArray)

Identity key pair (Ed25519). public_key is 32 bytes; private_key is 64 bytes (libsodium’s secret-key encoding: seed ++ derived pub).

pub type IdentityKeyPair {
  IdentityKeyPair(public_key: BitArray, private_key: BitArray)
}

Constructors

  • IdentityKeyPair(public_key: BitArray, private_key: BitArray)

A parsed PreKeySignalMessage. inner_message is the serialized inner SignalMessage and is fed to dr_decrypt_message after the recipient has initialized their Double Ratchet from the recovered X3DH secret.

pub type PksmMessage {
  PksmMessage(
    registration_id: Int,
    base_key: BitArray,
    identity_key: BitArray,
    one_time_pre_key_id: option.Option(Int),
    signed_pre_key_id: Int,
    inner_message: BitArray,
  )
}

Constructors

  • PksmMessage(
      registration_id: Int,
      base_key: BitArray,
      identity_key: BitArray,
      one_time_pre_key_id: option.Option(Int),
      signed_pre_key_id: Int,
      inner_message: BitArray,
    )

One-time pre-key. private_key must be stored: the DH half is needed to complete X3DH on the responder side.

pub type PreKey {
  PreKey(
    key_id: Int,
    public_key: BitArray,
    private_key: BitArray,
  )
}

Constructors

  • PreKey(key_id: Int, public_key: BitArray, private_key: BitArray)

Pre-key bundle: the public material a party publishes so others can start sessions with them asynchronously. Serialized by encode_bundle to exactly what the NIF consumes:

identity_key(32) || signed_pre_key(32) || signature(64) [|| one_time_pre_key(32)]

Key ids and the registration id are not part of this binary – they travel in the PreKeySignalMessage of the first message.

pub type PreKeyBundle {
  PreKeyBundle(
    identity_key: BitArray,
    signed_pre_key: BitArray,
    signature: BitArray,
    one_time_pre_key: option.Option(BitArray),
  )
}

Constructors

  • PreKeyBundle(
      identity_key: BitArray,
      signed_pre_key: BitArray,
      signature: BitArray,
      one_time_pre_key: option.Option(BitArray),
    )

Information Alice must include in her first PreKeySignalMessage so Bob can identify which of his prekeys to consume and recover the X3DH shared secret.

pub type PreKeyInfo {
  PreKeyInfo(
    registration_id: Int,
    one_time_pre_key_id: option.Option(Int),
    signed_pre_key_id: Int,
    alice_ephemeral_pub: BitArray,
  )
}

Constructors

  • PreKeyInfo(
      registration_id: Int,
      one_time_pre_key_id: option.Option(Int),
      signed_pre_key_id: Int,
      alice_ephemeral_pub: BitArray,
    )

Signed pre-key: an X25519 keypair whose public half carries an Ed25519 signature made with the identity private key.

pub type SignedPreKey {
  SignedPreKey(
    key_id: Int,
    public_key: BitArray,
    private_key: BitArray,
    signature: BitArray,
  )
}

Constructors

  • SignedPreKey(
      key_id: Int,
      public_key: BitArray,
      private_key: BitArray,
      signature: BitArray,
    )

Values

pub fn decode_bundle(
  wire: BitArray,
) -> Result(PreKeyBundle, String)

Parses a pre-key bundle from its wire form. Accepts exactly 128 bytes (no one-time pre-key) or 160 bytes (with one).

pub fn dr_decrypt_message(
  session: DrSession,
  ciphertext: BitArray,
) -> Result(#(BitArray, DrSession), String)

Decrypt a Double Ratchet ciphertext. Returns the plaintext and the advanced session state.

pub fn dr_encrypt_message(
  session: DrSession,
  message: BitArray,
) -> Result(#(BitArray, DrSession), String)

Encrypt a message under the Double Ratchet. Returns the ciphertext and the advanced session state.

pub fn dr_encrypt_prekey(
  session: DrSession,
  message: BitArray,
  info: PreKeyInfo,
) -> Result(#(BitArray, DrSession), String)

Encrypt Alice’s first message and wrap it in a PreKeySignalMessage so Bob can recover the X3DH shared secret before decrypting.

pub fn encode_bundle(bundle: PreKeyBundle) -> BitArray

Serializes a pre-key bundle to the NIF wire form: identity_key(32) || signed_pre_key(32) || signature(64) [|| one_time_pre_key(32)]

pub fn generate_identity_key_pair() -> Result(
  IdentityKeyPair,
  String,
)

Generates a new identity key pair.

pub fn generate_pre_key(key_id: Int) -> Result(PreKey, String)

Generates a new pre-key with the given ID.

pub fn generate_signed_pre_key(
  identity_key: BitArray,
  key_id: Int,
) -> Result(SignedPreKey, String)

Generates a new signed pre-key with the given ID, signed by the identity key.

pub fn init_double_ratchet(
  shared_secret: BitArray,
  local_identity_pub: BitArray,
  remote_identity_pub: BitArray,
  self_identity_priv: BitArray,
  role: DrRole,
) -> Result(DrSession, String)

Initialize a Double Ratchet session.

shared_secret must be 96 bytes (typically the X3DH output). local_identity_pub and remote_identity_pub are 32-byte Ed25519 pubs; both are stored in DR state and folded into every message MAC (Signal spec: HMAC scope is sender_id || receiver_id || version || message).

  • Alice: self_identity_priv may be empty (she uses a fresh ephemeral for DH).
  • Bob: self_identity_priv is his 64-byte Ed25519 secret, used as the initial DH ratchet pair. Bob’s encrypt fails until he receives Alice’s first message.
pub fn pksm_decode(wire: BitArray) -> Result(PksmMessage, String)

Decode a PreKeySignalMessage wire envelope.

pub fn process_pre_key_bundle(
  local_identity_priv: BitArray,
  bundle: PreKeyBundle,
) -> Result(#(BitArray, BitArray), String)

Performs X3DH key agreement against a remote pre-key bundle.

Returns #(shared_secret, ephemeral_pub) where the 96-byte shared secret (32B DR root key || two 32B per-direction DR-HE header-key seeds) is fed straight into init_double_ratchet.

pub fn process_pre_key_bundle_bob(
  identity_priv: BitArray,
  signed_pre_key_priv: BitArray,
  one_time_pre_key_priv: BitArray,
  remote_identity_pub: BitArray,
  remote_ephemeral_pub: BitArray,
) -> Result(BitArray, String)

Bob’s side of X3DH. Returns the same 96-byte shared secret Alice derives from process_pre_key_bundle (32B root key || two 32B per-direction DR-HE header-key seeds).

Pass an empty BitArray for one_time_pre_key_priv when no OPK is being used.

Search Document