SignalProtocol (libsignal_protocol v0.3.0)
View SourceThin Elixir facade over the :libsignal_protocol_nif Erlang NIF.
All functions return {:ok, term} | {:error, term} as the NIF does. A
missing NIF raises UndefinedFunctionError at the call site -- callers
must ensure the NIF is built and on the load path before use.
Summary
Functions
Encrypt Alice's first message and wrap it in a PreKeySignalMessage envelope so Bob can recover the X3DH shared secret before decrypting.
Generates an X25519 pre-key. Returns {key_id, public, private}; keep the
private half to run process_pre_key_bundle_bob/5 against the published
pre-key.
Generates an X25519 signed pre-key. Returns
{key_id, public, private, signature} -- the signature is Ed25519 over the
public key under identity_key.
Optional probe that the NIF is loaded. libsodium is initialised when the
NIF library loads, so no per-VM setup call is required; this raises
UndefinedFunctionError if the NIF is missing and returns :ok otherwise.
Decode a PreKeySignalMessage wire envelope produced by dr_encrypt_prekey/3.
Performs X3DH key agreement against a remote pre-key bundle.
Bob's side of X3DH. Recovers the same 96-byte shared secret Alice derived
via process_pre_key_bundle/2 (32B DR root key || two 32B per-direction
DR-HE header-key seeds).
Functions
@spec dr_encrypt_prekey( binary(), binary(), {non_neg_integer(), non_neg_integer() | nil, non_neg_integer(), binary()} ) :: {:ok, {binary(), binary()}} | {:error, term()}
Encrypt Alice's first message and wrap it in a PreKeySignalMessage envelope so Bob can recover the X3DH shared secret before decrypting.
pre_key_info is a 4-tuple {registration_id, one_time_pre_key_id_or_nil, signed_pre_key_id, alice_x3dh_ephemeral_pub}. The ephemeral pub is the
32-byte X25519 key returned by process_pre_key_bundle/2.
Returns {:ok, {pksm_wire_bytes, new_session}} on success.
@spec generate_pre_key(non_neg_integer()) :: {:ok, {non_neg_integer(), binary(), binary()}} | {:error, atom()}
Generates an X25519 pre-key. Returns {key_id, public, private}; keep the
private half to run process_pre_key_bundle_bob/5 against the published
pre-key.
@spec generate_signed_pre_key(binary(), non_neg_integer()) :: {:ok, {non_neg_integer(), binary(), binary(), binary()}} | {:error, atom()}
Generates an X25519 signed pre-key. Returns
{key_id, public, private, signature} -- the signature is Ed25519 over the
public key under identity_key.
@spec init() :: :ok
Optional probe that the NIF is loaded. libsodium is initialised when the
NIF library loads, so no per-VM setup call is required; this raises
UndefinedFunctionError if the NIF is missing and returns :ok otherwise.
@spec pksm_decode(binary()) :: {:ok, {non_neg_integer(), binary(), binary(), non_neg_integer() | nil, non_neg_integer(), binary()}} | {:error, term()}
Decode a PreKeySignalMessage wire envelope produced by dr_encrypt_prekey/3.
Returns
{:ok, {registration_id, base_key, identity_key, one_time_pre_key_id_or_nil, signed_pre_key_id, inner_dr_message}}
on success, or {:error, :malformed_message} on malformed input.
Bob's typical flow:
pksm_decode/1to extract fields and the inner DR message.- Look up his SPK + OPK private keys by id.
process_pre_key_bundle_bob/5to derive the same SK Alice has.init_double_ratchet/5(as Bob,is_alice = 0).dr_decrypt_message/2on the inner DR message.
Performs X3DH key agreement against a remote pre-key bundle.
The bundle is a binary in the format expected by the C NIF:
remote_identity_pub(32) ++ signed_prekey_pub(32) ++ signature(64)
with an optional trailing one_time_prekey(32). The signature is
Ed25519 (crypto_sign_detached) over signed_prekey_pub under the
remote identity key.
Returns {:ok, {shared_secret(96), ephemeral_pub(32)}} on success.
The 96-byte shared secret is root(32) || seed_a(32) || seed_b(32) and is
fed directly into init_double_ratchet/5.
@spec process_pre_key_bundle_bob(binary(), binary(), binary(), binary(), binary()) :: {:ok, binary()} | {:error, term()}
Bob's side of X3DH. Recovers the same 96-byte shared secret Alice derived
via process_pre_key_bundle/2 (32B DR root key || two 32B per-direction
DR-HE header-key seeds).
Inputs:
identity_priv- Bob's 64-byte Ed25519 identity private key.signed_pre_key_priv- 32-byte X25519 private key matching the SPK Alice consumed from Bob's bundle.one_time_pre_key_priv- 32-byte X25519 private key matching the OPK Alice consumed, or<<>>if no OPK was used.remote_identity_pub- Alice's 32-byte Ed25519 identity public key, extracted from the PreKeySignalMessage.remote_ephemeral_pub- Alice's 32-byte X25519 ephemeral public key, also extracted from the PreKeySignalMessage (thebase_keyfield).