-
Notifications
You must be signed in to change notification settings - Fork 385
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Initial MSC for encrypting recovery keys for online megolm backups #1686
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
# Proposal for storing an encrypted recovery key on the server to aid recovery of megolm key backups | ||
|
||
## Problem | ||
|
||
[MSC1219](https://github.com/matrix-org/matrix-doc/issues/1219) proposes an API for optionally storing encrypted megolm keys on your homeserver, so if a user loses all their devices, they can still recover their history. The megolm keys are public-key encrypted using a private Curve25519 key that only the end-user has. | ||
|
||
However, there are usability concerns about users having to store their Curve25519 recovery private key in a secure manner. Casual users are likely to be scared away by having to file away a relatively long (e.g. 10 word) generated recovery key. | ||
|
||
## Proposed solution | ||
|
||
Taking inspiration from Apple’s [FileVault 2](https://hal.inria.fr/hal-01460615/document) full-disk encryption, we'd like to give the user the option to encrypt their key with a passphrase and store it on the server (much as Apple store encrypted copies of your FileVault AES key on your hard disk, encrypted by your UNIX account password). This is also similar to storing a passphrased SSH private key on a server for convenience. | ||
|
||
In practice, this means: | ||
* Mandating that clients use a high complexity passphrase to encrypt the recovery key - either by enforcing complexity requirements or by generating it for them (similar to 1Password's password creation UX). | ||
* Symmetrically encrypting the Curve25519 key by N rounds of PBKDF2(key, passphrase) where N=100,000 - similarly to how we encrypt [offline megolm key backups](https://github.com/matrix-org/matrix-doc/issues/1211) today. (TODO: This needs to be fleshed out). | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ...and then presumably we need to hit the private key with AES to actually encrypt it with the key/iv from the PBKDF2? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @uhoreg if you can suggest how we should actually do this bit of it, it'd be much appreciated |
||
* Storing the encrypted key on the server. | ||
|
||
We propose storing it using the /account_data API: | ||
|
||
```json | ||
PUT /_matrix/client/r0/user/{userId}/account_data/m.recovery_key | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The recovery key will be different for different backup versions, so maybe we should have a different name for each version. Also, we should probably put it in the |
||
|
||
{ | ||
"algorithm": "m.recovery_key.v1.curve25519.pbkdf2", | ||
"data": <base64>, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. will also need to store a salt. Could also store other PBKDF2 parameters, such as number of rounds, so that people can be more paranoid if they want to. |
||
"m.hidden": true, | ||
} | ||
``` | ||
|
||
We propose extending the /account_data API with two conveniences: | ||
* the `m.hidden` event field to indicate to the server that such events should not be included in /sync responses to clients. | ||
* a `GET /_matrix/client/r0/user/{userId}/account_data/m.recovery_key` accessor, symmetrical to the existing PUT method, to access the data when needed. | ||
|
||
We deliberately encrypt the Curve25519 private key rather than deriving it from the passphrase so that if the user chooses not to store their encrypted recovery key on the server, they can benefit from a Curve25519 key generated from a high entropy source of random rather than being needlessly derived from a passphrase of some kind. (TODO: Is this accurate)? | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think this is accurate, as users who want high entropy can just use a randomly generated base64 string or something similar as their passphrase. I think the main benefit of encrypting the private key is that you change the passphrase without re-encrypting everything. |
||
|
||
## Security considerations | ||
|
||
The proposal above is vulnerable to a malicious server admin performing a dictionary attack against the encrypted passphrases stored on their server to access history. (It's worth bearing in mind that the server admin can also always hijack its user's accounts; the thing that stopping them from impersonating their users is E2E device verification.) | ||
|
||
## Possible extensions | ||
|
||
In future, we could consider supporting authenticating users for login based on their encrypted passphrase, meaning that users only have to remember one password for their Matrix account rather than a login password and a history-access passphrase. However, this of course exposes the user's whole E2E history to the risk of dictionary attacks by public attackers (i.e. not just server admins), keysniffer-at-login attacks or clients which are lazy about storing account passwords securely. There's also a risk that because login passwords are much more commonly entered than history passwords, they might encourage users to force a weaker password. It's unclear whether this reduction in security-in-depth is worth the UX benefits of a single master password, so we suggest checking how this proposal goes first (given in general we expect key recovery to happen by cross-verifying devices at login rather than by entering a recovery key or passphrase). | ||
|
||
## See also: | ||
|
||
Notes from discussing this IRL are at https://docs.google.com/document/d/11fF1rbX5eTkrfxXRS8UhpW5sBENOCydYlLWzB8X1IuU/edit |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I presume, if you are taking inspiration from FileVault, the system should also ask you to file away the generated key anyway? IIRC FileVault both encrypts your key with your UNIX password and has you write down the seed for the unencrypted key somewhere, just in case you forget your password.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yup. I will clarify, but the idea is that backing up your megolm keys, and backing up the recovery key is optional too. You can always keep a copy of the recovery key too offline.