From 57d91c8ff545477129a243345f3495c5000bd522 Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Wed, 12 Aug 2020 23:35:51 +0300 Subject: [PATCH 1/9] Proposal for verifiable forwarded events Signed-off-by: Tulir Asokan --- proposals/2730-verifiable-forwarded-events.md | 215 ++++++++++++++++++ 1 file changed, 215 insertions(+) create mode 100644 proposals/2730-verifiable-forwarded-events.md diff --git a/proposals/2730-verifiable-forwarded-events.md b/proposals/2730-verifiable-forwarded-events.md new file mode 100644 index 00000000000..00afabb6565 --- /dev/null +++ b/proposals/2730-verifiable-forwarded-events.md @@ -0,0 +1,215 @@ +# Verifiable forwarded events +This is an alternative to [MSC2723](https://github.com/matrix-org/matrix-doc/pull/2723) +that handles the issue of faking forwards. + +## Proposal +The proposed solution is copying the entire federation event data, which allows +recipients to validate the signatures even if they are not in the origin room. + +As clients generally don't have access to signatures nor any way to validate +them, both sending and validating require server support. Sending is +implemented as a new endpoint, while validating happens automatically and the +server adds the validation result to the top-level `unsigned` object. + +### `PUT /_matrix/client/r0/rooms/{roomId}/event/{eventId}/forward/{targetRoomId}/{txnId}` +This endpoint requests the server to find `eventId` from `roomId` and forward +it to `targetRoomId`. The `txnId` behaves the same way as in the existing +`/send` endpoints. + +Only unredacted message events can be forwarded. If the given event ID is a +state event, a redaction or a redacted message event, the request will be +rejected with a standard error response using the code `M_NOT_FORWARDABLE`. + +To forward an event, the server creates a new event with the same event type +and normal top-level fields. To determine the content, the server has to +inspect the content of the source event: + +If the source event was already forwarded from some other room, the `content` +should simply be copied with no modifications. This means that an event +forwarded many times will only remember the original source, not any hops it +made on the way. + +If the source event was not a forward, but contains (invalid) data in the +`m.forwarded` key, the request will be rejected with `M_NOT_FORWARDABLE` like +other unforwardable events. This limitation also can be used to intentionally +mark messages as unforwardable (e.g. `"m.forwarded": {"allow": false}`). + +If the event does not contain `m.forwarded` at all, the server must generate a +new one. `m.forwarded` is an object that contains all the top-level keys of the +original event, except for `type`, `content` and `unsigned`. The following keys +are therefore at least required: + +* `auth_events` +* `prev_events` +* `room_id` +* `sender` +* `depth` +* `origin` +* `origin_server_ts` +* `hashes` +* `signatures` + +The following keys may also be present: + +* `prev_state`, may be present as an empty array even in non-state events +* `event_id`, only in v1 and v2 rooms + +Additionally, the server SHOULD include its own `unsigned` object in the +`m.forwarded` data that contains the `displayname` and `avatar_url` of the +sender. + +If the resulting event is too large, the request is rejected with a standard +error response using the code `M_TOO_LARGE`. Before rejecting the request, +servers MAY check if the event would be small enough without the profile data +in `unsigned`, and send the event without that data if it is. + +#### Example + +
+Source event (federation format) + +```json +{ + "auth_events": [ + "$wChClfXonLE8RZikJ446AXvRpbh_JjDK8sNpMpZbqPs", + "$RaXN_RayMvoEmMnUHlZScIdSpShT8zggd4p6qcQk9L8", + "$kFop6R7AohiYSTh_ijUctTujdVTg3rwBPdaMLeZMNrg" + ], + "prev_events": [ + "$pIFO6_sI1Ul_3jPixtbnJn_h0Pe0yB__TJD_VCW9Q-Q" + ], + "type": "m.room.message", + "room_id": "!FIIWlyqwNLyMAtmRBF:maunium.net", + "sender": "@tulir:maunium.net", + "content": { + "msgtype": "m.text", + "body": "test" + }, + "depth": 115, + "prev_state": [], + "origin": "maunium.net", + "origin_server_ts": 1597257769634, + "hashes": { + "sha256": "xBR7NmH2WQBx0auQWEDEYNbcPf9ATlDSwkv9EBxueMI" + }, + "signatures": { + "maunium.net": { + "ed25519:a_xxeS": "cc9XnH9ByO7yadC6CdMhh3c/TN1tQ9FiZdKYyRDi4Og1dZMylmBM9uSI7c4GUEqswLBLxW5DTFU3n7vMHAGhAw" + } + }, + "unsigned": { + "age_ts": 1597257769634 + } +} +``` + +
+
+Forwarded event (client format) + +```json +{ + "type": "m.room.message", + "room_id": "!eVRGrjZQgJZGNllOkw:grin.hu", + "event_id": "$r8h8W9A5KS8D65_Df8fwLkTe7aqOm48KmyaJ6tRNAmE", + "sender": "@tulir:maunium.net", + "origin_server_ts": 1597263764138, + "content": { + "msgtype": "m.text", + "body": "test", + "m.forwarded": { + "auth_events": [ + "$wChClfXonLE8RZikJ446AXvRpbh_JjDK8sNpMpZbqPs", + "$RaXN_RayMvoEmMnUHlZScIdSpShT8zggd4p6qcQk9L8", + "$kFop6R7AohiYSTh_ijUctTujdVTg3rwBPdaMLeZMNrg" + ], + "prev_events": [ + "$pIFO6_sI1Ul_3jPixtbnJn_h0Pe0yB__TJD_VCW9Q-Q" + ], + "room_id": "!FIIWlyqwNLyMAtmRBF:maunium.net", + "sender": "@tulir:maunium.net", + "depth": 115, + "prev_state": [], + "origin": "maunium.net", + "origin_server_ts": 1597257769634, + "hashes": { + "sha256": "xBR7NmH2WQBx0auQWEDEYNbcPf9ATlDSwkv9EBxueMI" + }, + "signatures": { + "maunium.net": { + "ed25519:a_xxeS": "cc9XnH9ByO7yadC6CdMhh3c/TN1tQ9FiZdKYyRDi4Og1dZMylmBM9uSI7c4GUEqswLBLxW5DTFU3n7vMHAGhAw" + } + }, + "unsigned": { + "displayname": "tulir", + "avatar_url": "mxc://maunium.net/jdlSfvudiMSmcRrleeiYjjFO" + } + } + }, + "unsigned": { + "m.forwarded": { + "valid": true, + "event_id": "$BfxMy-oNFOeE0eFt6r-l3h7MtwNVIX0GrructyJq1wA" + } + } +} +``` + +
+ +### Receiving events with `m.forwarded` +When a server receives a message event that has the `m.forwarded` key in its +`content`, the server MUST use the data to validate the signatures, then add a +`m.forwarded` key to the top-level `unsigned` of the event with the validation +information. + +#### Validating signatures +To validate a signature, the server should start with the `m.forwarded` object +and modify it as follows: + +* If the object is missing any of the required keys, mark it as invalid without + trying to validate it. +* Remove the `unsigned` key (if present). +* Copy `type` from the top level into `m.forwarded`. +* Make a copy of the top-level `content`, remove `m.forwarded` and put it in + the `m.forwarded`. +* Using the result object, validate the hashes and signatures on the event, as + specified in sections 26.2 through 26.4 of the server-server specification: + https://matrix.org/docs/spec/server_server/r0.1.4#validating-hashes-and-signatures-on-received-events + +#### Unsigned `m.forwarded` object +For any message event with `m.fowarded` in the content, the server MUST add or +override the `m.forwarded` key in the `unsigned` object of the event. The key +MUST be an object that contains `valid` and `event_id`. + +If the `m.forwarded` object was valid and the signatures were validated, the +`valid` value should be `true`. In any other case (invalid signature, bogus +data, etc), the value should be `false`. + +In v1 and v2 rooms, the `event_id` is copied from the `m.forwarded` object in +`content`. In v3 and up, the `event_id` is based on the reference hash that was +validated in the previous section. Copying the event ID in v1/v2 rooms is for +convenience of clients: they only need to look in one place regardless of the +room version. + +## Potential issues +* This is not as simple as MSC2723 and requires server support +* Events with bogus data in `m.forwarded` can't be forwarded +* Events that are close to the 64 KiB size limit can't be forwarded. MSC2723 + has the same problem, but this proposal has even more extra data. The amount + of extra data in both proposals is rather low (<1kb), so this should not be + a problem in practice + +## Alternatives +Instead of an endpoint for sending a forward, the new endpoint could be used to +generate the forward content and leave sending it up to the client with the +normal /send endpoint. However, this is an extra roundtrip for the client and +it is not clear if there are any significant benefits in doing so. + +## Unstable prefix +While this MSC is not in a released version of the spec, implementations should +use `net.maunium.msc2730` as a prefix and as a `unstable_features` flag in the +`/versions` endpoint. + +* `PUT /_matrix/client/unstable/net.maunium.msc2730/rooms/{roomId}/event/{eventId}/forward/{targetRoomId}/{txnId}` +* `net.maunium.msc2730.forwarded` From 3987938dc02149f8bda986e04bee409851466585 Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Thu, 13 Aug 2020 01:20:41 +0300 Subject: [PATCH 2/9] Add notes about client behavior and update other things Signed-off-by: Tulir Asokan --- proposals/2730-verifiable-forwarded-events.md | 69 +++++++++++-------- 1 file changed, 42 insertions(+), 27 deletions(-) diff --git a/proposals/2730-verifiable-forwarded-events.md b/proposals/2730-verifiable-forwarded-events.md index 00afabb6565..d0ea7933441 100644 --- a/proposals/2730-verifiable-forwarded-events.md +++ b/proposals/2730-verifiable-forwarded-events.md @@ -24,19 +24,20 @@ To forward an event, the server creates a new event with the same event type and normal top-level fields. To determine the content, the server has to inspect the content of the source event: -If the source event was already forwarded from some other room, the `content` -should simply be copied with no modifications. This means that an event -forwarded many times will only remember the original source, not any hops it -made on the way. - -If the source event was not a forward, but contains (invalid) data in the -`m.forwarded` key, the request will be rejected with `M_NOT_FORWARDABLE` like -other unforwardable events. This limitation also can be used to intentionally -mark messages as unforwardable (e.g. `"m.forwarded": {"allow": false}`). - -If the event does not contain `m.forwarded` at all, the server must generate a -new one. `m.forwarded` is an object that contains all the top-level keys of the -original event, except for `type`, `content` and `unsigned`. The following keys +* If the source event was already forwarded from some other room, the `content` + should simply be copied with no modifications. This means that an event + forwarded many times will only remember the original source, not any hops it + made on the way. +* If the source event was not a forward, but contains (invalid) data in the + `m.forwarded` key, the request will be rejected with `M_NOT_FORWARDABLE` like + other unforwardable events. This limitation also can be used to intentionally + mark messages as unforwardable (e.g. `"m.forwarded": {"allow": false}`). +* If the source event does not contain `m.forwarded` at all, the server must + generate a new one. After generating the object, it is placed in `content` of + the new event along with everything from the `content` of the source event. + +`m.forwarded` is an object that contains all the top-level keys of the original +event, except for `type`, `content` and `unsigned`. The following keys are therefore at least required: * `auth_events` @@ -54,9 +55,9 @@ The following keys may also be present: * `prev_state`, may be present as an empty array even in non-state events * `event_id`, only in v1 and v2 rooms -Additionally, the server SHOULD include its own `unsigned` object in the -`m.forwarded` data that contains the `displayname` and `avatar_url` of the -sender. +Additionally, when generating `m.forwarded` objects, the server SHOULD include +its own `unsigned` object in the `m.forwarded` data that contains the +`displayname` and `avatar_url` of the sender. If the resulting event is too large, the request is rejected with a standard error response using the code `M_TOO_LARGE`. Before rejecting the request, @@ -173,14 +174,14 @@ and modify it as follows: * Copy `type` from the top level into `m.forwarded`. * Make a copy of the top-level `content`, remove `m.forwarded` and put it in the `m.forwarded`. -* Using the result object, validate the hashes and signatures on the event, as - specified in sections 26.2 through 26.4 of the server-server specification: - https://matrix.org/docs/spec/server_server/r0.1.4#validating-hashes-and-signatures-on-received-events +* Using the result object, validate the signature, calculate the reference hash + and check the content hash of the event as specified in sections 26.2 through + 26.4 of the server-server specification: https://matrix.org/docs/spec/server_server/r0.1.4#validating-hashes-and-signatures-on-received-events #### Unsigned `m.forwarded` object -For any message event with `m.fowarded` in the content, the server MUST add or +For any message event with `m.forwarded` in the content, the server MUST add or override the `m.forwarded` key in the `unsigned` object of the event. The key -MUST be an object that contains `valid` and `event_id`. +MUST be an object that contains the keys `valid` and `event_id`. If the `m.forwarded` object was valid and the signatures were validated, the `valid` value should be `true`. In any other case (invalid signature, bogus @@ -188,19 +189,33 @@ data, etc), the value should be `false`. In v1 and v2 rooms, the `event_id` is copied from the `m.forwarded` object in `content`. In v3 and up, the `event_id` is based on the reference hash that was -validated in the previous section. Copying the event ID in v1/v2 rooms is for +calculated in the previous section. Copying the event ID in v1/v2 rooms is for convenience of clients: they only need to look in one place regardless of the room version. +## Client behavior +Clients SHOULD NOT trust forward metadata in the event content without an +explicit `"valid": true` in the unsigned `m.forwarded` object. Additionally, +clients SHOULD make sure the server supports this proposal before trusting +forwards even if the `valid` flag is present. + +Not trusting forward metadata does not necessarily mean it must be completely +ignored. For example, clients could render the event as a forward, but include +a notice saying it's unverified. + ## Potential issues -* This is not as simple as MSC2723 and requires server support -* Events with bogus data in `m.forwarded` can't be forwarded +* This is not as simple as MSC2723 and requires server support. +* Events with bogus data in `m.forwarded` can't be forwarded. * Events that are close to the 64 KiB size limit can't be forwarded. MSC2723 has the same problem, but this proposal has even more extra data. The amount of extra data in both proposals is rather low (<1kb), so this should not be - a problem in practice + a problem in practice. +* Encrypted events forwarded to other rooms won't be decryptable. Clients + should probably either prevent forwarding completely or only allow forwarding + to the same room for encrypted events. ## Alternatives +### Endpoint behavior Instead of an endpoint for sending a forward, the new endpoint could be used to generate the forward content and leave sending it up to the client with the normal /send endpoint. However, this is an extra roundtrip for the client and @@ -211,5 +226,5 @@ While this MSC is not in a released version of the spec, implementations should use `net.maunium.msc2730` as a prefix and as a `unstable_features` flag in the `/versions` endpoint. -* `PUT /_matrix/client/unstable/net.maunium.msc2730/rooms/{roomId}/event/{eventId}/forward/{targetRoomId}/{txnId}` -* `net.maunium.msc2730.forwarded` +* `PUT /_matrix/client/unstable/net.maunium.msc2730/rooms/{roomId}/event/{eventId}/forward/{targetRoomId}/{txnId}` as the endpoint +* `net.maunium.msc2730.forwarded` instead of `m.forwarded` in `content` and `unsigned` From 01cb1ab7af94ce9271473fd3b0e92105f36b7a6b Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Thu, 13 Aug 2020 01:32:57 +0300 Subject: [PATCH 3/9] Add request and response format and example Signed-off-by: Tulir Asokan --- proposals/2730-verifiable-forwarded-events.md | 25 ++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/proposals/2730-verifiable-forwarded-events.md b/proposals/2730-verifiable-forwarded-events.md index d0ea7933441..2a677c75c69 100644 --- a/proposals/2730-verifiable-forwarded-events.md +++ b/proposals/2730-verifiable-forwarded-events.md @@ -13,8 +13,8 @@ server adds the validation result to the top-level `unsigned` object. ### `PUT /_matrix/client/r0/rooms/{roomId}/event/{eventId}/forward/{targetRoomId}/{txnId}` This endpoint requests the server to find `eventId` from `roomId` and forward -it to `targetRoomId`. The `txnId` behaves the same way as in the existing -`/send` endpoints. +it to `targetRoomId`. The `txnId` behaves the same way as in the `/send` +endpoint. The request body is an empty JSON object. Only unredacted message events can be forwarded. If the given event ID is a state event, a redaction or a redacted message event, the request will be @@ -36,7 +36,7 @@ inspect the content of the source event: generate a new one. After generating the object, it is placed in `content` of the new event along with everything from the `content` of the source event. -`m.forwarded` is an object that contains all the top-level keys of the original +`m.forwarded` is an object that contains all the top-level keys of the source event, except for `type`, `content` and `unsigned`. The following keys are therefore at least required: @@ -64,6 +64,9 @@ error response using the code `M_TOO_LARGE`. Before rejecting the request, servers MAY check if the event would be small enough without the profile data in `unsigned`, and send the event without that data if it is. +Similar to the `/send` endpoint, this endpoint returns an object containing the +`event_id` of the forwarded event. + #### Example
@@ -105,6 +108,22 @@ in `unsigned`, and send the event without that data if it is. ```
+ +Request: + +``` +PUT /_matrix/client/r0/rooms/!FIIWlyqwNLyMAtmRBF:maunium.net/event/$BfxMy-oNFOeE0eFt6r-l3h7MtwNVIX0GrructyJq1wA/forward/!eVRGrjZQgJZGNllOkw:grin.hu/myTxnId1 +{} +``` + +Response: + +```json +{ + "event_id": "$r8h8W9A5KS8D65_Df8fwLkTe7aqOm48KmyaJ6tRNAmE" +} +``` +
Forwarded event (client format) From fa6132478b0407ee1c19980397d971dc8cb0d08e Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Thu, 13 Aug 2020 01:38:40 +0300 Subject: [PATCH 4/9] Move endpoint paragraphs around Signed-off-by: Tulir Asokan --- proposals/2730-verifiable-forwarded-events.md | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/proposals/2730-verifiable-forwarded-events.md b/proposals/2730-verifiable-forwarded-events.md index 2a677c75c69..c4351db6fd9 100644 --- a/proposals/2730-verifiable-forwarded-events.md +++ b/proposals/2730-verifiable-forwarded-events.md @@ -20,6 +20,15 @@ Only unredacted message events can be forwarded. If the given event ID is a state event, a redaction or a redacted message event, the request will be rejected with a standard error response using the code `M_NOT_FORWARDABLE`. +If the generated event is too large, the request is rejected with a standard +error response using the code `M_TOO_LARGE`. Before rejecting the request, +servers MAY check if the event would be small enough without the profile data +in `unsigned`, and send the event without that data if it is. + +Similar to the `/send` endpoint, this endpoint returns an object containing the +`event_id` of the forwarded event. + +#### Generating forwarded event To forward an event, the server creates a new event with the same event type and normal top-level fields. To determine the content, the server has to inspect the content of the source event: @@ -36,9 +45,10 @@ inspect the content of the source event: generate a new one. After generating the object, it is placed in `content` of the new event along with everything from the `content` of the source event. +##### Generating `m.forwarded` object `m.forwarded` is an object that contains all the top-level keys of the source -event, except for `type`, `content` and `unsigned`. The following keys -are therefore at least required: +event, except for `type`, `content` and `unsigned`. The following keys are +therefore at least required: * `auth_events` * `prev_events` @@ -59,14 +69,6 @@ Additionally, when generating `m.forwarded` objects, the server SHOULD include its own `unsigned` object in the `m.forwarded` data that contains the `displayname` and `avatar_url` of the sender. -If the resulting event is too large, the request is rejected with a standard -error response using the code `M_TOO_LARGE`. Before rejecting the request, -servers MAY check if the event would be small enough without the profile data -in `unsigned`, and send the event without that data if it is. - -Similar to the `/send` endpoint, this endpoint returns an object containing the -`event_id` of the forwarded event. - #### Example
From 548a5a307cb9a33297fcd7d49e61ff4c41b06c5d Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Thu, 13 Aug 2020 11:06:55 +0300 Subject: [PATCH 5/9] Add unstable prefix for error code --- proposals/2730-verifiable-forwarded-events.md | 1 + 1 file changed, 1 insertion(+) diff --git a/proposals/2730-verifiable-forwarded-events.md b/proposals/2730-verifiable-forwarded-events.md index c4351db6fd9..75651de12aa 100644 --- a/proposals/2730-verifiable-forwarded-events.md +++ b/proposals/2730-verifiable-forwarded-events.md @@ -249,3 +249,4 @@ use `net.maunium.msc2730` as a prefix and as a `unstable_features` flag in the * `PUT /_matrix/client/unstable/net.maunium.msc2730/rooms/{roomId}/event/{eventId}/forward/{targetRoomId}/{txnId}` as the endpoint * `net.maunium.msc2730.forwarded` instead of `m.forwarded` in `content` and `unsigned` +* `NET.MAUNIUM.MSC2730_NOT_FORWARDABLE` instead of `M_NOT_FORWARDABLE` as the error code From 823dbf7ec33be28fc554cb8bee9f4c4bd54028c6 Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Thu, 13 Aug 2020 13:10:09 +0300 Subject: [PATCH 6/9] Include source room version in forwarded events --- proposals/2730-verifiable-forwarded-events.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/proposals/2730-verifiable-forwarded-events.md b/proposals/2730-verifiable-forwarded-events.md index 75651de12aa..b913085caba 100644 --- a/proposals/2730-verifiable-forwarded-events.md +++ b/proposals/2730-verifiable-forwarded-events.md @@ -65,9 +65,10 @@ The following keys may also be present: * `prev_state`, may be present as an empty array even in non-state events * `event_id`, only in v1 and v2 rooms -Additionally, when generating `m.forwarded` objects, the server SHOULD include -its own `unsigned` object in the `m.forwarded` data that contains the -`displayname` and `avatar_url` of the sender. +Additionally, the server MUST include an `unsigned` object, containing a +`room_version` field that specifies the version of the source room. The server +SHOULD also include the sender's profile metadata in the unsigned object under +the fields `displayname` and `avatar_url`. #### Example From 018c92d39b853030fdb4bd97b587cef28d17eb19 Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Thu, 24 Dec 2020 13:35:17 +0200 Subject: [PATCH 7/9] Add support for encrypted events Signed-off-by: Tulir Asokan --- proposals/2730-verifiable-forwarded-events.md | 35 ++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/proposals/2730-verifiable-forwarded-events.md b/proposals/2730-verifiable-forwarded-events.md index b913085caba..f6f7c25d5af 100644 --- a/proposals/2730-verifiable-forwarded-events.md +++ b/proposals/2730-verifiable-forwarded-events.md @@ -14,7 +14,10 @@ server adds the validation result to the top-level `unsigned` object. ### `PUT /_matrix/client/r0/rooms/{roomId}/event/{eventId}/forward/{targetRoomId}/{txnId}` This endpoint requests the server to find `eventId` from `roomId` and forward it to `targetRoomId`. The `txnId` behaves the same way as in the `/send` -endpoint. The request body is an empty JSON object. +endpoint. The request body has an optional `decryption_keys` field that will be +copied to `content`->`m.forwarded`->`unsigned` in the resulting event when +present. The content of the `decryption_keys` object varies based on whether or +not the target room is encrypted, see the "Encrypted events" section below. Only unredacted message events can be forwarded. If the given event ID is a state event, a redaction or a redacted message event, the request will be @@ -215,6 +218,30 @@ calculated in the previous section. Copying the event ID in v1/v2 rooms is for convenience of clients: they only need to look in one place regardless of the room version. +### Encrypted events +In some cases, users may want to forward encrypted messages to rooms with users +who are not in the origin room. In order to allow everyone in the recipient +room to decrypt the forwarded message, the keys must be sent with the message. +However, only keys for the message being forwarded should be sent, any other +messages in the origin room must not be decryptable with those keys. + +To achieve this, the user forwarding the message includes the message-specific +symmetric AES and HMAC keys (see [Message encryption] in the Megolm spec). Each +of the keys are encoded as unpadded base64 and placed in the `aes_key`, +`hmac_key` and `aes_iv` fields in the `decryption_keys` object in the forward +request. + +[Message encryption]: https://gitlab.matrix.org/matrix-org/olm/-/blob/master/docs/megolm.md#message-encryption + +When forwarding encrypted messages to encrypted rooms, the `decryption_keys` +object is encrypted the same way `content` would be in normal messages. +Recipient clients should check which fields are present in the `decryption_keys` +object to determine whether or not it is encrypted. + +The decryption keys should be included even if forwarding a message to the same +room, as there may be new users in the room who didn't receive keys to old +messages. + ## Client behavior Clients SHOULD NOT trust forward metadata in the event content without an explicit `"valid": true` in the unsigned `m.forwarded` object. Additionally, @@ -225,6 +252,12 @@ Not trusting forward metadata does not necessarily mean it must be completely ignored. For example, clients could render the event as a forward, but include a notice saying it's unverified. +When receiving forwarded encrypted events, clients should treat the message +like they treat forwarded keys, i.e. not confirmed to originate from the user. + +Clients may discourage users from forwarding encrypted messages to unencrypted +rooms, as that would leak the message content to the servers. + ## Potential issues * This is not as simple as MSC2723 and requires server support. * Events with bogus data in `m.forwarded` can't be forwarded. From fc9ea6a6cad5b602c41f8e61da81f189b2ffa4ba Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Thu, 24 Dec 2020 13:37:45 +0200 Subject: [PATCH 8/9] Remove potential issue that isn't an issue anymore Signed-off-by: Tulir Asokan --- proposals/2730-verifiable-forwarded-events.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/proposals/2730-verifiable-forwarded-events.md b/proposals/2730-verifiable-forwarded-events.md index f6f7c25d5af..21679f887b3 100644 --- a/proposals/2730-verifiable-forwarded-events.md +++ b/proposals/2730-verifiable-forwarded-events.md @@ -265,9 +265,6 @@ rooms, as that would leak the message content to the servers. has the same problem, but this proposal has even more extra data. The amount of extra data in both proposals is rather low (<1kb), so this should not be a problem in practice. -* Encrypted events forwarded to other rooms won't be decryptable. Clients - should probably either prevent forwarding completely or only allow forwarding - to the same room for encrypted events. ## Alternatives ### Endpoint behavior From a0b3ef6dc3807f5cf9c5462a35578595364ed5b8 Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Thu, 7 Jan 2021 13:34:49 +0200 Subject: [PATCH 9/9] Add note about relation metadata in forwarded events Signed-off-by: Tulir Asokan --- proposals/2730-verifiable-forwarded-events.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/proposals/2730-verifiable-forwarded-events.md b/proposals/2730-verifiable-forwarded-events.md index 21679f887b3..01cfb684ac8 100644 --- a/proposals/2730-verifiable-forwarded-events.md +++ b/proposals/2730-verifiable-forwarded-events.md @@ -258,6 +258,12 @@ like they treat forwarded keys, i.e. not confirmed to originate from the user. Clients may discourage users from forwarding encrypted messages to unencrypted rooms, as that would leak the message content to the servers. +If a forwarded event contains relation metadata such as a reply, clients should +not display it to users. This behavior is consistent with other platforms (e.g. +Telegram and WhatsApp) and removes any problems if some users can't get the +relation target event. The existence of reply metadata may still be used to +remove reply fallbacks. + ## Potential issues * This is not as simple as MSC2723 and requires server support. * Events with bogus data in `m.forwarded` can't be forwarded.