Matthew Garrett ([personal profile] mjg59) wrote2025-06-05 02:05 pm
Entry tags:

How Twitter could (somewhat) fix their encrypted DMs

As I wrote in my last post, Twitter's new encrypted DM infrastructure is pretty awful. But the amount of work required to make it somewhat better isn't large.

When Juicebox is used with HSMs, it supports encrypting the communication between the client and the backend. This is handled by generating a unique keypair for each HSM. The public key is provided to the client, while the private key remains within the HSM. Even if you can see the traffic sent to the HSM, it's encrypted using the Noise protocol and so the user's encrypted secret data can't be retrieved.

But this is only useful if you know that the public key corresponds to a private key in the HSM! Right now there's no way to know this, but there's worse - the client doesn't have the public key built into it, it's supplied as a response to an API request made to Twitter's servers. Even if the current keys are associated with the HSMs, Twitter could swap them out with ones that aren't, terminate the encrypted connection at their endpoint, and then fake your query to the HSM and get the encrypted data that way. Worse, this could be done for specific targeted users, without any indication to the user that this has happened, making it almost impossible to detect in general.

This is at least partially fixable. Twitter could prove to a third party that their Juicebox keys were generated in an HSM, and the key material could be moved into clients. This makes attacking individual users more difficult (the backdoor code would need to be shipped in the public client), but can't easily help with the website version[1] even if a framework exists to analyse the clients and verify that the correct public keys are in use.

It's still worse than Signal. Use Signal.

[1] Since they could still just serve backdoored Javascript to specific users. This is, unfortunately, kind of an inherent problem when it comes to web-based clients - we don't have good frameworks to detect whether the site itself is malicious.
Matthew Garrett ([personal profile] mjg59) wrote2025-06-05 12:02 pm
Entry tags:

Twitter's new encrypted DMs aren't better than the old ones

(Edit: Twitter could improve this significantly with very few changes - I wrote about that here. It's unclear why they'd launch without doing that, since it entirely defeats the point of using HSMs)

When Twitter[1] launched encrypted DMs a couple
of years ago, it was the worst kind of end-to-end
encrypted - technically e2ee, but in a way that made it relatively easy for Twitter to inject new encryption keys and get everyone's messages anyway. It was also lacking a whole bunch of features such as "sending pictures", so the entire thing was largely a waste of time. But a couple of days ago, Elon announced the arrival of "XChat", a new encrypted message platform built on Rust with (Bitcoin style) encryption, whole new architecture. Maybe this time they've got it right?

tl;dr - no. Use Signal. Twitter can probably obtain your private keys, and admit that they can MITM you and have full access to your metadata.

