prose-app-web icon indicating copy to clipboard operation
prose-app-web copied to clipboard

OMEMO flows

Open nesium opened this issue 2 months ago • 4 comments

Hey @valeriansaliou. I need to collect my thoughts about how we want to implement the OMEMO flows and want to let you know what's coming your way.

I've installed Conversations to see how they're handling it.

One of the questions I had - besides error handling - was how they'd display the user's identities when the spec says that you shouldn't start a session before sending a message…

Clients SHOULD NOT immediately fetch the bundle and build a session as soon as a new device is announced. Before the first message is exchanged, the contact does not know which PreKey has been used (or, in fact, that any PreKey was used at all). As they have not had a chance to remove the used PreKey from their bundle announcement, this could lead to collisions where both Alice and Bob pick the same PreKey to build a session with a specific device. As each PreKey SHOULD only be used once, the party that sends their initial OMEMOKeyExchange later loses this race condition. This means that they think they have a valid session with the contact, when in reality their messages MAY be ignored by the other end. By postponing building sessions, the chance of such issues occurring can be drastically reduced. It is RECOMMENDED to construct sessions only immediately before sending a message.

https://xmpp.org/extensions/xep-0384.html#rules

The order is to fetch the device list of a user first (or be notified via PEP) then fetch the bundle for each device. The bundle includes its identity which is what can be displayed to and verified by the user.

It turns out that Conversations displays an empty list of devices when you start a new conversation with a contact, even if the contact does have OMEMO-enabled devices.

When you send the first message, depending on the blind trust setting (in the "Expert settings" - it is enabled by default)…

You'll either see a brief toast that informs you that the user's identity was blindly trusted…

or you're presented with a screen to trust the identity manually first…

You'll also see the latter screen if you've marked all devices as 'untrusted'.

If we introduce the concept of 'Private Groups' we'd also need to handle the case where the other party does not have any OMEMO-enabled devices (anymore). It would not make sense in that case to implicitly send an unencrypted message.

There's also the possibility of a broken session which sometimes can be repaired by resetting it (e.g. changed identity) but sometimes it may not (e.g. invalid identity, missing bundle).

And devices might disappear and reappear later in which case it would be considered inactive:

Since you subscribed to the device list you will now be receiving device ids from your contacts. Save the jid-device id tuples for later use. Each tuple will have an active flag. If a device id is no longer in the list you set it to inactive. If it re-appears later you set it to active again.

https://gist.github.com/iNPUTmice/e3fe475752e39b40ea87ae5ed73b3e01

Here's a populated version of user details screen in Conversations and the menu that precedes it:

What you're also seeing in this screen are devices with a green shield. I had verified these via a QR code scan. Interestingly you cannot set them to 'untrusted' again, once you've verified them.

Once you have verified a contact's devices and they'll add a new device, the moment you send a new message you will be presented with the 'Trust OMEMO Fingerprint' selection screen from above, even if the 'Blind Trust' setting is enabled.

In summary a device can have 4 states in Conversations:

  • Undecided
  • Trusted
  • Untrusted
  • Verified

In Monal they explicitly display the 'Undecided' state (yellow). You can also see a broken session there…

whereas in Conversations I believe the 'Undecided' state reflects the 'Blind Trust' setting, so 'Undecided' is displayed as 'Trusted' if 'Blind Trust' is enabled.


Then receiving messages from untrusted devices.

Monal displays an error…

whereas Conversations decrypts the message regardless and displays it as encrypted, but untrusted (second to last message)…


Btw. Conversations also supports PGP encryption. But that seems to have its own complications (?) …


In terms of Prose Core API, I think we can handle most of these flows by throwing typed errors or returning a result structure from the sendMessage method. These could then e.g. either implicate that the message was sent because a device was blindly trusted or that it wasn't send because all devices are untrusted. The web app would then need to start the appropriate flows.

Of course there would also need to be methods to load, manage and trust devices.

A user's device list would not be populated before sending the first message (as mentioned above).

We'll also need new events (device added/removed).


Do you have any further thoughts/wishes/concerns/change requests?

nesium avatar Apr 11 '24 10:04 nesium