Protocol definition for generic messages.
This repository is part of the source code of Wire. You can find more information at wire.com or by contacting opensource@wire.com.
You can find the published source code at github.com/wireapp/wire.
For licensing information, see the attached LICENSE file and the list of third-party licenses at wire.com/legal/licenses/.
Protocol definition for generic messages.
GenericMessage
is supposed to be used in client messages (‘client-message-add’ event) and in OTR encrypted messages. Once E2EE is released client messages will no longer be used.
GenericMessage
contains message id and specific message content (oneOf
)
MessageId
field is client generated identifier of a message this GenericMessage
relates to, it should be used by all clients to correlate message updates. This is not unique event id, there may (and will) be several GenericMessage
events with the same messageId
, each GenericMessage
provides part of final message or some update to it.
Each ImageAsset version/tag is sent in separate request which means there are several GenericMessage
events for each asset, all of them will use the same messageId
, this actually replaces correlationId
from regular asset events. It will be the same for different updates, for example like events, they will all contain messageId
of references message.
Clients need to take case of message id collisions. It is possible, that some malicious client will generate events with the same id in order to override other messages. Every time GenericMessage
is received, client need to check if it already has a message with the same id and make sure that this is a valid update. If received event is not valid update (for example sender doesn’t match to original message author in text messages), then clients is allowed to drop the message or use different id for it. Using different id is preferred to handle unintended collisions or to expose buggy sender behaviour.
Actual message content is included as oneof
field in GenericMessage
, this way we can later add more message types in backward compatible manner.
A user sends a generic message of type Availability
if he wants to change his personal availability. The availability can be of four types: None
, Available
, Busy
, and Away
.
Regular text message content, optionally including a list of mentioned users.
Describes user mentioned in text message. Contains user_id
, start
and end
offsets of the mention string in UTF16 characters. The offset is used to highlight mention text inside the message. user_id
is optional because to keep it backwards compatible when mentioning more than one user e.g. @everyone or @some_team.
Internal message, sent on self conversation to notify other clients (belonging to the same user) about messages being read in some conversation.
Internal message, sent on self conversation to notify other clients about conversation being cleared.
Internal message, sent on self conversation to notify other clients about message being locally deleted.
Message sent to recall previously sent message, can be only sent by original author of deleted message.
If the content of a previously sent message should be edited, a generic message of type MessageEdit
has to be sent.
It should reference the new content (for now only type Text
can be edited) as well as the nonce of the message it is replacing. If an edit message is received which is referencing a non existent nonce it should be discarded.
If the reception of a previously sent message should be confirmed, a generic message of type Confirmation
has to be sent. It should reference the message to be confirmed. Currently the confirmation comes in two flavours: Read
and Delivered
.
Location sharing message, contains GPS coordinates (latitude and longitude) and optional location name string.
Expresses a reaction to a previously received message. The reaction itself can be any string but should be an emoji. If there are multiple reactions from one user to the same message, only the most recent one should be kept. In order to remove/clear a previous reaction, the empty string should be sent.
Contains metadata for single image asset version, most fields correspond to metadata sent on regular assets endpoint.
There are three special fields:
otr_key
- optional symmetric encryption key. If asset message includes this key, then asset stored on backend is encrypted, and clients can use this key to decrypt original image data.sha256
- hash of encrypted asset ciphertext. Should be provided for encrypted messages, clients should check it before trying to decrypt an asset.Asset encryption should follow similar procedure as symmetric encryption in native push notifications.
Encryption with standard AES256 in CBC mode with PKCS#5/7 padding and the initialization vector (IV) prepended to the ciphertext.
SHA256 is computed from cyphertext, receiving client validates it before decrypting an asset.
Metadata for generic file uploads. Intended to supersede ImageAsset at a later point. For encryption and related fields, see ImageAsset.
This message can be received in up to 3 parts which then can be merged together to build a complete asset record.
original
is set with basic info about the file being uploaded.preview
is set with basic info about the preview as well as the encryption fields. This step is optional.status.not_uploaded
field is set with the appropriate value.status.uploaded
field is set with encryption info provided.This message content is used if original message results in large payload, that would not be accepted by backend.
Regular messages are encrypted multiple times (per recipient) and in case of multiple participants even quite small
message can generate huge payload.
In that case we want to encrypt original message with symmetric encryption and only send a key to all participants.
Clients use fallowing procedure when sending a message:
GenericMessage
(OM
)ClientMismatch
error)OM
can be sent directlyOM
using symmetric encryption (the same way as for assets)External
message with AES key and sha of encrypted dataExternal
content and encrypted OM
attached (data
field in json)Messages sent through OTR can be decrypted only once, so it’s important not to loose any info, even when receiving a message that can not be fully decoded (when using older app version). It would be advisable to save original GenericMessage
data and decode it again after app update. This should be done at least when decoded message seems to have no content
, this will happen when new content type is added, in that case old app will think that the message is empty.