The new approach is pretty similar to the old one in that it's based on pretty straightforward and well tested cryptographic primitives, but merely using good cryptography doesn't mean you end up with a good solution. This time they've pivoted away from using the underlying cryptographic primitives directly and into higher level abstractions, which is probably a good thing. They're using Libsodium's boxes for message encryption, which is, well, fine? It doesn't offer forward secrecy (if someone's private key is leaked then all existing messages can be decrypted) so it's a long way from the state of the art for a messaging client (Signal's had forward secrecy for over a decade!), but it's not inherently broken or anything. It is, however, written in C, not Rust[2].

That's about the extent of the good news. Twitter's old implementation involved clients generating keypairs and pushing the public key to Twitter. Each client (a physical device or a browser instance) had its own private key, and messages were simply encrypted to every public key associated with an account. This meant that new devices couldn't decrypt old messages, and also meant there was a maximum number of supported devices and terrible scaling issues and it was pretty bad. The new approach generates a keypair and then stores the private key using the Juicebox protocol. Other devices can then retrieve the private key.

Doesn't this mean Twitter has the private key? Well, no. There's a PIN involved, and the PIN is used to generate an encryption key. The stored copy of the private key is encrypted with that key, so if you don't know the PIN you can't decrypt the key. So we brute force the PIN, right? Juicebox actually protects against that - before the backend will hand over the encrypted key, you have to prove knowledge of the PIN to it (this is done in a clever way that doesn't directly reveal the PIN to the backend). If you ask for the key too many times while providing the wrong PIN, access is locked down.

But this is true only if the Juicebox backend is trustworthy. If the backend is controlled by someone untrustworthy[3] then they're going to be able to obtain the encrypted key material (even if it's in an HSM, they can simply watch what comes out of the HSM when the user authenticates if there's no validation of the HSM's keys). And now all they need is the PIN. Turning the PIN into an encryption key is done using the Argon2id key derivation function, using 32 iterations and a memory cost of 16MB (the Juicebox white paper says 16KB, but (a) that's laughably small and (b) the code says 16 * 1024 in an argument that takes kilobytes), which makes it computationally and moderately memory expensive to generate the encryption key used to decrypt the private key. How expensive? Well, on my (not very fast) laptop, that takes less than 0.2 seconds. How many attempts to I need to crack the PIN? Twitter's chosen to fix that to 4 digits, so a maximum of 10,000. You aren't going to need many machines running in parallel to bring this down to a very small amount of time, at which point private keys can, to a first approximation, be extracted at will.

Juicebox attempts to defend against this by supporting sharding your key over multiple backends, and only requiring a subset of those to recover the original. I can't find any evidence that Twitter's does seem to be making use of this,Twitter uses three backends and requires data from at least two, but all the backends used are under x.com so are presumably under Twitter's direct control. Trusting the keystore without needing to trust whoever's hosting it requires a trustworthy communications mechanism between the client and the keystore. If the device you're talking to can prove that it's an HSM that implements the attempt limiting protocol and has no other mechanism to export the data, this can be made to work. Signal makes use of something along these lines using Intel SGX for contact list and settings storage and recovery, and Google and Apple also have documentation about how they handle this in ways that make it difficult for them to obtain backed up key material. Twitter has no documentation of this, and as far as I can tell does nothing to prove that the backend is in any way trustworthy. (Edit to add: The Juicebox API does support authenticated communication between the client and the HSM, but that relies on you having some way to prove that the public key you're presented with corresponds to a private key that only exists in the HSM. Twitter gives you the public key whenever you communicate with them, so even if they've implemented this properly you can't prove they haven't made up a new key and MITMed you the next time you retrieve your key)

On the plus side, Juicebox is written in Rust, so Elon's not 100% wrong. Just mostly wrong.

But ok, at least you've got viable end-to-end encryption even if someone can put in some (not all that much, really) effort to obtain your private key and render it all pointless? Actually no, since you're still relying on the Twitter server to give you the public key of the other party and there's no out of band mechanism to do that or verify the authenticity of that public key at present. Twitter can simply give you a public key where they control the private key, decrypt the message, and then reencrypt it with the intended recipient's key and pass it on. The support page makes it clear that this is a known shortcoming and that it'll be fixed at some point, but they said that about the original encrypted DM support and it never was, so that's probably dependent on whether Elon gets distracted by something else again. And the server knows who and when you're messaging even if they haven't bothered to break your private key, so there's a lot of metadata leakage.

Signal doesn't have these shortcomings. Use Signal.

[1] I'll respect their name change once Elon respects his daughter

[2] There are implementations written in Rust, but Twitter's using the C one with these JNI bindings

[3] Or someone nominally trustworthy but who's been compelled to act against your interests - even if Elon were absolutely committed to protecting all his users, his overarching goals for Twitter require him to have legal presence in multiple jurisdictions that are not necessarily above placing employees in physical danger if there's a perception that they could obtain someone's encryption keys
lightreads: a partial image of a etymology tree for the Indo-European word 'leuk done in white neon on black'; in the lower left is (Default)
lightreads ([personal profile] lightreads) wrote2025-05-30 01:23 pm

Where the Axe Is Buried by Ray Nayler

Where the Axe Is Buried

4/5. A near future scifi thriller about the violently authoritarian surveillance state (it’s Russia) where the president is downloaded into successive bodies which the population steadfastly pretends not to notice, and the western european powers that have “rationalized,” i.e., installed AI prime ministers. A book about regime destabilization, and surveillance shadows, and thought control, and inception.

I was reading perfectly acceptable books, and then I picked this up and was like oh damn. Now this is good writing. This is tight (less than 100,000 words, probably) and intense and strange and bleak and hopeful. It stradles several genres and as such I suspect will not satisfy a lot of people: too literary and ambiguous for some, too much thriller for others. But this really landed for me.

Dense, chewy, controlled, beautifully written. Terribly sad on the costs of defying authoritarianism. Hopeful, in a complicated way.

Content notes: State violence Disappearances, camps, etc.
lightreads: a partial image of a etymology tree for the Indo-European word 'leuk done in white neon on black'; in the lower left is (Default)
lightreads ([personal profile] lightreads) wrote2025-05-28 03:45 pm

The Last Hour Between Worlds by Melissa Caruso

The Last Hour Between Worlds

4/5. A single mother, just two months post-partum, gets out for one night to attend a ball in her fantasy city. Which gets complicated when the whole ballroom keeps falling through levels of reality each time the clock strikes, and when her former crush turned professional enemy, the hot lady thief, is also on the case.

This is a lot of fun, and very stylish. Visually, I mean – there’s a lot going on here with what people are wearing and carrying, and with the shifting esthetics of each layer of reality. And you know I’m in favor of adventure books about mothers, particularly very new mothers like this one.

If you’re paying even moderate amounts of attention, none of these plot twists will rock you. But they are all pleasing to unwind, as is the whole book.

Content notes: Violence, temporary character death.
lightreads: a partial image of a etymology tree for the Indo-European word 'leuk done in white neon on black'; in the lower left is (Default)
lightreads ([personal profile] lightreads) wrote2025-05-27 01:06 pm

The Shots You Take by Rachel Reid

The Shots You Take

3/5. Another one of these M/M hockey romances. This one is even less about hockey than usual – old estranged teammates reconnect post retirement when one’s father dies. They have a lot of baggage having to do with how they used to sleep together, and one of them was in love and one of them had a lot of internalized homophobia.

I mean, I suppose someone did have to title a hockey romance that at some point.

Anyway, this one is nice, particularly for having actual adults in it. It also successfully walks that tough line where one half of the pairing treated the other half very poorly in the past, and there’s a lot of justifiable anger, but it is a romance after all so we have to retain some sympathy for both sides. So yeah, I liked this one fine. I’m not liking any romance more than fine at the moment, though, so who even knows what’s good anymore.

Content notes: Parental death and the raw aftermath.