Matrix vs. XMPP: Crypto
2021 February 17
Matrix and XMPP (Extensible Messaging and Presence Protocol) are protocols for federated instant messaging.
In this post, I will briefly discuss the encryption protocols used in XMPP and Matrix.
XMPP supports multiple protocols, including OpenPGP, OTR (Off The Record), and OMEMO (OMEMO Multi-End Message and Object Encryption). I'll discuss each briefly, but I will mainly focus on OMEMO.
OpenPGP (PGP = Pretty Good Privacy) is a cryptography protocol most commonly associated with email. It provides confidentiality, integrity, authentication, and non-repudiation and can be used asynchronously. It does not provide forward or backward secrecy or deniability.
OTR views the non-repudiation of OpenPGP as a problem and was designed to provide both authentication and deniability: When Alice sends Bob a message, Bob should be confident that the message genuinely came from Alice, but he should not be able to prove this to a third party. It also provides (reply-based) forward and backward secrecy not available in OpenPGP. The biggest usability issue with OTR is that OTR conversations can only be started synchronously (i.e., when both parties are online), although work is being done to address this deficiency.
OMEMO uses the Double-Ratchet Algorithm to provide both per-message forward secrecy and reply-based forward and backward secrecy. It also provides authentication and deniability like OTR, but it can be used asynchronously and with multiple devices, making it much more usable. It's basically the Signal Protocol adapted for use with XMPP.
OMEMO is the current recommended protocol to use with XMPP, so I'll talk about it from now on when talking about cryptography with XMPP.
Matrix has two protocols it uses for encrypted conversations: Olm and Megolm.
Olm, like OMEMO, is a double-ratchet that's basically the Signal Protocol for Matrix.
Megolm is not a double-ratchet. It's a weakened protocol which does not provide backward (future) secrecy but does provide forward secrecy. (The forward secrecy is also weakened by preserving old keys longer than strictly necessary, allowing old messages to be fetched and decrypted more than once if desired by the application. This is considered a feature.)
Matrix in practice uses a hybrid of these two algorithms: Megolm is used for the duration of a "session" (100 messages or 1 week by default). New Megolm sessions are established using Olm. The consequence of this is that while Matrix does not provide backward secrecy on a per-message basis, it does provide it on a per-session basis. Key compromise could result in up to 100 messages (or however many are in a session) being compromised, but the self-healing properties of Olm would eventually kick in.
Setting the Megolm session duration to 1 message would effectively turn Matrix's encryption into just Olm and make it equivalent to OMEMO.
Comparing OMEMO in XMPP vs. Megolm/Olm in Matrix, we can see that OMEMO is more secure, but we shouldn't take that as a definitive statement that OMEMO is better. Megolm being the way it is is an intentional choice. It makes it more efficient and better able to scale for very large encrypted group chats. Also, the Megolm security model is theoretically more flexible: you can set rooms to be more secure or more efficient, to fit your needs. It's a feature, not a bug.
(In practice, it is not obvious how to harness this flexibility and change settings like session duration. At this time, as far as I can tell, Megolm is just weaker crypto with less overhead. But maybe one day we'll have settings that users or admins can change easily through some UI.)
That said, I personally have little use for the optimizations Megolm provides through weaker security. I don't participate in any encrypted conversations large enough for OMEMO to become slow.
Encryption is set on a per-client basis in XMPP. Each device (or, specifically, each client on each device) decides whether or not to use encryption (and what type of encryption) for a given conversation. By contrast, Matrix rooms have a setting indicating that they are either encrypted or not encrypted (and encryption cannot be disabled for a room after being enabled).
Matrix supports (and strongly encourages) uploading private keys to the server, encrypted with a passphrase, so that messages can be recovered in the event that keys are lost. Element (the web version, at least) uses dark patterns to push this choice on users: a toast notification appears each time Element opens, asking the user to set up secure backup. This notification can be temporarily dismissed with the "Later" button, but there's no way to definitively refuse to set this up.
Matrix has a feature called cross-signing which should make device verification easier. (This feature also requires uploading encrypted private keys to the server.)
OMEMO and Olm depend on messages being transferred back and forth between devices to achieve backward secrecy. (These messages don't need to be actual chat messages with bodies; they just need to provide new random data. I don't know whether any XMPP or Matrix clients automatically send empty messages to forward the ratchet, but certainly always-off devices don't.) Always-off devices included in encrypted conversations weaken the security of those conversations. If Alice turns her phone off permanently, but her friends keep encrypting messages for it, the last-used keys on that phone could decrypt all the messages people have encrypted for it since the time it went offline. I don't know which clients, if any, take steps to mitigate this (such as refusing to encrypt messages for devices they haven't heard from recently).
Here are assorted sources and links with additional information: