From ef50deccd57847b908314fb82cc150f3ac226f8e Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Fri, 12 Jun 2026 15:39:42 +0100 Subject: [PATCH 1/3] Use OpenAPI definition for `EncryptedFile`. ... instead of the ad-hoc table we have currently. --- content/appendices.md | 8 +- .../modules/end_to_end_encryption.md | 34 ++------ .../definitions/encrypted_file.yaml | 84 +++++++++++++++++++ 3 files changed, 99 insertions(+), 27 deletions(-) create mode 100644 data/api/client-server/definitions/encrypted_file.yaml diff --git a/content/appendices.md b/content/appendices.md index 703dd051..0e87fe8b 100644 --- a/content/appendices.md +++ b/content/appendices.md @@ -12,7 +12,7 @@ Specifically, where RFC 4648 requires that encoded data be padded to a multiple of four characters using `=` characters, unpadded Base64 omits this padding. -For reference, RFC 4648 uses the following alphabet for Base 64: +For reference, RFC 4648 uses the following alphabet for Base64: Value Encoding Value Encoding Value Encoding Value Encoding 0 A 17 R 34 i 51 z @@ -47,6 +47,12 @@ When decoding Base64, implementations SHOULD accept input with or without padding characters wherever possible, to ensure maximum interoperability. +### URL-safe unpadded Base64 + +URL-safe unpadded Base64 is identical to standard unpadded Base64, except that +it uses `-` (minus) as the 62nd character in the alphabet, and `_` (underscore) +as the 63rd. + ## Binary data In some cases it is necessary to encapsulate binary data, for example, 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 ec86203d..88a97bdd 100644 --- a/content/client-server-api/modules/end_to_end_encryption.md +++ b/content/client-server-api/modules/end_to_end_encryption.md @@ -355,7 +355,7 @@ key, and encrypts the file using AES-CTR. The counter is 64 bits long, starting at 0 and prefixed by a random 64-bit Initialization Vector (IV), which together form a 128-bit unique counter block. -Clients MUST generate both the AES key and IV using a cryptographically +Clients MUST generate both the AES key and IV using a cryptographically secure random source and MUST NOT use the same key or IV multiple times. The latter 64 bits of the 128-bit counter block MUST start at zero. @@ -385,31 +385,11 @@ Key](https://tools.ietf.org/html/rfc7517#appendix-A.3) format, with a ###### Extensions to `m.room.message` msgtypes This module adds `file` and `thumbnail_file` properties, of type -`EncryptedFile`, to `m.room.message` msgtypes that reference files, such -as [m.file](#mfile) and [m.image](#mimage), replacing the `url` and `thumbnail_url` -properties. +[`EncryptedFile`](#definition-encryptedfile), to `m.room.message` msgtypes that +reference files, such as [m.file](#mfile) and [m.image](#mimage), replacing the +`url` and `thumbnail_url` properties. -`EncryptedFile` - -| Parameter | Type | Description | -|-----------|------------------|------------------------------------------------------------------------------------------------| -| url | string | **Required.** The URL to the file. | -| key | JWK | **Required.** A [JSON Web Key](https://tools.ietf.org/html/rfc7517#appendix-A.3) object. | -| iv | string | **Required.** The 128-bit unique counter block used by AES-CTR, encoded as unpadded base64. | -| hashes | {string: string} | **Required.** A map from an algorithm name to a hash of the ciphertext, encoded as unpadded base64. Clients MUST support the SHA-256 hash, which uses the key `sha256`. | -| v | string | **Required.** Version of the encrypted attachment's protocol. Must be `v2`. | - -`JWK` - -| Parameter | Type | Description | -| --------- |----------|--------------------------------------------------------------------------------------------------------------------------| -| kty | string | **Required.** Key type. Must be `oct`. | -| key_ops | [string] | **Required.** Key operations. Must at least contain `encrypt` and `decrypt`. | -| alg | string | **Required.** Algorithm. Must be `A256CTR`. | -| k | string | **Required.** The key, encoded as urlsafe unpadded base64. | -| ext | boolean | **Required.** Extractable. Must be `true`. This is a [W3C extension](https://w3c.github.io/webcrypto/#iana-section-jwk). | - -Example: +Example `m.room.message` event containing an encrypted image: ```json { @@ -470,6 +450,8 @@ Example: } ``` +{{% definition path="api/client-server/definitions/encrypted_file" %}} + #### Device verification Before Alice sends Bob encrypted data, or trusts data received from him, @@ -764,7 +746,7 @@ The process between Alice and Bob verifying each other would be: 15. Assuming they match, Alice and Bob's devices each calculate Message Authentication Codes (MACs) for: * {{% changed-in v="1.18" %}} Each of the keys that they wish the other user - to verify (usually their device ed25519 key and their master signing key, + to verify (usually their device ed25519 key and their master signing key, see below). The master signing key SHOULD be included when two different users are verifying each other. Verifying individual devices of other users is deprecated. diff --git a/data/api/client-server/definitions/encrypted_file.yaml b/data/api/client-server/definitions/encrypted_file.yaml new file mode 100644 index 00000000..5bb7af4c --- /dev/null +++ b/data/api/client-server/definitions/encrypted_file.yaml @@ -0,0 +1,84 @@ +# Copyright 2018-2026 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: EncryptedFile +description: | + Information on an encrypted media blob, including its location in the + [content repository](/client-server-api/#content-repository), and the keys + necessary to decrypt it. +properties: + url: + type: string + format: mx-mxc-uri + description: The URL to the file. + example: "mxc://example.org/FHyPlCeYUSFFxlgbQYZmoEoe" + key: + type: object + title: JWK + description: A [JSON Web Key](https://tools.ietf.org/html/rfc7517#appendix-A.3) object. + properties: + kty: + type: string + description: Key type. Must be `oct`. + example: "oct" + key_ops: + type: array + items: + type: string + description: Key operations. Must at least contain `encrypt` and `decrypt`. + example: ["encrypt", "decrypt"] + alg: + type: string + description: Algorithm. Must be `A256CTR`. + example: A256CTR + k: + type: string + description: The key, encoded as [URL-safe unpadded Base64](/appendices/#url-safe-unpadded-base64). + example: "aWF6-32KGYaC3A_FEUCk1Bt0JA37zP0wrStgmdCaW-0" + ext: + type: boolean + description: "Extractable. Must be `true`. This is a [W3C extension](https://w3c.github.io/webcrypto/#iana-section-jwk)." + example: true + required: + - kty + - key_ops + - alg + - k + - ext + iv: + type: string + description: The 128-bit unique counter block used by AES-CTR, encoded as [unpadded Base64](/appendices/#unpadded-base64). + example: "w+sE15fzSc0AAAAAAAAAAA" + hashes: + type: object + title: EncryptedFileHashes + description: + A map from an algorithm name to a hash of the ciphertext. Clients MUST support the SHA-256 hash, which uses the key `sha256`. + properties: + sha256: + type: string + description: The hash of the ciphertext. encoded as [unpadded Base64](/appendices/#unpadded-base64). + example: "fdSLu/YkRx3Wyh3KQabP3rd6+SFiKg5lsJZQHtkSAYA" + required: ['sha256'] + v: + type: string + description: Version of the encrypted attachment’s protocol. Must be `v2`. + example: v2 +required: + - url + - key + - iv + - hashes + - v From 515279709a671f8da42d5c3487befea7fc4ab3a2 Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Fri, 12 Jun 2026 15:41:05 +0100 Subject: [PATCH 2/3] Links to EncryptedFile --- .../schema/core-event-schema/msgtype_infos/image_info.yaml | 3 +-- data/event-schemas/schema/m.room.message$m.audio.yaml | 4 +--- data/event-schemas/schema/m.room.message$m.file.yaml | 7 ++----- data/event-schemas/schema/m.room.message$m.image.yaml | 4 +--- data/event-schemas/schema/m.room.message$m.location.yaml | 3 +-- data/event-schemas/schema/m.room.message$m.video.yaml | 7 ++----- 6 files changed, 8 insertions(+), 20 deletions(-) diff --git a/data/event-schemas/schema/core-event-schema/msgtype_infos/image_info.yaml b/data/event-schemas/schema/core-event-schema/msgtype_infos/image_info.yaml index 42e4540d..c19eca15 100644 --- a/data/event-schemas/schema/core-event-schema/msgtype_infos/image_info.yaml +++ b/data/event-schemas/schema/core-event-schema/msgtype_infos/image_info.yaml @@ -27,8 +27,7 @@ properties: pattern: "^mxc:\\/\\/" thumbnail_file: description: |- - Information on the encrypted thumbnail file, as specified in - [End-to-end encryption](/client-server-api/#sending-encrypted-attachments). + An [EncryptedFile](/client-server-api/#definition-encryptedfile) structure. Only present if the thumbnail is encrypted. title: EncryptedFile type: object diff --git a/data/event-schemas/schema/m.room.message$m.audio.yaml b/data/event-schemas/schema/m.room.message$m.audio.yaml index d138de38..462933c9 100644 --- a/data/event-schemas/schema/m.room.message$m.audio.yaml +++ b/data/event-schemas/schema/m.room.message$m.audio.yaml @@ -58,9 +58,7 @@ properties: pattern: "^mxc:\\/\\/" file: description: |- - Required if the file is encrypted. Information on the encrypted - file, as specified in - [End-to-end encryption](/client-server-api/#sending-encrypted-attachments). + Required if the file is encrypted. An [EncryptedFile](/client-server-api/#definition-encryptedfile) structure. title: EncryptedFile type: object required: diff --git a/data/event-schemas/schema/m.room.message$m.file.yaml b/data/event-schemas/schema/m.room.message$m.file.yaml index 296118e0..ca9a6ceb 100644 --- a/data/event-schemas/schema/m.room.message$m.file.yaml +++ b/data/event-schemas/schema/m.room.message$m.file.yaml @@ -48,8 +48,7 @@ properties: pattern: "^mxc:\\/\\/" thumbnail_file: description: |- - Information on the encrypted thumbnail file, as specified in - [End-to-end encryption](/client-server-api/#sending-encrypted-attachments). + An [EncryptedFile](/client-server-api/#definition-encryptedfile) structure. Only present if the thumbnail is encrypted. title: EncryptedFile type: object @@ -72,9 +71,7 @@ properties: pattern: "^mxc:\\/\\/" file: description: |- - Required if the file is encrypted. Information on the encrypted - file, as specified in - [End-to-end encryption](/client-server-api/#sending-encrypted-attachments). + Required if the file is encrypted. An [EncryptedFile](/client-server-api/#definition-encryptedfile) structure. title: EncryptedFile type: object required: diff --git a/data/event-schemas/schema/m.room.message$m.image.yaml b/data/event-schemas/schema/m.room.message$m.image.yaml index 2cb7371d..f36d5f7d 100644 --- a/data/event-schemas/schema/m.room.message$m.image.yaml +++ b/data/event-schemas/schema/m.room.message$m.image.yaml @@ -48,9 +48,7 @@ properties: pattern: "^mxc:\\/\\/" file: description: |- - Required if the file is encrypted. Information on the encrypted - file, as specified in - [End-to-end encryption](/client-server-api/#sending-encrypted-attachments). + Required if the file is encrypted. An [EncryptedFile](/client-server-api/#definition-encryptedfile) structure. title: EncryptedFile type: object required: diff --git a/data/event-schemas/schema/m.room.message$m.location.yaml b/data/event-schemas/schema/m.room.message$m.location.yaml index 3f1b9c1c..507f6a7f 100644 --- a/data/event-schemas/schema/m.room.message$m.location.yaml +++ b/data/event-schemas/schema/m.room.message$m.location.yaml @@ -31,8 +31,7 @@ properties: pattern: "^mxc:\\/\\/" thumbnail_file: description: |- - Information on the encrypted thumbnail file, as specified in - [End-to-end encryption](/client-server-api/#sending-encrypted-attachments). + An [EncryptedFile](/client-server-api/#definition-encryptedfile) structure. Only present if the thumbnail is encrypted. title: EncryptedFile type: object diff --git a/data/event-schemas/schema/m.room.message$m.video.yaml b/data/event-schemas/schema/m.room.message$m.video.yaml index 5ff9c250..0f3c5159 100644 --- a/data/event-schemas/schema/m.room.message$m.video.yaml +++ b/data/event-schemas/schema/m.room.message$m.video.yaml @@ -58,8 +58,7 @@ properties: pattern: "^mxc:\\/\\/" thumbnail_file: description: |- - Information on the encrypted thumbnail file, as specified in - [End-to-end encryption](/client-server-api/#sending-encrypted-attachments). + An [EncryptedFile](/client-server-api/#definition-encryptedfile) structure. Only present if the thumbnail is encrypted. title: EncryptedFile type: object @@ -82,9 +81,7 @@ properties: pattern: "^mxc:\\/\\/" file: description: |- - Required if the file is encrypted. Information on the encrypted - file, as specified in - [End-to-end encryption](/client-server-api/#sending-encrypted-attachments). + Required if the file is encrypted. An [EncryptedFile](/client-server-api/#definition-encryptedfile) structure. title: EncryptedFile type: object required: From 7fff7a78fd862b57c5d71aa57961d8db2556429c Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Fri, 12 Jun 2026 15:43:53 +0100 Subject: [PATCH 3/3] Add changelogs --- changelogs/appendices/newsfragments/2398.clarification | 1 + changelogs/client_server/newsfragments/2398.clarification | 1 + 2 files changed, 2 insertions(+) create mode 100644 changelogs/appendices/newsfragments/2398.clarification create mode 100644 changelogs/client_server/newsfragments/2398.clarification diff --git a/changelogs/appendices/newsfragments/2398.clarification b/changelogs/appendices/newsfragments/2398.clarification new file mode 100644 index 00000000..93fee967 --- /dev/null +++ b/changelogs/appendices/newsfragments/2398.clarification @@ -0,0 +1 @@ +Add specification of URL-safe unpadded Base64. diff --git a/changelogs/client_server/newsfragments/2398.clarification b/changelogs/client_server/newsfragments/2398.clarification new file mode 100644 index 00000000..17e14845 --- /dev/null +++ b/changelogs/client_server/newsfragments/2398.clarification @@ -0,0 +1 @@ +Clarify definitions of `EncryptedFile` structure.