Here's one example where a PAKE would be very helpful.
In Matrix E2EE chat, every user winds up with a ton of different E2EE sessions and thus a ton of different keys that they need to store. (This part of the protocol is unnecessarily complicated IMO, but it's too late to change it now.)
The key to making multi-device support work in practice has been to store an encrypted archive of all the keys for all your sessions, in encrypted form on the server. Where do you get the key for this encryption? It seems the only workable option is to derive it from a passphrase, since the user might choose to log in from a new device (or a new browser) at any moment. So the secret has to live only in the user's head.
But now each user has to remember two passwords: (1) their login password and (2) their encrypted key backup password. Do we really believe that they will pick two totally different, independent passwords??? And if they don't, then in what way are the E2EE keys protected from the server?
So it would be great if we could prevent the server ever learning the login password. For that reason, a few of us random volunteers have been looking at adding SRP or SCRAM or something to Matrix.
I don't understand why you would ever protect an encrypted archive of keys stored serverside with a passphrase authenticated from a password hash stored on the server (which is effectively how a PAKE works).
It sounds like what you want is a password-based KDF, to derive keys clientside for the encrypted bundle.
(SRP is pretty much dead now, for what it's worth).
> It sounds like what you want is a password-based KDF, to derive keys clientside for the encrypted bundle.
The encrypted blob containing E2EE keys is encrypted with a symmetric key that's derived from PBKDF2 on a passphrase.
The problem is that standard password-based authentication exposes the login password to the server every time the user logs in.
So if the user is lazy and uses the same password for both purposes, then the server could very easily derive the key and decrypt the blob that contains all of the E2EE keys.
Even if the user picks slightly different passwords, e.g. "password1" vs "password2", the server has a huge advantage over your standard brute force attacker.
> (SRP is pretty much dead now, for what it's worth).
I am having trouble following the security design here. If the server ever decrypts this data, it doesn't matter how you store the keys. If it doesn't, the encryption keys never need to leave the client.
I think you need to start by very clearly defining the security model you are trying to design, and then start talking about constructions to throw at it.
I don't know what the shrug means, but you shouldn't use SRP in a 2021 design.
The shrug was that it’s weird to call something dead when it never really took off in the first place.
> you shouldn’t use SRP in a 2021 design
Ok I guess I’ll take your word for it. Which PAKE should we use instead? This is the perfect time to change our plans, since we haven’t really built anything yet.
I'm still not clear on what the PAKE is doing here, or what's being decrypted where. The problem with a PAKE between clients and servers, especially if based on the same password as the root secret for your system, is that it depends on storing a password-derived verifier on the server. That's almost never OK!
I think this gets at the root of the confusion. Talking through this has been helpful, so thanks.
So the main thing is that apparently using a PAKE is not sufficient by itself. Not revealing the password at login time only solves part of the problem.
The second requirement is that the PAKE’s “password related string” that it learns and stores must be something that does not reveal (significant information about) the password itself.
I had assumed that that was a baseline “table stakes” kind of requirement for an authentication protocol in the 2020’s, but apparently that’s not part of the definition here(?)
As to your comment about using the same password to create the verifier and the encryption key, I agree it’s not ideal. But in the real world, what practical alternative do we have?
We have password hashing functions that are pretty good at making password cracking impractical. We should use them and trust them to do their job.
As long as the verifier comes from a hash that makes finding preimages prohibitively expensive (ie, a PHF), then it seems like there’s room to work here.
Or if you have better ideas, I would love to hear them. (Not being snarky here - it would actually be good to get input from someone who works on this stuff.)
I'm still not clear on what problem you're trying to solve, but if you have a messaging system with root secret password that's used to protect message confidentiality, you cannot have information about that password stored on servers. The verifier a PAKE uses to check password validity in an augmented PAKE reveals information about the message-protecting password.
Maybe I'm unclear about the application here! But what I'm reading is a proposal in which the deployment of a PAKE could make the system drastically less secure on the whole.
I think you might as well client-side hash it under these circumstances?
Like the "proper" answer is rethink your protocol, have 1 password and make everything not suck.
Minimum (and achievable) job? Client side hash.
Yes it's sh%tty JS crypto in the web case but you have legacy reasons you don't want plaintext even over SSL and you're not going to promise "military grade crypto" to anyone. It's explicable. You can use existing decently reviewed JS libs at least. Any kind of PAKE was gonna be weird JS libraries for web folks anyway.
Yes you're exposed to all the CDNs your UIs use but you were exposed to them anyway.
OK yes tptacek JS crypto is bad and the browser is the worst runtime ever but it's still orders of magnitude less code than needed to make a functional web ui for a chat client, it's pretty bounded, testable and the worst case screwup is not much different than sending your password to the server in plaintext. Which is current state.
The server can store a sha256 of the PBKDF2 output of your client hashing process or whatevs? It's likely to be harder to crack than the key blob you stored on servers already. From a data at rest and in flight standpoint this is at least the same security you get from a PAKE but way easier for everyone to understand. It's one-round, no one needs to think, on server side you can still politely upgrade with zero user interaction. Clients don't have to use fringe crypto supported by one person on github. (Good luck finding a cocoa pod for any kind of PAKE).
It will get weird sending salts to clients if you care about username enumeration, feels like the only way for that not to be stateful in a bad way on your servers is if you derive it from email or login id or something (aka don't actually need to store or send). Not sure how you would resolve that if your UX needs to support multiple login identifiers. That would be hard because you have secret but pre-auth information (relationship between names), and it would require its own sort of thinking.
I have zero knowledge of matrix and so this will probably go down as an embarassing comment. The things I don't know here outweigh the things I do, so this is probably bad advice.
I do want to say, sometimes you just have to go low tech and the dumb thing is the best answer. Sometimes you have to endure raised eyebrows and not doing the sexy thing for community and engineering reasons.
Props for shipping and maintaining a thing that people use and care about. That is hard. Everyone got raised eyebrows but no one got MRs.
Are you sure that's how Matrix E2EE works? In my experience, to access encrypted chats after logging in for the first time I have to verify the new session by performing a synchronous prompt-verify sequence from an existing session, and I don't remember setting any encryption passphrase at all.
What gives? Are we just using different defaults or clients or something?
Disclaimer: I'm not an expert in this stuff, just a 3rd party client developer who is interested in the topic.
AFAIK, there are two ways to validate a new device in Matrix.
It sounds like you're describing the interactive device validation procedure. After that, your two devices trust each other, and the old device can "cross sign" the public key of your new device, so others can trust it too.
Personally for me, even with cross-signing, I was still getting a significant number of messages that failed to decrypt. Usually I think the problem was that one of my devices wasn't around to receive the original version of some key. And for whatever reason, even with cross-signing, it wasn't getting the keys from my other devices. For example, maybe my other devices were offline at the time.
The fix for me was to go the passphrase route. Now, regardless of what device I'm on, the passphrase gets me access to all of my secrets via the encrypted blob on the server.
In Matrix E2EE chat, every user winds up with a ton of different E2EE sessions and thus a ton of different keys that they need to store. (This part of the protocol is unnecessarily complicated IMO, but it's too late to change it now.)
The key to making multi-device support work in practice has been to store an encrypted archive of all the keys for all your sessions, in encrypted form on the server. Where do you get the key for this encryption? It seems the only workable option is to derive it from a passphrase, since the user might choose to log in from a new device (or a new browser) at any moment. So the secret has to live only in the user's head.
But now each user has to remember two passwords: (1) their login password and (2) their encrypted key backup password. Do we really believe that they will pick two totally different, independent passwords??? And if they don't, then in what way are the E2EE keys protected from the server?
So it would be great if we could prevent the server ever learning the login password. For that reason, a few of us random volunteers have been looking at adding SRP or SCRAM or something to Matrix.