-
-
Notifications
You must be signed in to change notification settings - Fork 115
Spec PR - MSC4147: Including device keys with Olm-encrypted events #2122
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
base: main
Are you sure you want to change the base?
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 @@ | ||
Include device keys with Olm-encrypted events as per [MSC4147](https://github.com/matrix-org/matrix-spec-proposals/pull/4147). |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1512,20 +1512,7 @@ message. | |
|
||
The plaintext payload is of the form: | ||
|
||
```json | ||
{ | ||
"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>" | ||
} | ||
} | ||
``` | ||
{{% definition path="api/client-server/definitions/olm_payload" %}} | ||
|
||
The type and content of the plaintext message event are given in the | ||
payload. | ||
|
@@ -1536,15 +1523,19 @@ 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. | ||
Clients must ensure that the sending 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. To perform | ||
this check, 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 under the `sender_device_keys` | ||
property. Additionally, clients MUST also verify the signature of the keys. | ||
If `sender_device_keys` is absent, clients MUST retrieve the sender's | ||
keys from [`/keys/query`](#post_matrixclientv3keysquery) instead. This | ||
will not allow them to verify key ownership if the sending device was | ||
logged out or had its keys reset since sending the event. Therefore, | ||
clients MUST populate the `sender_device_keys` property when sending | ||
events themselves. | ||
Comment on lines
+1526
to
+1538
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 find this very easy to follow, and I think it's conflating several checks. (The previous text also had this problem, but I think we're making it worse.) I think we probably want to replace this whole paragraph and the preceding one, with a couple of new h6-level sections to slot in before "Recovering from undecryptable messages". Something like this: Validation of incoming decrypted eventsAfter decrypting an incoming encrypted event, clients MUST apply the following checks:
Any event that does not comply with these checks MUST be discarded. Verification of the sending user for incoming eventsIn addition, for each Olm session, clients MUST verify that the Curve25519 key used to establish the Olm session does indeed belong to the claimed
Ownership of the Curve25519 key is then established in one of two ways:
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. Phew, that ended up longer than I expected. Sorry to pile this cleanup work onto this PR. @dkasak: would you mind checking that I haven't missed anything here? |
||
|
||
If a client has multiple sessions established with another device, it | ||
should use the session from which it last received and successfully | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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>", | ||
} | ||
} | ||
} | ||
} |
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 replaced the example with a schema because that allows us to reuse
device_keys.yaml
.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.
(and it's just generally Better. We're trying to phase out these old-style json blocks)