Compare commits

...

4 commits

Author SHA1 Message Date
codedust f5c708fcdb
Merge 48bbc53045 into cbff6790c3 2026-02-04 18:46:01 +02:00
Kévin Commaille cbff6790c3
Spec for MSC4380: Invite blocking (#2305)
Signed-off-by: Kévin Commaille <zecakeh@tedomum.fr>
2026-02-04 16:24:37 +00:00
Kim Brose 8b7187927d
Add identifier pronunciation (#2307)
* Add identifier pronunciation

Signed-off-by: HarHarLinks <2803622+HarHarLinks@users.noreply.github.com>

* Add changelog entry

Signed-off-by: HarHarLinks <2803622+HarHarLinks@users.noreply.github.com>

---------

Signed-off-by: HarHarLinks <2803622+HarHarLinks@users.noreply.github.com>
2026-02-04 13:45:13 +00:00
codedust 48bbc53045 Clarify terminology for keys in cross-signing module
- the naming of the master signing key has been harmonised (no more 'master
  cross-signing key' or 'master key').
- in the QR code example, the term 'cross-signing key' has been replaced
  by 'master signing key' since in mode 0x00, the current user's own master
  signing key and what the device thinks the other user's master signng key
  is used.
- it has been made more explicit that cross-signing private keys stored on the
  server are stored as described in the secrets module (as opposed to store
  them in unencrypted form)

Signed-off-by: codedust <codedust@so.urceco.de>
Co-authored-by: Richard van der Hoff <1389908+richvdh@users.noreply.github.com>
2026-01-30 15:11:05 +01:00
20 changed files with 203 additions and 72 deletions

View file

@ -0,0 +1 @@
Add identifier pronunciation guidelines. Contributed by @HarHarLinks.

View file

@ -0,0 +1 @@
Add invite blocking, as per [MSC4380](https://github.com/matrix-org/matrix-spec-proposals/pull/4380).

View file

@ -0,0 +1 @@
Clarify terminology for keys in cross-signing module.

View file

@ -533,6 +533,11 @@ where `domain` is the [server name](#server-name) of the homeserver
which allocated the identifier, and `localpart` is an identifier
allocated by that homeserver.
Because the domain part identifies the server on which the ID resolves,
the canonical pronunciation of the separating `:` is "on".
For example, `@user:matrix.org` would be pronounced as "at user on matrix dot
org".
The precise grammar defining the allowable format of an identifier
depends on the type of identifier. For example, event IDs can sometimes
be represented with a `domain` component under some conditions - see the

View file

@ -4071,6 +4071,7 @@ that profile.
| [Sticker Messages](#sticker-messages) | Optional | Optional | Optional | Optional | Optional |
| [Third-party Networks](#third-party-networks) | Optional | Optional | Optional | Optional | Optional |
| [Threading](#threading) | Optional | Optional | Optional | Optional | Optional |
| [Invite permission](#invite-permission) | Optional | Optional | Optional | Optional | Optional |
*Please see each module for more details on what clients need to
implement.*
@ -4144,6 +4145,7 @@ systems.
{{% cs-module name="SSO client login/authentication" filename="sso_login" %}}
{{% cs-module name="Direct Messaging" filename="dm" %}}
{{% cs-module name="Ignoring Users" filename="ignore_users" %}}
{{% cs-module name="Invite permission" filename="invite_permission" %}}
{{% cs-module name="Sticker Messages" filename="stickers" %}}
{{% cs-module name="Reporting Content" filename="report_content" %}}
{{% cs-module name="Third-party Networks" filename="third_party_networks" %}}

View file

@ -93,7 +93,7 @@ Example:
```
`ed25519` and `curve25519` keys are used for [device keys](#device-keys).
Additionally, `ed25519` keys are used for [cross-signing keys](#cross-signing).
Additionally, `ed25519` keys are used for [cross-signing key](#cross-signing).
`signed_curve25519` keys are used for [one-time and fallback keys](#one-time-and-fallback-keys).
@ -675,7 +675,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:
* Each of the keys that they wish the other user to verify (usually their
device ed25519 key and their master cross-signing key).
device ed25519 key and their master signing key, see below).
* The complete list of key IDs that they wish the other user to verify.
The MAC calculation is defined [below](#mac-calculation).
@ -931,40 +931,42 @@ and can be translated online:
Rather than requiring Alice to verify each of Bob's devices with each of
her own devices and vice versa, the cross-signing feature allows users
to sign their device keys such that Alice and Bob only need to verify
once. With cross-signing, each user has a set of cross-signing keys that
once. With cross-signing, each user has a set of cross-signing key pairs that
are used to sign their own device keys and other users' keys, and can be
used to trust device keys that were not verified directly.
Each user has three ed25519 key pairs for cross-signing:
Each user has three ed25519 key pairs used for cross-signing (cross-signing keys):
- a master key (MSK) that serves as the user's identity in
cross-signing and signs their other cross-signing keys;
- a master signing key (MSK, for historical reasons sometimes known as
`master_key`) that serves as the user's identity in cross-signing and signs
their user-signing and self-signing keys;
- a user-signing key (USK) -- only visible to the user that it belongs
to --that signs other users' master keys; and
to -- that signs other users' master signing keys; and
- a self-signing key (SSK) that signs the user's own device keys.
The master key may also be used to sign other items such as the backup
key. The master key may also be signed by the user's own device keys to
The master signing key may also be used to sign other items such as the backup
key. The master signing key may also be signed by the user's own device keys to
aid in migrating from device verifications: if Alice's device had
previously verified Bob's device and Bob's device has signed his master
key, then Alice's device can trust Bob's master key, and she can sign it
key, then Alice's device can trust Bob's master signing key, and she can sign it
with her user-signing key.
Users upload their cross-signing keys to the server using [POST
Users upload the public part of their master signing, user-signing and
self-signing key to the server using [POST
/\_matrix/client/v3/keys/device\_signing/upload](/client-server-api/#post_matrixclientv3keysdevice_signingupload). When Alice uploads
new cross-signing keys, her user ID will appear in the `changed`
new keys, her user ID will appear in the `changed`
property of the `device_lists` field of the `/sync` of response of all
users who share an encrypted room with her. When Bob sees Alice's user
ID in his `/sync`, he will call [POST /\_matrix/client/v3/keys/query](/client-server-api/#post_matrixclientv3keysquery)
to retrieve Alice's device and cross-signing keys.
to retrieve Alice's device keys, as well as their cross-signing keys.
If Alice has a device and wishes to send an encrypted message to Bob,
she can trust Bob's device if:
- Alice's device is using a master key that has signed her
- Alice's device is using a master signing key that has signed her
user-signing key,
- Alice's user-signing key has signed Bob's master key,
- Bob's master key has signed Bob's self-signing key, and
- Alice's user-signing key has signed Bob's master signing key,
- Bob's master signing key has signed Bob's self-signing key, and
- Bob's self-signing key has signed Bob's device key.
The following diagram illustrates how keys are signed:
@ -1024,27 +1026,28 @@ signatures that she cannot see:
```
[Verification methods](#device-verification) can be used to verify a
user's master key by using the master public key, encoded using unpadded
base64, as the device ID, and treating it as a normal device. For
example, if Alice and Bob verify each other using SAS, Alice's
user's master signing key by treating its public key (master signing public
key), encoded using unpadded base64, as the device ID, and treating it as a
normal device. For example, if Alice and Bob verify each other using SAS,
Alice's
`m.key.verification.mac` message to Bob may include
`"ed25519:alices+master+public+key": "alices+master+public+key"` in the
`mac` property. Servers therefore must ensure that device IDs will not
collide with cross-signing public keys.
The cross-signing private keys can be stored on the server or shared with other
devices using the [Secrets](#secrets) module. When doing so, the master,
user-signing, and self-signing keys are identified using the names
`m.cross_signing.master`, `m.cross_signing.user_signing`, and
Using the [Secrets](#secrets) module the cross-signing private keys can
be stored on the server or shared with other devices. When doing so, the
master signing, user-signing, and self-signing keys are identified using the
names `m.cross_signing.master`, `m.cross_signing.user_signing`, and
`m.cross_signing.self_signing`, respectively, and the keys are base64-encoded
before being encrypted.
###### Key and signature security
A user's master key could allow an attacker to impersonate that user to
A user's master signing key could allow an attacker to impersonate that user to
other users, or other users to that user. Thus clients must ensure that
the private part of the master key is treated securely. If clients do
not have a secure means of storing the master key (such as a secret
the private part of the master signing key is treated securely. If clients do
not have a secure means of storing the master signing key (such as a secret
storage system provided by the operating system), then clients must not
store the private part.
@ -1052,14 +1055,14 @@ If a user's client sees that any other user has changed their master
key, that client must notify the user about the change before allowing
communication between the users to continue.
Since device key IDs (`ed25519:DEVICE_ID`) and cross-signing key IDs
Since device key IDs (`ed25519:DEVICE_ID`) as well as cross-signing key IDs
(`ed25519:PUBLIC_KEY`) occupy the same namespace, clients must ensure that they
use the correct keys when verifying.
While servers MUST not allow devices to have the same IDs as cross-signing
keys, a malicious server could construct such a situation, so clients must not
rely on the server being well-behaved and should take the following precautions
against this.
keys, a malicious server could construct such a situation, so clients
must not rely on the server being well-behaved and should take the following
precautions against this:
1. Clients MUST refer to keys by their public keys during the verification
process, rather than only by the key ID.
@ -1067,31 +1070,32 @@ against this.
verification process, and ensure that they do not change in the course of
verification.
3. Clients SHOULD also display a warning and MUST refuse to verify a user when
they detect that the user has a device with the same ID as a cross-signing key.
they detect that the user has a device with the same ID as a cross-signing
key.
A user's user-signing and self-signing keys are intended to be easily
replaceable if they are compromised by re-issuing a new key signed by
the user's master key and possibly by re-verifying devices or users.
the user's master signing key and possibly by re-verifying devices or users.
However, doing so relies on the user being able to notice when their
keys have been compromised, and it involves extra work for the user, and
so although clients do not have to treat the private parts as
sensitively as the master key, clients should still make efforts to
sensitively as the master signing key, clients should still make efforts to
store the private part securely, or not store it at all. Clients will
need to balance the security of the keys with the usability of signing
users and devices when performing key verification.
To avoid leaking of social graphs, servers will only allow users to see:
- signatures made by the user's own master, self-signing or
- signatures made by the user's own master signing, self-signing or
user-signing keys,
- signatures made by the user's own devices about their own master
key,
- signatures made by other users' self-signing keys about their
respective devices,
- signatures made by other users' master keys about their respective
- signatures made by other users' master signing keys about their respective
self-signing key, or
- signatures made by other users' devices about their respective
master keys.
master signing keys.
Users will not be able to see signatures made by other users'
user-signing keys.
@ -1193,24 +1197,24 @@ The binary segment MUST be of the following form:
- one byte indicating the QR code verification mode. Should be one of the
following values:
- `0x00` verifying another user with cross-signing
- `0x01` self-verifying in which the current device does trust the master key
- `0x01` self-verifying in which the current device does trust the master signing key
- `0x02` self-verifying in which the current device does not yet trust the
master key
master signing key
- the event ID or `transaction_id` of the associated verification
request event, encoded as:
- two bytes in network byte order (big-endian) indicating the length in
bytes of the ID as a UTF-8 string
- the ID encoded as a UTF-8 string
- the first key, as 32 bytes. The key to use depends on the mode field:
- if `0x00` or `0x01`, then the current user's own master cross-signing public key
- if `0x00` or `0x01`, then the current user's own master signing public key
- if `0x02`, then the current device's Ed25519 signing key
- the second key, as 32 bytes. The key to use depends on the mode field:
- if `0x00`, then what the device thinks the other user's master
cross-signing public key is
public key is
- if `0x01`, then what the device thinks the other device's Ed25519 signing
public key is
- if `0x02`, then what the device thinks the user's master cross-signing public
key is
- if `0x02`, then what the device thinks the user's master signing public key
is
- a random shared secret, as a sequence of bytes. It is suggested to use a secret
that is about 8 bytes long. Note: as we do not share the length of the
secret, and it is not a fixed size, clients will just use the remainder of
@ -1221,14 +1225,14 @@ For example, if Alice displays a QR code encoding the following binary data:
```nohighlight
"MATRIX" |ver|mode| len | event ID
4D 41 54 52 49 58 02 00 00 2D 21 41 42 43 44 ...
| user's cross-signing key | other user's cross-signing key | shared secret
00 01 02 03 04 05 06 07 ... 10 11 12 13 14 15 16 17 ... 20 21 22 23 24 25 26 27
| the first key | the second key | shared secret
00 01 02 03 04 05 06 07 ... 10 11 12 13 14 15 16 17 ... 20 21 22 23 24 25 26 27
```
this indicates that Alice is verifying another user (say Bob), in response to
the request from event "$ABCD...", her cross-signing key is
Mode `0x00` indicates that Alice is verifying another user (say Bob), in
response to the request from event "$ABCD...", her master signing key is
`0001020304050607...` (which is "AAECAwQFBg..." in base64), she thinks that
Bob's cross-signing key is `1011121314151617...` (which is "EBESExQVFh..." in
Bob's master signing key is `1011121314151617...` (which is "EBESExQVFh..." in
base64), and the shared secret is `2021222324252627` (which is "ICEiIyQlJic" in
base64).
@ -1300,8 +1304,8 @@ one of its variants.
Clients must only store keys in backups after they have ensured that the
`auth_data` is trusted. This can be done either by:
- checking that it is signed by the user's [master cross-signing
key](#cross-signing) or by a verified device belonging to the same user, or
- checking that it is signed by the user's [master signing key](#cross-signing)
or by a verified device belonging to the same user, or
- deriving the public key from a private key that it obtained from a trusted
source. Trusted sources for the private key include the user entering the
key, retrieving the key stored in [secret storage](#secret-storage), or

View file

@ -0,0 +1,51 @@
### Invite permission
{{% added-in v="1.18" %}}
Users may want to control who is allowed to invite them to new rooms. This module defines how
clients and servers can implement invite permission.
#### Account data
{{% event event="m.invite_permission_config" %}}
#### Client behaviour
To reject invites from all users automatically, clients MAY add an [`m.invite_permission_config`](#minvite_permission_config)
event in the user's [account data](#client-config) with the `default_action` property set to
`block`. To stop rejecting all invites, the same event without the `default_action` property MUST be
added to the account data.
When the `default_action` field is unset, other parts of the specification might still have effects
on invites seen by clients, like [ignoring users](#ignoring-users).
Attempting to send an invite to a user that blocks invites will result in an error response with the
`M_INVITE_BLOCKED` error code.
#### Server behaviour
When invites to a given user are blocked, the user's homeserver MUST respond to the following
endpoints with an HTTP 403 status code, with the Matrix error code `M_INVITE_BLOCKED`, if the user
is invited:
* [`PUT /_matrix/federation/v1/invite/{roomId}/{eventId}`](/server-server-api/#put_matrixfederationv1inviteroomideventid)
* [`PUT /_matrix/federation/v2/invite/{roomId}/{eventId}`](/server-server-api/#put_matrixfederationv2inviteroomideventid)
* [`POST /_matrix/client/v3/rooms/{roomId}/invite`](#post_matrixclientv3roomsroomidinvite)
* [`POST /_matrix/client/v3/createRoom`](#post_matrixclientv3createroom), due to a user in the
`invite` list. It is possible for one of the invited users to be rejected whilst the room creation
as a whole succeeds.
* [`PUT /_matrix/client/v3/rooms/{roomId}/state/m.room.member/{stateKey}`](#put_matrixclientv3roomsroomidstateeventtypestatekey),
when the `membership` is set to `invite`.
In addition, invite events for this user already in the database, or received over federation, MUST
NOT be served over client synchronisation endpoints such as [`GET /sync`](#get_matrixclientv3sync).
Servers MAY return any suppressed invite events over `GET /sync` if invite blocking is later
disabled.
Other endpoints, such as [`GET /rooms/{roomId}/state`](#get_matrixclientv3roomsroomidstate), are not
affected by invite blocking: invite events are returned as normal.
The Application Services API is also unaffected by invite blocking: invite events are sent over
[`PUT /_matrix/app/v1/transactions/{txnId}`](/application-service-api/#put_matrixappv1transactionstxnid).

View file

@ -250,7 +250,6 @@ paths:
}
"400":
description: |-
The request is invalid. A meaningful `errcode` and description
error text will be returned. Example reasons for rejection include:
@ -274,6 +273,17 @@ paths:
application/json:
schema:
$ref: definitions/errors/error.yaml
"403":
description: |-
Creating the room is not allowed.
{{% added-in v="1.18"%}} The `M_INVITE_BLOCKED` error code is used to
indicate that one of the homeservers of the invited users rejected
the invite due to [invite blocking](/client-server-api/#invite-permission).
content:
application/json:
schema:
$ref: definitions/errors/error.yaml
tags:
- Room creation
servers:

View file

@ -32,9 +32,9 @@ paths:
except when used by an application service.
User-Interactive Authentication MUST be performed for regular clients, except in these cases:
- there is no existing cross-signing master key uploaded to the homeserver, OR
- there is an existing cross-signing master key and it exactly matches the
cross-signing master key provided in the request body. If there are any additional
- there is no existing master signing key uploaded to the homeserver, OR
- there is an existing master signing key and it exactly matches the
master signing key provided in the request body. If there are any additional
keys provided in the request (self-signing key, user-signing key) they MUST also
match the existing keys stored on the server. In other words, the request contains
no new keys.
@ -61,22 +61,22 @@ paths:
type: object
properties:
master_key:
description: Optional. The user\'s master key.
description: Optional. The user\'s master signing key.
allOf:
- $ref: definitions/cross_signing_key.yaml
self_signing_key:
description: |-
Optional. The user\'s self-signing key. Must be signed by
the accompanying master key, or by the user\'s most recently
uploaded master key if no master key is included in the
the accompanying master signing key, or by the user\'s most recently
uploaded master signing key if no master signing key is included in the
request.
allOf:
- $ref: definitions/cross_signing_key.yaml
user_signing_key:
description: |-
Optional. The user\'s user-signing key. Must be signed by
the accompanying master key, or by the user\'s most recently
uploaded master key if no master key is included in the
the accompanying master signing key, or by the user\'s most recently
uploaded master signing key if no master signing key is included in the
request.
allOf:
- $ref: definitions/cross_signing_key.yaml
@ -147,7 +147,7 @@ paths:
* `M_INVALID_SIGNATURE`: For example, the self-signing or
user-signing key had an incorrect signature.
* `M_MISSING_PARAM`: No master key is available.
* `M_MISSING_PARAM`: No master signing key is available.
content:
application/json:
schema:

View file

@ -13,7 +13,7 @@
# limitations under the License.
type: object
title: CrossSigningKey
description: Cross signing key
description: Key used for cross signing
properties:
user_id:
type: string
@ -44,8 +44,8 @@ properties:
title: Signatures
description: |-
Signatures of the key, calculated using the process described at [Signing JSON](/appendices/#signing-json).
Optional for the master key. Other keys must be signed by the
user\'s master key.
Optional for the master signing key. Other keys must be signed by the
user\'s master signing key.
example: {
"@alice:example.com": {
"ed25519:alice+base64+master+key": "signature+of+key"

View file

@ -83,7 +83,7 @@ paths:
value: {}
"400":
description: |-
The request is invalid. A meaningful `errcode` and description
error text will be returned. Example reasons for rejection include:
@ -99,12 +99,18 @@ paths:
$ref: definitions/errors/error.yaml
"403":
description: |-
You do not have permission to invite the user to the room. A meaningful `errcode` and description error text will be returned. Example reasons for rejections are:
You do not have permission to invite the user to the room. A
meaningful `errcode` and description error text will be returned.
Example reasons for rejections are:
- The invitee has been banned from the room.
- The invitee is already a member of the room.
- The inviter is not currently in the room.
- The inviter's power level is insufficient to invite users to the room.
{{% added-in v="1.18"%}} The `M_INVITE_BLOCKED` error code is used to
indicate that the homeserver rejected the invite due to
[invite blocking](/client-server-api/#invite-permission).
content:
application/json:
schema:

View file

@ -219,8 +219,8 @@ paths:
x-addedInMatrixVersion: "1.1"
type: object
description: |-
Information on the master cross-signing keys of the queried users.
A map from user ID, to master key information. For each key, the
Information on the master signing keys of the queried users.
A map from user ID, to master signing key information. For each key, the
information returned will be the same as uploaded via
`/keys/device_signing/upload`, along with the signatures
uploaded via `/keys/signatures/upload` that the requesting user

View file

@ -116,7 +116,13 @@ paths:
"error": "The alias '#hello:example.org' does not point to this room."
}
"403":
description: The sender doesn't have permission to send the event into the room.
description: |-
The sender doesn't have permission to send the event into the room.
{{% added-in v="1.18"%}} If the `eventType` is `m.room.member` and
the `membership` is `invite`, the `M_INVITE_BLOCKED` error code is
used to indicate that the homeserver rejected the invite due to
[invite blocking](/client-server-api/#invite-permission).
content:
application/json:
schema:

View file

@ -97,6 +97,10 @@ paths:
- The invitee is already a member of the room.
- The inviter is not currently in the room.
- The inviter's power level is insufficient to invite users to the room.
{{% added-in v="1.18"%}} The `M_INVITE_BLOCKED` error code is used to
indicate that the homeserver rejected the invite due to
[invite blocking](/client-server-api/#invite-permission).
content:
application/json:
schema:

View file

@ -155,11 +155,17 @@ paths:
]
"403":
description: |-
The invite is not allowed. This could be for a number of reasons, including:
The invite is not allowed.
The `M_FORBIDDEN` error code is used to indicate one of the following:
* The sender is not allowed to send invites to the target user/homeserver.
* The homeserver does not permit anyone to invite its users.
* The homeserver refuses to participate in the room.
{{% added-in v="1.18"%}} The `M_INVITE_BLOCKED` error code is used to
indicate that the homeserver rejected the invite due to
[invite blocking](/client-server-api/#invite-permission).
content:
application/json:
schema:

View file

@ -192,11 +192,17 @@ paths:
}
"403":
description: |-
The invite is not allowed. This could be for a number of reasons, including:
The invite is not allowed.
The `M_FORBIDDEN` error code is used to indicate one of the following:
* The sender is not allowed to send invites to the target user/homeserver.
* The homeserver does not permit anyone to invite its users.
* The homeserver refuses to participate in the room.
{{% added-in v="1.18"%}} The `M_INVITE_BLOCKED` error code is used to
indicate that the homeserver rejected the invite due to
[invite blocking](/client-server-api/#invite-permission).
content:
application/json:
schema:

View file

@ -79,7 +79,7 @@ paths:
- keys
master_key:
type: object
description: The user\'s master cross-signing key.
description: The user\'s master signing key.
allOf:
- $ref: ../client-server/definitions/cross_signing_key.yaml
- example:

View file

@ -194,8 +194,8 @@ paths:
x-addedInMatrixVersion: "1.1"
type: object
description: |-
Information on the master cross-signing keys of the queried users.
A map from user ID, to master key information. For each key, the
Information on the master signing keys of the queried users.
A map from user ID, to master signing key information. For each key, the
information returned will be the same as uploaded via
`/keys/device_signing/upload`, along with the signatures
uploaded via `/keys/signatures/upload` that the user is

View file

@ -0,0 +1,7 @@
{
"$ref": "core/event.json",
"type": "m.invite_permission_config",
"content": {
"default_action": "block"
}
}

View file

@ -0,0 +1,21 @@
---
$schema: https://json-schema.org/draft/2020-12/schema
allOf:
- $ref: core-event-schema/event.yaml
- title: Invite Permission
type: object
description: |-
The permission configuration for receiving invites for the current account.
properties:
content:
type: object
properties:
default_action:
type: string
description: |-
When set to `block`, the user does not wish to receive *any* room invites, and they
should be rejected automatically by the homeserver.
A missing, invalid or unsupported value means that the user wants to receive invites
as normal. Other parts of the specification might still have effects on invites, like
[ignoring users](/client-server-api/#ignoring-users).