Signal struct provides direct access to Signal protocol operations including message encryption/decryption for both 1:1 and group conversations, session management, and participant node creation.
Access
Access Signal protocol operations through the client:Methods
encrypt_message
Encrypt plaintext for a single recipient using the Signal protocol.jid- Recipient JID. PN JIDs are resolved to LID andHostedJIDs toHostedLidwhen a mapping exists, matching WA Web’sSignalAddress.toString()and the internal send path. See Signal address resolution.plaintext- Raw bytes to encrypt. The caller is responsible for padding if needed.
(EncType, Vec<u8>)- The encryption type and ciphertext bytes
EncType::PreKeyMessage- Session was just established (includes prekey bundle)EncType::Message- Standard encrypted message
decrypt_message
Decrypt a Signal protocol message from a sender.jid- Sender JID. PN JIDs are resolved to LID andHostedJIDs toHostedLidwhen a mapping exists.enc_type- The encryption type (EncType::PreKeyMessageorEncType::Message)ciphertext- Encrypted bytes to decrypt
Vec<u8>- Raw padded plaintext. UseMessageUtils::unpad_message_refwith the stanza’svattribute if WhatsApp message unpadding is needed.
Passing
EncType::SenderKey returns an error — use decrypt_group_message for sender-key encrypted group messages.encrypt_group_message
Encrypt plaintext for a group using sender keys.group_jid- Group JID (@g.us)plaintext- Raw bytes to encrypt
(Option<Vec<u8>>, Vec<u8>)- A tuple of optional SKDM bytes and ciphertext bytes. The SKDM isSomeonly when a new sender key was created (first encrypt for this group or after key rotation). You must distribute the SKDM to all group participants when present.
decrypt_group_message
Decrypt a group (sender-key) message.group_jid- Group JIDsender_jid- Sender’s JID within the groupciphertext- Encrypted bytes to decrypt
Vec<u8>- Raw padded plaintext. UseMessageUtils::unpad_message_refwith the stanza’svattribute if WhatsApp message unpadding is needed.
validate_session
Check whether a Signal session exists for a JID.jid- JID to check. PN JIDs are resolved to LID andHostedJIDs toHostedLidwhen a mapping exists.
bool-trueif a session exists,falseotherwise
delete_sessions
Delete Signal sessions and identity keys for the given JIDs.jids- JIDs whose sessions and identity keys should be deleted. PN JIDs are resolved to LID andHostedJIDs toHostedLidwhen a mapping exists.
deleteRemoteSession behavior, which removes both the session and identity key as a paired operation. Changes are flushed to the persistent backend before returning.
Example:
create_participant_nodes
Create encrypted participant<to> nodes for the given recipient JIDs.
recipient_jids- JIDs to encrypt formessage- Protobuf message to encrypt
(Vec<Node>, bool)- The encrypted participant XML nodes and a boolean indicating whether a device identity node should be included in the stanza (true when any participant received a PreKey message).
session_mutexes_for() (bare recipient JID for the recipient, per-device for own companion devices).
Example:
assert_sessions
Ensure E2E sessions exist for the given JIDs.jids- JIDs to ensure sessions for
get_user_devices
Get all known device JIDs for the given user JIDs via usync.jids- User JIDs to query
Vec<Jid>- All device JIDs for the given users
EncType
TheEncType enum represents the Signal protocol encryption type used for a message:
EncType exposes two predicate helpers: is_session() (true for Message / PreKeyMessage, excludes MessageSecret) and is_bot_secret() (true only for MessageSecret).
Bot message decryption (msmsg)
When you message Meta AI or another@bot account, the bot’s replies arrive as <enc type="msmsg"> stanzas. These are not Signal-session encrypted — they use a dual-HKDF derivation over the 32-byte messageSecret from the prompt you sent, then AES-256-GCM.
The client handles this end to end and transparently:
- On send to a bot, the outbound
MessageContextInfo.messageSecretis persisted (keyed by(chat, sender, msg_id)) so the reply can be decrypted later. - On receive, an
msmsgstanza is decrypted and decoded into awa::Message, then dispatched as a normalEvent::Message— there is no separate bot event. The sender is the bot JID (e.g.…@bot) andMsgMetaInfo.target_idpoints back at your original prompt. - On failure (missing secret, GCM tag mismatch, malformed proto) the client nacks with reason
495(MissingMessageSecret) instead of silently dropping, and group bot replies are acked with a bare<ack class="message">matching WA Web.
wacore::bot_message::decrypt_bot_message(message_secret, enc_iv, enc_payload, ctx), and persistence is backed by the MsgSecretStore trait.
Usage examples
Manual 1:1 encryption round-trip
Check session before sending
Group encryption with SKDM handling
Reset a broken session
See also
- Signal Protocol implementation - Deep dive into the protocol internals
- Client - Core client API
- Send - High-level message sending (handles encryption automatically)