diff --git a/.github/_typos.toml b/.github/_typos.toml index 38078207..4aff005f 100644 --- a/.github/_typos.toml +++ b/.github/_typos.toml @@ -9,4 +9,4 @@ au1ba7o = "au1ba7o" [default.extend-words] Appy = "Appy" -fo = "fo" \ No newline at end of file +fo = "fo" diff --git a/changelogs/client_server/newsfragments/3615.feature b/changelogs/client_server/newsfragments/3615.feature new file mode 100644 index 00000000..19a07e26 --- /dev/null +++ b/changelogs/client_server/newsfragments/3615.feature @@ -0,0 +1 @@ +Add support for fallback keys (optional keys used once one-time keys run out), as per [MSC2732](https://github.com/matrix-org/matrix-doc/pull/2732). \ No newline at end of file diff --git a/content/client-server-api/modules/end_to_end_encryption.md b/content/client-server-api/modules/end_to_end_encryption.md index 7ac7c086..990a7751 100644 --- a/content/client-server-api/modules/end_to_end_encryption.md +++ b/content/client-server-api/modules/end_to_end_encryption.md @@ -117,9 +117,13 @@ must include the public part of the device's Ed25519 key, and must be signed by that key, as described in [Signing JSON](/appendices/#signing-json). -One-time keys are also uploaded to the homeserver using the +One-time and fallback keys are also uploaded to the homeserver using the [`/keys/upload`](/client-server-api/#post_matrixclientv3keysupload) API. +{{% added-in v="1.2" %}} Fallback keys are similar to one-time keys, but +are not consumed once used. They are only used when the device has run out +of one-time keys, and can be replaced by a new fallback key. + Devices must store the private part of each key they upload. They can discard the private part of a one-time key when they receive a message using that key. However it's possible that a one-time key given out by a @@ -128,6 +132,24 @@ never know that it can discard the key. Therefore a device could end up trying to store too many private keys. A device that is trying to store too many private keys may discard keys starting with the oldest. +{{% boxes/warning %}} +Fallback keys are used to prevent one-time key exhaustion when devices +are offline/unable to upload additional keys, though sessions started using +fallback keys could be vulnerable to replay attacks. +{{% /boxes/warning %}} + +{{% boxes/warning %}} +Clients should not store the private half of fallback keys indefinitely +to avoid situations where attackers can decrypt past messages sent using +that fallback key. + +Instead, clients should keep the private keys for at most 2 fallback keys: +the current, unused, fallback key and the key immediately preceding it. +Once the client is reasonably certain it has received all messages that +used the old fallback key, such as after an hour since the first message, +it should remove that fallback key. +{{% /boxes/warning %}} + ##### Tracking the device list for a user Before Alice can send an encrypted message to Bob, she needs a list of @@ -344,6 +366,11 @@ A homeserver should rate-limit the number of one-time keys that a given user or remote server can claim. A homeserver should discard the public part of a one time key once it has given that key to another user. +{{% added-in v="1.2" %}} If the device has run out of one-time keys which +can be claimed, the homeserver will return the fallback key (if one was +uploaded). Fallback keys are not deleted once used and should be replaced +by the device when they are able to upload more one-time keys. + #### Device verification Before Alice sends Bob encrypted data, or trusts data received from him, @@ -1603,10 +1630,23 @@ It also adds a `one_time_keys_count` property. Note the spelling difference with the `one_time_key_counts` property in the [`/keys/upload`](/client-server-api/#post_matrixclientv3keysupload) response. -| Parameter | Type | Description | -|----------------------------|--------------------|------------------------------------------------------------------------------------------------------------------------| -| device_lists | DeviceLists | Optional. Information on e2e device updates. Note: only present on an incremental sync. | -| device_one_time_keys_count | {string: integer} | Optional. For each key algorithm, the number of unclaimed one-time keys currently held on the server for this device. | + +{{% added-in v="1.2" %}} Finally, a `device_unused_fallback_key_types` property +is added to list the key algorithms where the device has a fallback key that +*has not* been used in a [`/keys/claim`](/client-server-api/#post_matrixclientv3keysclaim) +response. When a previously uploaded fallback key's algorithm is missing +from this list, the device should upload a replacement key alongside any +necessary one-time keys to avoid the fallback key's further usage. This +property is required for inclusion, though previous versions of the +specification did not have it. In addition to `/versions`, this can be +a way to identify the server's support for fallback keys. + + +| Parameter | Type | Description | +|----------------------------------|--------------------|------------------------------------------------------------------------------------------------------------------------| +| device_lists | DeviceLists | Optional. Information on e2e device updates. Note: only present on an incremental sync. | +| device_one_time_keys_count | {string: integer} | Optional. For each key algorithm, the number of unclaimed one-time keys currently held on the server for this device. | +| device_unused_fallback_key_types | [string] | **Required.** The unused fallback key algorithms. | `DeviceLists` diff --git a/data/api/client-server/keys.yaml b/data/api/client-server/keys.yaml index 65782362..357df233 100644 --- a/data/api/client-server/keys.yaml +++ b/data/api/client-server/keys.yaml @@ -100,6 +100,40 @@ paths: } } } + fallback_keys: + type: object + x-addedInMatrixVersion: "1.2" + description: |- + The public key which should be used if the device's one-time keys + are exhausted. The fallback key is not deleted once used, but should + be replaced when additional one-time keys are being uploaded. The + server will notify the client of the fallback key being used through + `/sync`. + + There can only be at most one key per algorithm uploaded, and the server + will only persist one key per algorithm. + + When uploading a signed key, an additional `fallback: true` key should + be included to denote that the key is a fallback key. + + May be absent if a new fallback key is not required. + additionalProperties: + type: + - string + - object + # XXX: We can't define an actual object here - see one_time_keys. + example: { + "curve25519:AAAAAG": "/qyvZvwjiTxGdGU0RCguDCLeR+nmsb3FfNG3/Ve4vU8", + "signed_curve25519:AAAAGj": { + "key": "zKbLg+NrIjpnagy+pIY6uPL4ZwEG2v+8F9lmgsnlZzs", + "fallback": true, + "signatures": { + "@alice:example.com": { + "ed25519:JLAFKJWSCS": "FLWxXqGbwrb8SM3Y795eB6OA8bwBcoMZFXBqnTn58AYWZSqiD45tlBVcDa2L7RwdKXebW/VzDlnfVJ+9jok1Bw" + } + } + } + } responses: 200: description: @@ -378,6 +412,9 @@ paths: See the [key algorithms](/client-server-api/#key-algorithms) section for information on the Key Object format. + + If necessary, the claimed key might be a fallback key. Fallback + keys are re-used by the server until replaced by the device. additionalProperties: type: object additionalProperties: