initial commit of e2e backup proposal
parent
f5dc0eaed2
commit
1b81970a1e
@ -0,0 +1,197 @@
|
||||
Storing megolm keys serverside
|
||||
==============================
|
||||
|
||||
Background
|
||||
----------
|
||||
|
||||
We *optionally* let clients store a copy of their megolm inbound session keys
|
||||
on the HS so that they can recover history if all devices are lost without an
|
||||
explicit key export; transparently share history between a user's devices;
|
||||
transparently share missing keys between a user's devices to fix UISIs; support
|
||||
clients with limited local storage for keys.
|
||||
|
||||
See also:
|
||||
|
||||
* https://github.com/matrix-org/matrix-doc/issues/1219
|
||||
* https://github.com/vector-im/riot-web/issues/3661
|
||||
* https://github.com/vector-im/riot-web/issues/5675
|
||||
* https://docs.google.com/document/d/1MOoIA9qEKIhUQ3UmKZG-loqA8e0BzgWKKlKRUGMynVc/edit#
|
||||
(old version of proposal)
|
||||
|
||||
Proposal
|
||||
--------
|
||||
|
||||
This proposal creates new APIs to allow clients to back up room decryption keys
|
||||
on the server. Decryption keys are encrypted (using public key crypto) before
|
||||
being sent to the server along with some unencrypted metadata to allow the
|
||||
server to manage the backups, overwriting backups with "better" versions of the
|
||||
keys. The user is given a private recovery key to save for recovering the keys
|
||||
from the backup.
|
||||
|
||||
Clients can create new versions of backups. A client would start a new version
|
||||
of a backup when, for example, a user loses a device, and wants to ensure that
|
||||
that device does not get any new decryption keys.
|
||||
|
||||
### Possible UX for interactive clients
|
||||
|
||||
On receipt of encryption keys (1st time):
|
||||
|
||||
1. client checks if there is an existing backup: `GET /room_keys/version`
|
||||
1. if not, ask if the user wants to back up keys
|
||||
1. if yes:
|
||||
1. generate new key pair
|
||||
2. create new backup version: `POST /room_keys/version`
|
||||
3. display private key to user to save
|
||||
2. if no, exit and remember decision (user can change their mind later)
|
||||
3. while prompting, continue to poll `GET /room_keys/versions`, as
|
||||
another device may have created a backup. If so, go to 1.2.
|
||||
2. if yes, get public key, prompt user to verify a device that signed the
|
||||
key¹, or enter recovery key (which can derive the backup key).
|
||||
1. User can also decide to create a new backup, in which case, go to 1.1.
|
||||
2. send key to backup: `PUT /room_keys/keys/${roomId}/${sessionId}?version=$v`
|
||||
3. continue backing up keys as we receive them (may receive a 403 error if a
|
||||
new backup version has been created: see below)
|
||||
|
||||
On 403 error when trying to `PUT` keys:
|
||||
|
||||
1. get the current version
|
||||
2. notify the user that there is a new backup version, and display relevant
|
||||
information
|
||||
3. confirm with user that they want to use the backup (user may want use the
|
||||
backup, to stop backing up keys, or to create a new backup)
|
||||
4. verify the device that signed the backup key¹, or enter recovery key
|
||||
|
||||
¹: cross-signing (when that is completed) can be used to verify the device
|
||||
that signed the key.
|
||||
|
||||
On receipt of undecryptable message:
|
||||
|
||||
1. ask user if they want to restore backup (ask whether to get individual key,
|
||||
room keys, or all keys). (This can be done in the same place as asking if
|
||||
the user wants to request keys from other devices.)
|
||||
2. if yes, prompt for private key, and get keys: `GET /room_keys/keys`
|
||||
|
||||
### API
|
||||
|
||||
#### Backup versions
|
||||
|
||||
##### `POST /room_keys/version`
|
||||
|
||||
Create a new backup version.
|
||||
|
||||
Body parameters:
|
||||
|
||||
- `algorithm` (string): Required. The algorithm used for storing backups.
|
||||
Currently, only `m.megolm_backup.v1` is defined. (FIXME: change the algorithm
|
||||
name to include the encryption method)
|
||||
- `auth_data` (string or object): Required. algorithm-dependent data. For
|
||||
`m.megolm_backup.v1`, this is a signedjson object with the following keys:
|
||||
- `public_key` (string): ...
|
||||
- `signatures` (object): signatures of the public key
|
||||
|
||||
Example:
|
||||
|
||||
```javascript
|
||||
{
|
||||
"algorithm": "m.megolm_backup.v1",
|
||||
"auth_data": {
|
||||
"public_key": {
|
||||
"public_key": "abcdefg",
|
||||
"signatures": {
|
||||
"something": {
|
||||
"ed25519:something": "hijklmnop"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
On success, returns a JSON object with keys:
|
||||
|
||||
- `version` (integer): the backup version
|
||||
|
||||
##### `GET /room_keys/version`
|
||||
|
||||
Get information about the current version.
|
||||
|
||||
On success, returns a JSON object with keys:
|
||||
|
||||
- `algorithm` (string): Required. Same as in the body parameters for `POST
|
||||
/room_keys/version`.
|
||||
- `auth_data` (string or object): Required. Same as in the body parameters for
|
||||
`POST /room_keys/version`.
|
||||
- `version` (integer): the backup version
|
||||
|
||||
|
||||
#### Storing keys
|
||||
|
||||
##### `PUT /room_keys/keys/${roomId}/${sessionId}?version=$v`
|
||||
|
||||
Store the key for the given session in the given room, using the given backup
|
||||
version.
|
||||
|
||||
If the server already has a backup in the backup version for the given session
|
||||
and room, then it will keep the "better" one ...
|
||||
|
||||
Body parameters:
|
||||
|
||||
- `first_message_index` (integer): Required. The index of the first message
|
||||
in the session that the key can decrypt.
|
||||
- `forwarded_count` (integer): Required. The number of times this key has been
|
||||
forwarded.
|
||||
- `is_verified` (boolean): Whether the device backing up the key has verified
|
||||
the device that the key is from.
|
||||
- `session_data` (string): The backup of the key, encrypted according to the
|
||||
backup algorithm.
|
||||
|
||||
On success, returns ... ?
|
||||
|
||||
##### `PUT /room_keys/keys/${roomId}?version=$v`
|
||||
|
||||
Store several keys for the given room, using the given backup version.
|
||||
|
||||
Behaves the same way as if the keys were added individually using `PUT
|
||||
/room_keys/keys/${roomId}/${sessionId}?version=$v`.
|
||||
|
||||
Body paremeters:
|
||||
- `sessions` (object): an object where the keys are the session IDs, and the
|
||||
values are objects of the same form as the body in `PUT
|
||||
/room_keys/keys/${roomId}/${sessionId}?version=$v`.
|
||||
|
||||
On success, returns same as `PUT
|
||||
/room_keys/keys/${roomId}/${sessionId}?version=$v`
|
||||
|
||||
##### `PUT /room_keys/keys/?version=$v`
|
||||
|
||||
...
|
||||
|
||||
#### Retrieving keys
|
||||
|
||||
##### `GET /room_keys/keys/${roomId}/${sessionId}?version=$v`
|
||||
##### `GET /room_keys/keys/${roomId}?version=$v`
|
||||
##### `GET /room_keys/keys/?version=$v`
|
||||
|
||||
#### Deleting keys
|
||||
|
||||
##### `DELETE /room_keys/keys/${roomId}/${sessionId}?version=$v`
|
||||
##### `DELETE /room_keys/keys/${roomId}?version=$v`
|
||||
##### `DELETE /room_keys/keys/?version=$v`
|
||||
|
||||
Tradeoffs
|
||||
---------
|
||||
|
||||
Security Considerations
|
||||
-----------------------
|
||||
|
||||
An attacker who gains access to a user's account can delete or corrupt their
|
||||
key backup. This proposal does not attempt to protect against that.
|
||||
|
||||
Other Issues
|
||||
------------
|
||||
|
||||
Since many clients will receive encryption keys at around the same time,
|
||||
clients should randomly offset their requests ...
|
||||
|
||||
Conclusion
|
||||
----------
|
Loading…
Reference in New Issue