mirror of
https://github.com/matrix-org/matrix-spec
synced 2026-08-04 23:17:48 +02:00
Compare commits
12 commits
7e053aeedb
...
d1920f840c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d1920f840c | ||
|
|
02ce04f083 | ||
|
|
a692b7be83 | ||
|
|
4c2bb5aae1 | ||
|
|
f9dec5dc92 | ||
|
|
16b04f9d6c | ||
|
|
cece4c28ec | ||
|
|
3e6c1e35d9 | ||
|
|
409d052b79 | ||
|
|
22dfc249b6 | ||
|
|
c53c2d093a | ||
|
|
1b62e3d515 |
|
|
@ -0,0 +1 @@
|
||||||
|
Add further normative language in mutual rooms server behaviour.
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
Improve the format description of `m.room.encrypted` (Olm/Megolm) events.
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
Use MXC URI type for all user `avatar_url` fields. Contributed by @networkException.
|
||||||
1
changelogs/olm_megolm/newsfragments/2421.clarification
Normal file
1
changelogs/olm_megolm/newsfragments/2421.clarification
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
Fix typesetting of some symbols in the Olm/Megolm spec.
|
||||||
|
|
@ -1723,28 +1723,30 @@ Devices that support Olm must include "m.olm.v1.curve25519-aes-sha2" in
|
||||||
their list of supported messaging algorithms, must list a Curve25519
|
their list of supported messaging algorithms, must list a Curve25519
|
||||||
device key, and must publish Curve25519 one-time keys.
|
device key, and must publish Curve25519 one-time keys.
|
||||||
|
|
||||||
An event encrypted using Olm has the following format:
|
The content of an [`m.room.encrypted`](#mroomencrypted) event using Olm has the following format:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"type": "m.room.encrypted",
|
|
||||||
"content": {
|
"content": {
|
||||||
"algorithm": "m.olm.v1.curve25519-aes-sha2",
|
"algorithm": "m.olm.v1.curve25519-aes-sha2",
|
||||||
"sender_key": "<sender_curve25519_key>",
|
"sender_key": "<sender_curve25519_key>",
|
||||||
"ciphertext": {
|
"ciphertext": {
|
||||||
"<device_curve25519_key>": {
|
"<device_curve25519_key>": {
|
||||||
"type": 0,
|
"type": 0,
|
||||||
"body": "<encrypted_payload_base_64>"
|
"body": "<base64_encoded_olm_message>"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
Note that when the event is received from the server, it will have a `type`
|
||||||
`ciphertext` is a mapping from device Curve25519 key to an encrypted
|
(with a value of `m.room.encrypted`) and `sender` property alongside the
|
||||||
payload for that device. `body` is a Base64-encoded [Olm message body](/olm-megolm/olm/#the-olm-message-format).
|
`content` property. In `content`, `ciphertext` is a mapping from a device
|
||||||
`type` is an integer indicating the type of the message body: 0 for the
|
Curve25519 key to an object with a `type` and a `body`. Here, `body` is a
|
||||||
initial [pre-key message](/olm-megolm/olm/#pre-key-messages), 1 for [normal messages](/olm-megolm/olm/#normal-messages).
|
Base64-encoded [Olm message](/olm-megolm/olm/#the-olm-message-format), and
|
||||||
|
`type` is an integer indicating the type of the message:
|
||||||
|
0 for the initial [pre-key messages](/olm-megolm/olm/#pre-key-messages),
|
||||||
|
1 for [normal messages](/olm-megolm/olm/#normal-messages).
|
||||||
|
|
||||||
Olm sessions will generate messages with a type of 0 until they receive
|
Olm sessions will generate messages with a type of 0 until they receive
|
||||||
a message. Once a session has decrypted a message it will produce
|
a message. Once a session has decrypted a message it will produce
|
||||||
|
|
@ -1891,23 +1893,24 @@ This uses:
|
||||||
Devices that support Megolm must support Olm, and include
|
Devices that support Megolm must support Olm, and include
|
||||||
"m.megolm.v1.aes-sha2" in their list of supported messaging algorithms.
|
"m.megolm.v1.aes-sha2" in their list of supported messaging algorithms.
|
||||||
|
|
||||||
An event encrypted using Megolm has the following format:
|
The content of an [`m.room.encrypted`](#mroomencrypted) event using Megolm has the following format:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"type": "m.room.encrypted",
|
|
||||||
"content": {
|
"content": {
|
||||||
"algorithm": "m.megolm.v1.aes-sha2",
|
"algorithm": "m.megolm.v1.aes-sha2",
|
||||||
"sender_key": "<sender_curve25519_key>",
|
"sender_key": "<sender_curve25519_key>",
|
||||||
"device_id": "<sender_device_id>",
|
"device_id": "<sender_device_id>",
|
||||||
"session_id": "<outbound_group_session_id>",
|
"session_id": "<outbound_group_session_id>",
|
||||||
"ciphertext": "<encrypted_payload_base_64>"
|
"ciphertext": "<base64_encoded_megolm_message>"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
Note that when the event is received from the server, it will have additional
|
||||||
The encrypted payload can contain any message event. The plaintext is of
|
properties alongside the `content` property, including a `type` (with a value
|
||||||
the form:
|
of `m.room.encrypted`) and a `sender` property. In `content`, `ciphertext`
|
||||||
|
is a Base64-encoded [Megolm message](/olm-megolm/megolm/#message-format),
|
||||||
|
whose plaintext body is of the form:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
|
|
@ -1917,7 +1920,7 @@ the form:
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
We include the room ID in the payload, because otherwise the homeserver
|
We include the room ID in the encrypted message, because otherwise the homeserver
|
||||||
would be able to change the room a message was sent in.
|
would be able to change the room a message was sent in.
|
||||||
|
|
||||||
Clients must guard against replay attacks by keeping track of the
|
Clients must guard against replay attacks by keeping track of the
|
||||||
|
|
|
||||||
|
|
@ -91,13 +91,13 @@ For example, a replacement for an encrypted event might look like this:
|
||||||
"sender_key": "<sender_curve25519_key>",
|
"sender_key": "<sender_curve25519_key>",
|
||||||
"device_id": "<sender_device_id>",
|
"device_id": "<sender_device_id>",
|
||||||
"session_id": "<outbound_group_session_id>",
|
"session_id": "<outbound_group_session_id>",
|
||||||
"ciphertext": "<encrypted_payload_base_64>"
|
"ciphertext": "<base64_encoded_megolm_message>"
|
||||||
}
|
}
|
||||||
// irrelevant fields not shown
|
// irrelevant fields not shown
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
... and, once decrypted, the payload might look like this:
|
... and the plaintext body of the Megolm message might look like this:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,9 @@
|
||||||
|
|
||||||
#### Server behaviour
|
#### Server behaviour
|
||||||
|
|
||||||
The server may decide that the response to this endpoint is too large, and only return a
|
The server MAY decide that the response to this endpoint is too large, and only return a
|
||||||
subset of the results. In this case, the server should populate the optional field `next_batch`
|
subset of the results. In this case, the server populates the optional field `next_batch`
|
||||||
with an [opaque identifier](/appendices/#opaque-identifiers). The client may then supply
|
with an [opaque identifier](/appendices/#opaque-identifiers). The client can then supply
|
||||||
the identifier as the `from` query parameter in a subsequent request, along with the original
|
the identifier as the `from` query parameter in a subsequent request, along with the original
|
||||||
`user_id`, to fetch the next batch of responses. This will continue until the server no longer
|
`user_id`, to fetch the next batch of responses. This will continue until the server no longer
|
||||||
inserts `next_batch`, meaning there are no further results.
|
inserts `next_batch`, meaning there are no further results.
|
||||||
|
|
|
||||||
|
|
@ -257,8 +257,8 @@ consists of the following key-value pairs:
|
||||||
|
|
||||||
**Name**|**Tag**|**Type**|**Meaning**
|
**Name**|**Tag**|**Type**|**Meaning**
|
||||||
:-----:|:-----:|:-----:|:-----:
|
:-----:|:-----:|:-----:|:-----:
|
||||||
Message-Index|0x08|Integer|The index of the ratchet, i
|
Message-Index|0x08|Integer|The index of the ratchet, \(i\).
|
||||||
Cipher-Text|0x12|String|The cipher-text, Xi, of the message
|
Cipher-Text|0x12|String|The cipher-text of the message, \(X_i\).
|
||||||
|
|
||||||
Within the payload, integers are encoded using a variable length encoding. Each
|
Within the payload, integers are encoded using a variable length encoding. Each
|
||||||
integer is encoded as a sequence of bytes with the high bit set followed by a
|
integer is encoded as a sequence of bytes with the high bit set followed by a
|
||||||
|
|
|
||||||
|
|
@ -17,12 +17,12 @@ side of an \(=\) it means that the output is split.
|
||||||
When this document uses \(\operatorname{ECDH}\left(K_A,K_B\right)\) it means
|
When this document uses \(\operatorname{ECDH}\left(K_A,K_B\right)\) it means
|
||||||
that each party computes a Diffie-Hellman agreement using their private key
|
that each party computes a Diffie-Hellman agreement using their private key
|
||||||
and the remote party's public key.
|
and the remote party's public key.
|
||||||
So party \(A\) computes \(\operatorname{ECDH}\left(K_B^{public},K_A^{private}\right)\)
|
So party \(A\) computes \(\operatorname{ECDH}\left(K_B^{\mathit{public}},K_A^{\mathit{private}}\right)\)
|
||||||
and party \(B\) computes \(\operatorname{ECDH}\left(K_A^{public},K_B^{private}\right)\).
|
and party \(B\) computes \(\operatorname{ECDH}\left(K_A^{\mathit{public}},K_B^{\mathit{private}}\right)\).
|
||||||
|
|
||||||
Where this document uses \(\operatorname{HKDF}\left(salt,IKM,info,L\right)\) it
|
Where this document uses \(\operatorname{HKDF}\left(\mathit{salt},\mathit{IKM},\mathit{info},L\right)\) it
|
||||||
refers to the [HMAC-based key derivation function][] with a salt value of
|
refers to the [HMAC-based key derivation function][] with a salt value of
|
||||||
\(salt\), input key material of \(IKM\), context string \(info\),
|
\(\mathit{salt}\), input key material of \(\mathit{IKM}\), context string \(\mathit{info}\),
|
||||||
and output keying material length of \(L\) bytes.
|
and output keying material length of \(L\) bytes.
|
||||||
|
|
||||||
## The Olm Algorithm
|
## The Olm Algorithm
|
||||||
|
|
@ -226,9 +226,9 @@ significant bits are stored in the first byte.
|
||||||
|
|
||||||
**Name**|**Tag**|**Type**|**Meaning**
|
**Name**|**Tag**|**Type**|**Meaning**
|
||||||
:-----:|:-----:|:-----:|:-----:
|
:-----:|:-----:|:-----:|:-----:
|
||||||
Ratchet-Key|0x0A|String|The public part of the ratchet key, Ti, of the message
|
Ratchet-Key|0x0A|String|The public part of the ratchet key of the message, \(T_i\).
|
||||||
Chain-Index|0x10|Integer|The chain index, j, of the message
|
Chain-Index|0x10|Integer|The chain index of the message, \(j\).
|
||||||
Cipher-Text|0x22|String|The cipher-text, Xi, j, of the message
|
Cipher-Text|0x22|String|The cipher-text of the message, \(X_{i,j}\).
|
||||||
|
|
||||||
The length of the MAC is determined by the authenticated encryption algorithm
|
The length of the MAC is determined by the authenticated encryption algorithm
|
||||||
being used. (Olm version 1 uses [HMAC-SHA-256][], truncated to 8 bytes). The
|
being used. (Olm version 1 uses [HMAC-SHA-256][], truncated to 8 bytes). The
|
||||||
|
|
@ -251,9 +251,9 @@ The payload uses the same key-value format as for normal messages.
|
||||||
|
|
||||||
**Name**|**Tag**|**Type**|**Meaning**
|
**Name**|**Tag**|**Type**|**Meaning**
|
||||||
:-----:|:-----:|:-----:|:-----:
|
:-----:|:-----:|:-----:|:-----:
|
||||||
One-Time-Key|0x0A|String|The public part of Bob's single-use key, Eb.
|
One-Time-Key|0x0A|String|The public part of Bob's single-use key, \(E_B\).
|
||||||
Base-Key|0x12|String|The public part of Alice's single-use key, Ea.
|
Base-Key|0x12|String|The public part of Alice's single-use key, \(E_A\).
|
||||||
Identity-Key|0x1A|String|The public part of Alice's identity key, Ia.
|
Identity-Key|0x1A|String|The public part of Alice's identity key, \(I_A\).
|
||||||
Message|0x22|String|An embedded Olm message with its own version and MAC.
|
Message|0x22|String|An embedded Olm message with its own version and MAC.
|
||||||
|
|
||||||
## Olm Authenticated Encryption
|
## Olm Authenticated Encryption
|
||||||
|
|
@ -268,13 +268,13 @@ message key using [HKDF-SHA-256][] using the default salt and an info of
|
||||||
|
|
||||||
\[
|
\[
|
||||||
\begin{aligned}
|
\begin{aligned}
|
||||||
AES\_KEY_{i,j}\;\parallel\;HMAC\_KEY_{i,j}\;\parallel\;AES\_IV_{i,j}
|
\mathit{AES\_KEY}_{i,j}\;\parallel\;\mathit{HMAC\_KEY}_{i,j}\;\parallel\;\mathit{AES\_IV}_{i,j}
|
||||||
&= \operatorname{HKDF}\left(0,M_{i,j},\text{``OLM\_KEYS"},80\right)
|
&= \operatorname{HKDF}\left(0,M_{i,j},\text{``OLM\_KEYS"},80\right)
|
||||||
\end{aligned}
|
\end{aligned}
|
||||||
\]
|
\]
|
||||||
|
|
||||||
The plain-text is encrypted with AES-256, using the key \(AES\_KEY_{i,j}\)
|
The plain-text is encrypted with AES-256, using the key \(\mathit{AES\_KEY}_{i,j}\)
|
||||||
and the IV \(AES\_IV_{i,j}\) to give the cipher-text, \(X_{i,j}\).
|
and the IV \(\mathit{AES\_IV}_{i,j}\) to give the cipher-text, \(X_{i,j}\).
|
||||||
|
|
||||||
Then the entire message (including the Version Byte and all Payload Bytes) are
|
Then the entire message (including the Version Byte and all Payload Bytes) are
|
||||||
passed through [HMAC-SHA-256][]. The first 8 bytes of the MAC are appended to the message.
|
passed through [HMAC-SHA-256][]. The first 8 bytes of the MAC are appended to the message.
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,8 @@ properties:
|
||||||
example: true
|
example: true
|
||||||
avatar_url:
|
avatar_url:
|
||||||
type: string
|
type: string
|
||||||
format: uri
|
format: mx-mxc-uri
|
||||||
|
pattern: "^mxc:\\/\\/"
|
||||||
description: The URL for the room's avatar, if one is set.
|
description: The URL for the room's avatar, if one is set.
|
||||||
example: "mxc://example.org/abcdef"
|
example: "mxc://example.org/abcdef"
|
||||||
join_rule:
|
join_rule:
|
||||||
|
|
|
||||||
|
|
@ -340,7 +340,8 @@ paths:
|
||||||
description: The display name of the user this object is representing.
|
description: The display name of the user this object is representing.
|
||||||
avatar_url:
|
avatar_url:
|
||||||
type: string
|
type: string
|
||||||
format: uri
|
format: mx-mxc-uri
|
||||||
|
pattern: "^mxc:\\/\\/"
|
||||||
description: The avatar of the user this object is representing, as an [`mxc://`
|
description: The avatar of the user this object is representing, as an [`mxc://`
|
||||||
URI](/client-server-api/#matrix-content-mxc-uris).
|
URI](/client-server-api/#matrix-content-mxc-uris).
|
||||||
description: A map from user ID to a RoomMember object.
|
description: A map from user ID to a RoomMember object.
|
||||||
|
|
|
||||||
|
|
@ -238,7 +238,8 @@ paths:
|
||||||
title: Display name
|
title: Display name
|
||||||
avatar_url:
|
avatar_url:
|
||||||
type: string
|
type: string
|
||||||
format: uri
|
format: mx-mxc-uri
|
||||||
|
pattern: "^mxc:\\/\\/"
|
||||||
title: Avatar Url
|
title: Avatar Url
|
||||||
events_before:
|
events_before:
|
||||||
type: array
|
type: array
|
||||||
|
|
|
||||||
|
|
@ -90,7 +90,8 @@ paths:
|
||||||
description: The display name of the user, if one exists.
|
description: The display name of the user, if one exists.
|
||||||
avatar_url:
|
avatar_url:
|
||||||
type: string
|
type: string
|
||||||
format: uri
|
format: mx-mxc-uri
|
||||||
|
pattern: "^mxc:\\/\\/"
|
||||||
example: mxc://bar.com/foo
|
example: mxc://bar.com/foo
|
||||||
description: The avatar url, as an [`mxc://`
|
description: The avatar url, as an [`mxc://`
|
||||||
URI](/client-server-api/#matrix-content-mxc-uris),
|
URI](/client-server-api/#matrix-content-mxc-uris),
|
||||||
|
|
|
||||||
|
|
@ -172,6 +172,8 @@ paths:
|
||||||
example: John Doe
|
example: John Doe
|
||||||
avatar_url:
|
avatar_url:
|
||||||
type: string
|
type: string
|
||||||
|
format: mx-mxc-uri
|
||||||
|
pattern: "^mxc:\\/\\/"
|
||||||
description: |-
|
description: |-
|
||||||
The avatar URL for the user's avatar. MUST either be omitted or set to
|
The avatar URL for the user's avatar. MUST either be omitted or set to
|
||||||
`null` if the user does not have an avatar set.
|
`null` if the user does not have an avatar set.
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,8 @@
|
||||||
"properties": {
|
"properties": {
|
||||||
"avatar_url": {
|
"avatar_url": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
|
"format": "mx-mxc-uri",
|
||||||
|
"pattern": "^mxc:\\/\\/",
|
||||||
"description": "The current avatar URL for this user, if any."
|
"description": "The current avatar URL for this user, if any."
|
||||||
},
|
},
|
||||||
"displayname": {
|
"displayname": {
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,8 @@ properties:
|
||||||
avatar_url:
|
avatar_url:
|
||||||
description: 'The avatar URL for this user, if any.'
|
description: 'The avatar URL for this user, if any.'
|
||||||
type: string
|
type: string
|
||||||
format: uri
|
format: mx-mxc-uri
|
||||||
|
pattern: "^mxc:\\/\\/"
|
||||||
displayname:
|
displayname:
|
||||||
description: 'The display name for this user, if any.'
|
description: 'The display name for this user, if any.'
|
||||||
type:
|
type:
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue