Amarula.Protocol.Messages.PollCrypto (amarula v0.1.0)

View Source

Decrypt poll votes, ported from Baileys decryptPollVote (src/Utils/process-message.ts).

A vote's encPayload/encIv are AES-256-GCM encrypted under a key derived from the poll's message_secret and the ids of the poll, its creator, and the voter:

sign   = poll_msg_id ++ poll_creator_jid ++ voter_jid ++ "Poll Vote" ++ <<1>>
key0   = HMAC-SHA256(key=message_secret, data=<<0::256>>)   # 32 zero bytes
dec_key= HMAC-SHA256(key=key0, data=sign)
aad    = "<poll_msg_id>\0<voter_jid>"
plain  = AES-256-GCM-decrypt(encPayload, key=dec_key, iv=encIv, aad)
        Proto.Message.PollVoteMessage (selectedOptions = SHA-256 option hashes)

GCM tag is the trailing 16 bytes of encPayload.

Summary

Functions

Decrypt a poll vote (enc = %Proto.Message.PollEncValue{} or a map with :encPayload/:encIv). Returns {:ok, %PollVoteMessage{}} (its selectedOptions are SHA-256 hashes of the chosen option names — match against Poll.tally/3), or {:error, reason}.

Types

context()

@type context() :: %{
  message_secret: binary(),
  poll_msg_id: String.t(),
  poll_creator_jid: String.t(),
  voter_jid: String.t()
}

Functions

decrypt_vote(arg1, ctx)

@spec decrypt_vote(map(), context()) :: {:ok, struct()} | {:error, term()}

Decrypt a poll vote (enc = %Proto.Message.PollEncValue{} or a map with :encPayload/:encIv). Returns {:ok, %PollVoteMessage{}} (its selectedOptions are SHA-256 hashes of the chosen option names — match against Poll.tally/3), or {:error, reason}.