mirror of
https://github.com/matrix-org/matrix-spec
synced 2025-12-20 16:38:37 +01:00
Spec PR - MSC4147: Including device keys with Olm-encrypted events (#2122)
Some checks failed
Spec / 🔎 Validate OpenAPI specifications (push) Has been cancelled
Spec / 🔎 Check Event schema examples (push) Has been cancelled
Spec / 🔎 Check OpenAPI definitions examples (push) Has been cancelled
Spec / 🔎 Check JSON Schemas inline examples (push) Has been cancelled
Spec / ⚙️ Calculate baseURL for later jobs (push) Has been cancelled
Spec / 📢 Run towncrier for changelog (push) Has been cancelled
Spell Check / Spell Check with Typos (push) Has been cancelled
Spec / 🐍 Build OpenAPI definitions (push) Has been cancelled
Spec / 📖 Build the spec (push) Has been cancelled
Spec / 🔎 Validate generated HTML (push) Has been cancelled
Spec / 📖 Build the historical backup spec (push) Has been cancelled
Some checks failed
Spec / 🔎 Validate OpenAPI specifications (push) Has been cancelled
Spec / 🔎 Check Event schema examples (push) Has been cancelled
Spec / 🔎 Check OpenAPI definitions examples (push) Has been cancelled
Spec / 🔎 Check JSON Schemas inline examples (push) Has been cancelled
Spec / ⚙️ Calculate baseURL for later jobs (push) Has been cancelled
Spec / 📢 Run towncrier for changelog (push) Has been cancelled
Spell Check / Spell Check with Typos (push) Has been cancelled
Spec / 🐍 Build OpenAPI definitions (push) Has been cancelled
Spec / 📖 Build the spec (push) Has been cancelled
Spec / 🔎 Validate generated HTML (push) Has been cancelled
Spec / 📖 Build the historical backup spec (push) Has been cancelled
Signed-off-by: Johannes Marbach <n0-0ne+github@mailbox.org> Co-authored-by: Richard van der Hoff <richard@matrix.org>
This commit is contained in:
parent
cbf1854b93
commit
643a6dca2d
1
changelogs/client_server/newsfragments/2122.feature
Normal file
1
changelogs/client_server/newsfragments/2122.feature
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
Include device keys with Olm-encrypted events as per [MSC4147](https://github.com/matrix-org/matrix-spec-proposals/pull/4147).
|
||||||
|
|
@ -1512,40 +1512,11 @@ message.
|
||||||
|
|
||||||
The plaintext payload is of the form:
|
The plaintext payload is of the form:
|
||||||
|
|
||||||
```json
|
{{% definition path="api/client-server/definitions/olm_payload" %}}
|
||||||
{
|
|
||||||
"type": "<type of the plaintext event>",
|
|
||||||
"content": "<content for the plaintext event>",
|
|
||||||
"sender": "<sender_user_id>",
|
|
||||||
"recipient": "<recipient_user_id>",
|
|
||||||
"recipient_keys": {
|
|
||||||
"ed25519": "<our_ed25519_key>"
|
|
||||||
},
|
|
||||||
"keys": {
|
|
||||||
"ed25519": "<sender_ed25519_key>"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
The type and content of the plaintext message event are given in the
|
The type and content of the plaintext message event are given in the
|
||||||
payload.
|
payload.
|
||||||
|
|
||||||
Other properties are included in order to prevent an attacker from
|
|
||||||
publishing someone else's curve25519 keys as their own and subsequently
|
|
||||||
claiming to have sent messages which they didn't. `sender` must
|
|
||||||
correspond to the user who sent the event, `recipient` to the local
|
|
||||||
user, and `recipient_keys` to the local ed25519 key.
|
|
||||||
|
|
||||||
Clients must confirm that the `sender_key` property in the cleartext
|
|
||||||
`m.room.encrypted` event body, and the `keys.ed25519` property in the
|
|
||||||
decrypted plaintext, match the keys returned by
|
|
||||||
[`/keys/query`](#post_matrixclientv3keysquery) for
|
|
||||||
the given user. Clients must also verify the signature of the keys from the
|
|
||||||
`/keys/query` response. Without this check, a client cannot be sure that
|
|
||||||
the sender device owns the private part of the ed25519 key it claims to
|
|
||||||
have in the Olm payload. This is crucial when the ed25519 key corresponds
|
|
||||||
to a verified device.
|
|
||||||
|
|
||||||
If a client has multiple sessions established with another device, it
|
If a client has multiple sessions established with another device, it
|
||||||
should use the session from which it last received and successfully
|
should use the session from which it last received and successfully
|
||||||
decrypted a message. For these purposes, a session that has not received
|
decrypted a message. For these purposes, a session that has not received
|
||||||
|
|
@ -1555,6 +1526,68 @@ maximum number of olm sessions that it will maintain for each device,
|
||||||
and expiring sessions on a Least Recently Used basis. The maximum number
|
and expiring sessions on a Least Recently Used basis. The maximum number
|
||||||
of olm sessions maintained per device should be at least 4.
|
of olm sessions maintained per device should be at least 4.
|
||||||
|
|
||||||
|
###### Validation of incoming decrypted events
|
||||||
|
|
||||||
|
{{% changed-in v="1.15" %}} Existing checks made more explicit, and checks for `sender_device_keys` added.
|
||||||
|
|
||||||
|
After decrypting an incoming encrypted event, clients MUST apply the
|
||||||
|
following checks:
|
||||||
|
|
||||||
|
1. The `sender` property in the decrypted content must match the
|
||||||
|
`sender` of the event.
|
||||||
|
2. The `keys.ed25519` property in the decrypted content must match
|
||||||
|
the `sender_key` property in the cleartext `m.room.encrypted`
|
||||||
|
event body.
|
||||||
|
3. The `recipient` property in the decrypted content must match
|
||||||
|
the user ID of the local user.
|
||||||
|
4. The `recipient_keys.ed25519` property in the decrypted content
|
||||||
|
must match the client device's [Ed25519 signing key](#device-keys).
|
||||||
|
5. Where `sender_device_keys` is present in the decrypted content:
|
||||||
|
1. `sender_device_keys.user_id` must also match the `sender`
|
||||||
|
of the event.
|
||||||
|
2. `sender_device_keys.keys.ed25519:<device_id>` must also match
|
||||||
|
the `sender_key` property in the cleartext `m.room.encrypted`
|
||||||
|
event body.
|
||||||
|
3. `sender_device_keys.keys.curve25519:<device_id>` must match
|
||||||
|
the Curve25519 key used to establish the Olm session.
|
||||||
|
4. The `sender_device_keys` structure must have a valid signature
|
||||||
|
from the key with ID `ed25519:<device_id>` (i.e., the sending
|
||||||
|
device's Ed25519 key).
|
||||||
|
|
||||||
|
Any event that does not comply with these checks MUST be discarded.
|
||||||
|
|
||||||
|
###### Verification of the sending user for incoming events
|
||||||
|
|
||||||
|
{{% added-in v="1.15" %}}
|
||||||
|
|
||||||
|
In addition, for each Olm session, clients MUST verify that the
|
||||||
|
Curve25519 key used to establish the Olm session does indeed belong
|
||||||
|
to the claimed `sender`. This requires a signed "device keys" structure
|
||||||
|
for that Curve25519 key, which can be obtained in one of two ways:
|
||||||
|
|
||||||
|
1. An Olm message may be received with a `sender_device_keys` property
|
||||||
|
in the decrypted content.
|
||||||
|
2. The keys are returned via a [`/keys/query`](#post_matrixclientv3keysquery)
|
||||||
|
request. Note that both the Curve25519 key **and** the Ed25519 key in
|
||||||
|
the returned device keys structure must match those used in an
|
||||||
|
Olm-encrypted event as above. (In particular, the Ed25519 key must
|
||||||
|
be present in the **encrypted** content of an Olm-encrypted event
|
||||||
|
to prevent an attacker from claiming another user's Curve25519 key
|
||||||
|
as their own.)
|
||||||
|
|
||||||
|
Ownership of the Curve25519 key is then established in one of two ways:
|
||||||
|
|
||||||
|
1. Via [cross-signing](#cross-signing). For this to be sufficient, the
|
||||||
|
device keys structure must be signed by the sender's self-signing key,
|
||||||
|
and that self-signing key must itself have been validated (either via
|
||||||
|
[explicit verification](#device-verification) or a "trust on first use" (TOFU) mechanism).
|
||||||
|
2. Via explicit verification of the device's Ed25519 signing key, as
|
||||||
|
contained in the device keys structure. This is no longer recommended.
|
||||||
|
|
||||||
|
A failure to complete these verifications does not necessarily mean that
|
||||||
|
the session is bogus; however it is the case that there is no proof that
|
||||||
|
the claimed sender is accurate, and the user should be warned accordingly.
|
||||||
|
|
||||||
###### Recovering from undecryptable messages
|
###### Recovering from undecryptable messages
|
||||||
|
|
||||||
Occasionally messages may be undecryptable by clients due to a variety
|
Occasionally messages may be undecryptable by clients due to a variety
|
||||||
|
|
|
||||||
88
data/api/client-server/definitions/olm_payload.yaml
Normal file
88
data/api/client-server/definitions/olm_payload.yaml
Normal file
|
|
@ -0,0 +1,88 @@
|
||||||
|
# Copyright 2025 The Matrix.org Foundation C.I.C
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
|
||||||
|
type: object
|
||||||
|
title: OlmPayload
|
||||||
|
description: |-
|
||||||
|
The plaintext payload of Olm message events.
|
||||||
|
properties:
|
||||||
|
type:
|
||||||
|
type: string
|
||||||
|
description: The type of the event.
|
||||||
|
content:
|
||||||
|
type: object
|
||||||
|
description: The event content.
|
||||||
|
sender:
|
||||||
|
type: string
|
||||||
|
description: The user ID of the event sender.
|
||||||
|
recipient:
|
||||||
|
type: string
|
||||||
|
description: The user ID of the intended event recipient.
|
||||||
|
recipient_keys:
|
||||||
|
description: The recipient's signing keys of the encrypted event.
|
||||||
|
$ref: "#/components/schemas/SigningKeys"
|
||||||
|
keys:
|
||||||
|
$ref: "#/components/schemas/SigningKeys"
|
||||||
|
description: The sender's signing keys of the encrypted event.
|
||||||
|
sender_device_keys:
|
||||||
|
$ref: device_keys.yaml
|
||||||
|
description: The sender's device keys.
|
||||||
|
x-addedInMatrixVersion: "1.15"
|
||||||
|
required:
|
||||||
|
- type
|
||||||
|
- content
|
||||||
|
- sender
|
||||||
|
- recipient
|
||||||
|
- recipient_keys
|
||||||
|
- keys
|
||||||
|
components:
|
||||||
|
schemas:
|
||||||
|
SigningKeys:
|
||||||
|
type: object
|
||||||
|
title: SigningKeys
|
||||||
|
description: Public keys used for an `m.olm.v1.curve25519-aes-sha2` event.
|
||||||
|
properties:
|
||||||
|
ed25519:
|
||||||
|
type: string
|
||||||
|
description: The Ed25519 public key encoded using unpadded base64.
|
||||||
|
required:
|
||||||
|
- ed25519
|
||||||
|
example: {
|
||||||
|
"type": "<type of the plaintext event>",
|
||||||
|
"content": "<content for the plaintext event>",
|
||||||
|
"sender": "<sender_user_id>",
|
||||||
|
"recipient": "<recipient_user_id>",
|
||||||
|
"recipient_keys": {
|
||||||
|
"ed25519": "<our_ed25519_key>"
|
||||||
|
},
|
||||||
|
"keys": {
|
||||||
|
"ed25519": "<sender_ed25519_key>"
|
||||||
|
},
|
||||||
|
"sender_device_keys": {
|
||||||
|
"algorithms": ["<supported>", "<algorithms>"],
|
||||||
|
"user_id": "<user_id>",
|
||||||
|
"device_id": "<device_id>",
|
||||||
|
"keys": {
|
||||||
|
"ed25519:<device_id>": "<sender_ed25519_key>",
|
||||||
|
"curve25519:<device_id>": "<sender_curve25519_key>"
|
||||||
|
},
|
||||||
|
"signatures": {
|
||||||
|
"<user_id>": {
|
||||||
|
"ed25519:<device_id>": "<device_signature>",
|
||||||
|
"ed25519:<ssk_id>": "<ssk_signature>",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue