parent
97a7717d38
commit
da6938b818
8 changed files with 715 additions and 11 deletions
68
api/client-server/definitions/device_keys.yaml
Normal file
68
api/client-server/definitions/device_keys.yaml
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
# Copyright 2016 OpenMarket Ltd
|
||||||
|
#
|
||||||
|
# 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: DeviceKeys
|
||||||
|
description: Device identity keys
|
||||||
|
properties:
|
||||||
|
user_id:
|
||||||
|
type: string
|
||||||
|
description: |-
|
||||||
|
The ID of the user the device belongs to. Must match the user ID used
|
||||||
|
when logging in.
|
||||||
|
example: "@alice:example.com"
|
||||||
|
device_id:
|
||||||
|
type: string
|
||||||
|
description: |-
|
||||||
|
The ID of the device these keys belong to. Must match the device ID used
|
||||||
|
when logging in.
|
||||||
|
example: "JLAFKJWSCS"
|
||||||
|
algorithms:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
description: |-
|
||||||
|
The encryption algorithms supported by this device.
|
||||||
|
example: ["m.olm.curve25519-aes-sha256", "m.megolm.v1.aes-sha"]
|
||||||
|
keys:
|
||||||
|
type: object
|
||||||
|
description: |-
|
||||||
|
Public identity keys. The names of the properties should be in the
|
||||||
|
format ``<algorithm>:<device_id>``. The keys themselves should be
|
||||||
|
encoded as specified by the key algorithm.
|
||||||
|
additionalProperties:
|
||||||
|
type: string
|
||||||
|
example:
|
||||||
|
"curve25519:JLAFKJWSCS": "3C5BFWi2Y8MaVvjM8M22DBmh24PmgR0nPvJOIArzgyI"
|
||||||
|
"ed25519:JLAFKJWSCS": "lEuiRJBit0IG6nUf5pUzWTUEsRVVe/HJkoKuEww9ULI"
|
||||||
|
signatures:
|
||||||
|
type: object
|
||||||
|
description: |-
|
||||||
|
Signatures for the device key object. A map from user ID, to a map from
|
||||||
|
``<algorithm>:<device_id>`` to the signature.
|
||||||
|
|
||||||
|
The signature is calculated using the process described at `Signing
|
||||||
|
JSON`_.
|
||||||
|
additionalProperties:
|
||||||
|
type: object
|
||||||
|
additionalProperties:
|
||||||
|
type: string
|
||||||
|
example:
|
||||||
|
"@alice:example.com":
|
||||||
|
"ed25519:JLAFKJWSCS": "dSO80A01XiigH3uBiDVx/EjzaoycHcjq9lfQX0uWsqxl2giMIiSPR8a4d291W1ihKJL/a+myXS367WT6NAIcBA"
|
||||||
|
required:
|
||||||
|
- user_id
|
||||||
|
- device_id
|
||||||
|
- algorithms
|
||||||
|
- keys
|
||||||
|
- signatures
|
336
api/client-server/keys.yaml
Normal file
336
api/client-server/keys.yaml
Normal file
|
@ -0,0 +1,336 @@
|
||||||
|
# Copyright 2016 OpenMarket Ltd
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
swagger: '2.0'
|
||||||
|
info:
|
||||||
|
title: "Matrix Client-Server Client Config API"
|
||||||
|
version: "1.0.0"
|
||||||
|
host: localhost:8008
|
||||||
|
schemes:
|
||||||
|
- https
|
||||||
|
- http
|
||||||
|
basePath: /_matrix/client/%CLIENT_MAJOR_VERSION%
|
||||||
|
consumes:
|
||||||
|
- application/json
|
||||||
|
produces:
|
||||||
|
- application/json
|
||||||
|
securityDefinitions:
|
||||||
|
$ref: definitions/security.yaml
|
||||||
|
paths:
|
||||||
|
"/keys/upload":
|
||||||
|
post:
|
||||||
|
summary: Upload end-to-end encryption keys.
|
||||||
|
description: |-
|
||||||
|
Publishes end-to-end encryption keys for the device.
|
||||||
|
security:
|
||||||
|
- accessToken: []
|
||||||
|
parameters:
|
||||||
|
- in: body
|
||||||
|
name: keys
|
||||||
|
description: |-
|
||||||
|
The keys to be published
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
device_keys:
|
||||||
|
description: |-
|
||||||
|
Identity keys for the device. May be absent if no new
|
||||||
|
identity keys are required.
|
||||||
|
allOf:
|
||||||
|
- $ref: definitions/device_keys.yaml
|
||||||
|
one_time_keys:
|
||||||
|
type: object
|
||||||
|
description: |-
|
||||||
|
One-time public keys for "pre-key" messages. The names of
|
||||||
|
the properties should be in the format
|
||||||
|
``<algorithm>:<key_id>``. The format of the key is determined
|
||||||
|
by the key algorithm.
|
||||||
|
|
||||||
|
May be absent if no new one-time keys are required.
|
||||||
|
additionalProperties:
|
||||||
|
type:
|
||||||
|
- string
|
||||||
|
- object
|
||||||
|
example:
|
||||||
|
"curve25519:AAAAAQ": "/qyvZvwjiTxGdGU0RCguDCLeR+nmsb3FfNG3/Ve4vU8"
|
||||||
|
signed_curve25519:AAAAHg:
|
||||||
|
key: "zKbLg+NrIjpnagy+pIY6uPL4ZwEG2v+8F9lmgsnlZzs"
|
||||||
|
signatures:
|
||||||
|
"@alice:example.com":
|
||||||
|
ed25519:JLAFKJWSCS: "FLWxXqGbwrb8SM3Y795eB6OA8bwBcoMZFXBqnTn58AYWZSqiD45tlBVcDa2L7RwdKXebW/VzDlnfVJ+9jok1Bw"
|
||||||
|
signed_curve25519:AAAAHQ:
|
||||||
|
key: "j3fR3HemM16M7CWhoI4Sk5ZsdmdfQHsKL1xuSft6MSw"
|
||||||
|
signatures:
|
||||||
|
"@alice:example.com":
|
||||||
|
ed25519:JLAFKJWSCS: "IQeCEPb9HFk217cU9kw9EOiusC6kMIkoIRnbnfOh5Oc63S1ghgyjShBGpu34blQomoalCyXWyhaaT3MrLZYQAA"
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
description:
|
||||||
|
The provided keys were sucessfully uploaded.
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
one_time_key_counts:
|
||||||
|
type: object
|
||||||
|
additionalProperties:
|
||||||
|
type: integer
|
||||||
|
description: |-
|
||||||
|
For each key algorithm, the number of unclaimed one-time keys
|
||||||
|
of that type currently held on the server for this device.
|
||||||
|
example:
|
||||||
|
curve25519: 10
|
||||||
|
signed_curve25519: 20
|
||||||
|
required:
|
||||||
|
- one_time_key_counts
|
||||||
|
|
||||||
|
tags:
|
||||||
|
- End-to-end encryption
|
||||||
|
"/keys/query":
|
||||||
|
post:
|
||||||
|
summary: Download device identity keys.
|
||||||
|
description: |-
|
||||||
|
Returns the current devices and identity keys for the given users.
|
||||||
|
security:
|
||||||
|
- accessToken: []
|
||||||
|
parameters:
|
||||||
|
- in: body
|
||||||
|
name: query
|
||||||
|
description: |-
|
||||||
|
Query defining the keys to be downloaded
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
timeout:
|
||||||
|
type: integer
|
||||||
|
description: |-
|
||||||
|
The time (in milliseconds) to wait when downloading keys from
|
||||||
|
remote servers. 10 seconds is the recommended default.
|
||||||
|
example: 10000
|
||||||
|
device_keys:
|
||||||
|
type: object
|
||||||
|
description: |-
|
||||||
|
The keys to be downloaded. A map from user ID, to a list of
|
||||||
|
device IDs, or to an empty list to indicate all devices for the
|
||||||
|
corresponding user.
|
||||||
|
additionalProperties:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
description: "device ID"
|
||||||
|
example:
|
||||||
|
"@alice:example.com": []
|
||||||
|
required:
|
||||||
|
- device_keys
|
||||||
|
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
description:
|
||||||
|
The device information
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
failures:
|
||||||
|
type: object
|
||||||
|
description: |-
|
||||||
|
If any remote homeservers could not be reached, they are
|
||||||
|
recorded here. The names of the properties are the names of
|
||||||
|
the unreachable servers.
|
||||||
|
|
||||||
|
If the homeserver could be reached, but the user or device
|
||||||
|
was unknown, no failure is recorded. Instead, the corresponding
|
||||||
|
user or device is missing from the ``device_keys`` result.
|
||||||
|
additionalProperties:
|
||||||
|
type: object
|
||||||
|
example: {}
|
||||||
|
device_keys:
|
||||||
|
type: object
|
||||||
|
description: |-
|
||||||
|
Information on the queried devices. A map from user ID, to a
|
||||||
|
map from device ID to device information. For each device,
|
||||||
|
the information returned will be the same as uploaded via
|
||||||
|
``/keys/upload``, with the addition of an ``unsigned``
|
||||||
|
property.
|
||||||
|
additionalProperties:
|
||||||
|
type: object
|
||||||
|
additionalProperties:
|
||||||
|
allOf:
|
||||||
|
- $ref: definitions/device_keys.yaml
|
||||||
|
properties:
|
||||||
|
unsigned:
|
||||||
|
title: UnsignedDeviceInfo
|
||||||
|
type: object
|
||||||
|
description: |-
|
||||||
|
Additional data added to the device key information
|
||||||
|
by intermediate servers, and not covered by the
|
||||||
|
signatures.
|
||||||
|
properties:
|
||||||
|
device_display_name:
|
||||||
|
type: string
|
||||||
|
description:
|
||||||
|
The display name which the user set on the device.
|
||||||
|
example:
|
||||||
|
"@alice:example.com":
|
||||||
|
JLAFKJWSCS: {
|
||||||
|
"user_id": "@alice:example.com",
|
||||||
|
"device_id": "JLAFKJWSCS",
|
||||||
|
"algorithms": [
|
||||||
|
"m.olm.curve25519-aes-sha256",
|
||||||
|
"m.megolm.v1.aes-sha"
|
||||||
|
],
|
||||||
|
"keys": {
|
||||||
|
"curve25519:JLAFKJWSCS": "3C5BFWi2Y8MaVvjM8M22DBmh24PmgR0nPvJOIArzgyI",
|
||||||
|
"ed25519:JLAFKJWSCS": "lEuiRJBit0IG6nUf5pUzWTUEsRVVe/HJkoKuEww9ULI"
|
||||||
|
},
|
||||||
|
"signatures": {
|
||||||
|
"@alice:example.com": {
|
||||||
|
"ed25519:JLAFKJWSCS": "dSO80A01XiigH3uBiDVx/EjzaoycHcjq9lfQX0uWsqxl2giMIiSPR8a4d291W1ihKJL/a+myXS367WT6NAIcBA"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"unsigned": {
|
||||||
|
"device_display_name": "Alice's mobile phone"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tags:
|
||||||
|
- End-to-end encryption
|
||||||
|
"/keys/claim":
|
||||||
|
post:
|
||||||
|
summary: Claim one-time encryption keys.
|
||||||
|
description: |-
|
||||||
|
Claims one-time keys for use in pre-key messages.
|
||||||
|
security:
|
||||||
|
- accessToken: []
|
||||||
|
parameters:
|
||||||
|
- in: body
|
||||||
|
name: query
|
||||||
|
description: |-
|
||||||
|
Query defining the keys to be claimed
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
timeout:
|
||||||
|
type: integer
|
||||||
|
description: |-
|
||||||
|
The time (in milliseconds) to wait when downloading keys from
|
||||||
|
remote servers. 10 seconds is the recommended default.
|
||||||
|
example: 10000
|
||||||
|
one_time_keys:
|
||||||
|
type: object
|
||||||
|
description: |-
|
||||||
|
The keys to be claimed. A map from user ID, to a map from
|
||||||
|
device ID to algorithm name.
|
||||||
|
additionalProperties:
|
||||||
|
type: object
|
||||||
|
additionalProperties:
|
||||||
|
type: string
|
||||||
|
description: algorithm
|
||||||
|
example: "signed_curve25519"
|
||||||
|
example:
|
||||||
|
"@alice:example.com": { "JLAFKJWSCS": "curve25519" }
|
||||||
|
required:
|
||||||
|
- one_time_keys
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
description:
|
||||||
|
The claimed keys
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
failures:
|
||||||
|
type: object
|
||||||
|
description: |-
|
||||||
|
If any remote homeservers could not be reached, they are
|
||||||
|
recorded here. The names of the properties are the names of
|
||||||
|
the unreachable servers.
|
||||||
|
|
||||||
|
If the homeserver could be reached, but the user or device
|
||||||
|
was unknown, no failure is recorded. Instead, the corresponding
|
||||||
|
user or device is missing from the ``one_time_keys`` result.
|
||||||
|
additionalProperties:
|
||||||
|
type: object
|
||||||
|
example: {}
|
||||||
|
one_time_keys:
|
||||||
|
type: object
|
||||||
|
description: |-
|
||||||
|
One-time keys for the queried devices. A map from user ID, to a
|
||||||
|
map from ``<algorithm>:<key_id>`` to the key object.
|
||||||
|
additionalProperties:
|
||||||
|
type: object
|
||||||
|
additionalProperties:
|
||||||
|
type:
|
||||||
|
- string
|
||||||
|
- object
|
||||||
|
example:
|
||||||
|
"@alice:example.com":
|
||||||
|
JLAFKJWSCS:
|
||||||
|
signed_curve25519:AAAAHg:
|
||||||
|
key: "zKbLg+NrIjpnagy+pIY6uPL4ZwEG2v+8F9lmgsnlZzs"
|
||||||
|
signatures:
|
||||||
|
"@alice:example.com":
|
||||||
|
ed25519:JLAFKJWSCS: "FLWxXqGbwrb8SM3Y795eB6OA8bwBcoMZFXBqnTn58AYWZSqiD45tlBVcDa2L7RwdKXebW/VzDlnfVJ+9jok1Bw"
|
||||||
|
tags:
|
||||||
|
- End-to-end encryption
|
||||||
|
"/keys/changes":
|
||||||
|
get:
|
||||||
|
summary: Query users with recent device key updates.
|
||||||
|
description: |-
|
||||||
|
Gets a list of users who have updated their device identity keys since a
|
||||||
|
previous sync token.
|
||||||
|
|
||||||
|
The server should include in the results any users who:
|
||||||
|
|
||||||
|
* currently share a room with the calling user (ie, both users have
|
||||||
|
membership state ``join``); *and*
|
||||||
|
* added new device identity keys or removed an existing device with
|
||||||
|
identity keys, between ``from`` and ``to``.
|
||||||
|
security:
|
||||||
|
- accessToken: []
|
||||||
|
parameters:
|
||||||
|
- in: query
|
||||||
|
name: from
|
||||||
|
type: string
|
||||||
|
description: |-
|
||||||
|
The desired start point of the list. Should be the ``next_batch`` field
|
||||||
|
from a response to an earlier call to |/sync|. Users who have not
|
||||||
|
uploaded new device identity keys since this point, nor deleted
|
||||||
|
existing devices with identity keys since then, will be excluded
|
||||||
|
from the results.
|
||||||
|
required: true
|
||||||
|
x-example: "s72594_4483_1934"
|
||||||
|
- in: query
|
||||||
|
name: to
|
||||||
|
type: string
|
||||||
|
description: |-
|
||||||
|
The desired end point of the list. Should be the ``next_batch``
|
||||||
|
field from a recent call to |/sync| - typically the most recent
|
||||||
|
such call. This may be used by the server as a hint to check its
|
||||||
|
caches are up to date.
|
||||||
|
required: true
|
||||||
|
x-example: "s75689_5632_2435"
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
description:
|
||||||
|
The list of users who updated their devices.
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
changes:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
description: |-
|
||||||
|
The Matrix User IDs of all users who updated their device
|
||||||
|
identity keys.
|
||||||
|
example: ["@alice:example.com", "@bob:example.org"]
|
||||||
|
tags:
|
||||||
|
- End-to-end encryption
|
|
@ -242,6 +242,12 @@ paths:
|
||||||
description: |-
|
description: |-
|
||||||
Information on the send-to-device messages for the client
|
Information on the send-to-device messages for the client
|
||||||
device, as defined in |send_to_device_sync|_.
|
device, as defined in |send_to_device_sync|_.
|
||||||
|
device_lists:
|
||||||
|
title: DeviceLists
|
||||||
|
type: object
|
||||||
|
description: |-
|
||||||
|
Information on end-to-end device updates, as specified in
|
||||||
|
|device_lists_sync|_.
|
||||||
examples:
|
examples:
|
||||||
application/json: |-
|
application/json: |-
|
||||||
{
|
{
|
||||||
|
|
|
@ -46,6 +46,8 @@
|
||||||
- Allow guest accounts to use a number of endpoints which are required for
|
- Allow guest accounts to use a number of endpoints which are required for
|
||||||
end-to-end encryption.
|
end-to-end encryption.
|
||||||
(`#751 <https://github.com/matrix-org/matrix-doc/pull/751>`_).
|
(`#751 <https://github.com/matrix-org/matrix-doc/pull/751>`_).
|
||||||
|
- Add key distribution APIs, for use with end-to-end encryption.
|
||||||
|
(`#894 <https://github.com/matrix-org/matrix-doc/pull/894>`_).
|
||||||
|
|
||||||
- Spec clarifications:
|
- Spec clarifications:
|
||||||
|
|
||||||
|
|
|
@ -1436,3 +1436,5 @@ have to wait in milliseconds before they can try again.
|
||||||
|
|
||||||
.. |/user/<user_id>/account_data/<type>| replace:: ``/user/<user_id>/account_data/<type>``
|
.. |/user/<user_id>/account_data/<type>| replace:: ``/user/<user_id>/account_data/<type>``
|
||||||
.. _/user/<user_id>/account_data/<type>: #put-matrix-client-%CLIENT_MAJOR_VERSION%-user-userid-account-data-type
|
.. _/user/<user_id>/account_data/<type>: #put-matrix-client-%CLIENT_MAJOR_VERSION%-user-userid-account-data-type
|
||||||
|
|
||||||
|
.. _`Unpadded Base64`: ../appendices.html#unpadded-base64
|
||||||
|
|
|
@ -17,6 +17,290 @@ End-to-End Encryption
|
||||||
|
|
||||||
.. _module:e2e:
|
.. _module:e2e:
|
||||||
|
|
||||||
End to end encryption is being worked on and will be coming soon.
|
Matrix optionally supports end-to-end encryption, allowing rooms to be created
|
||||||
|
whose conversation contents is not decryptable or interceptable on any of the
|
||||||
|
participating homeservers.
|
||||||
|
|
||||||
You can read about what's underway at http://matrix.org/speculator/spec/drafts%2Fe2e/client_server/unstable.html#end-to-end-encryption.
|
.. WARNING::
|
||||||
|
|
||||||
|
End to end encryption is being worked on and will be coming soon. This
|
||||||
|
section is incomplete. You can read more about what's underway at
|
||||||
|
http://matrix.org/speculator/spec/drafts%2Fe2e/client_server/unstable.html#end-to-end-encryption.
|
||||||
|
|
||||||
|
Key Distribution
|
||||||
|
----------------
|
||||||
|
Encryption and Authentication in Matrix is based around public-key
|
||||||
|
cryptography. The Matrix protocol provides a basic mechanism for exchange of
|
||||||
|
public keys, though an out-of-band channel is required to exchange fingerprints
|
||||||
|
between users to build a web of trust.
|
||||||
|
|
||||||
|
Overview
|
||||||
|
~~~~~~~~
|
||||||
|
|
||||||
|
.. code::
|
||||||
|
|
||||||
|
1) Bob publishes the public keys and supported algorithms for his
|
||||||
|
device. This may include long-term identity keys, and/or one-time
|
||||||
|
keys.
|
||||||
|
|
||||||
|
+----------+ +--------------+
|
||||||
|
| Bob's HS | | Bob's Device |
|
||||||
|
+----------+ +--------------+
|
||||||
|
| |
|
||||||
|
|<=============|
|
||||||
|
/keys/upload
|
||||||
|
|
||||||
|
2) Alice requests Bob's public identity keys and supported algorithms.
|
||||||
|
|
||||||
|
+----------------+ +------------+ +----------+
|
||||||
|
| Alice's Device | | Alice's HS | | Bob's HS |
|
||||||
|
+----------------+ +------------+ +----------+
|
||||||
|
| | |
|
||||||
|
|=================>|==============>|
|
||||||
|
/keys/query <federation>
|
||||||
|
|
||||||
|
3) Alice selects an algorithm and claims any one-time keys needed.
|
||||||
|
|
||||||
|
+----------------+ +------------+ +----------+
|
||||||
|
| Alice's Device | | Alice's HS | | Bob's HS |
|
||||||
|
+----------------+ +------------+ +----------+
|
||||||
|
| | |
|
||||||
|
|=================>|==============>|
|
||||||
|
/keys/claim <federation>
|
||||||
|
|
||||||
|
|
||||||
|
Key algorithms
|
||||||
|
~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
The name ``ed25519`` corresponds to the `Ed25519`_ signature algorithm. The key
|
||||||
|
is a 32-byte Ed25519 public key, encoded using `unpadded Base64`_. Example:
|
||||||
|
|
||||||
|
.. code:: json
|
||||||
|
|
||||||
|
"SogYyrkTldLz0BXP+GYWs0qaYacUI0RleEqNT8J3riQ"
|
||||||
|
|
||||||
|
The name ``curve25519`` corresponds to the `Curve25519`_ ECDH algorithm. The
|
||||||
|
key is a 32-byte Curve25519 public key, encoded using `unpadded
|
||||||
|
Base64`_. Example:
|
||||||
|
|
||||||
|
.. code:: json
|
||||||
|
|
||||||
|
"JGLn/yafz74HB2AbPLYJWIVGnKAtqECOBf11yyXac2Y"
|
||||||
|
|
||||||
|
The name ``signed_curve25519`` also corresponds to the Curve25519 algorithm,
|
||||||
|
but keys using this algorithm are objects with the properties ``key`` (giving
|
||||||
|
the Base64-encoded 32-byte Curve25519 public key), and ``signatures`` (giving a
|
||||||
|
signature for the key object, as described in `Signing JSON`_). Example:
|
||||||
|
|
||||||
|
.. code:: json
|
||||||
|
|
||||||
|
{
|
||||||
|
"key":"06UzBknVHFMwgi7AVloY7ylC+xhOhEX4PkNge14Grl8",
|
||||||
|
"signatures": {
|
||||||
|
"@user:example.com": {
|
||||||
|
"ed25519:EGURVBUNJP": "YbJva03ihSj5mPk+CHMJKUKlCXCPFXjXOK6VqBnN9nA2evksQcTGn6hwQfrgRHIDDXO2le49x7jnWJHMJrJoBQ"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Device keys
|
||||||
|
~~~~~~~~~~~
|
||||||
|
|
||||||
|
Each device should have one Ed25519 signing key. This key should be generated
|
||||||
|
on the device from a cryptographically secure source, and the private part of
|
||||||
|
the key should never be exported from the device. This key is used as the
|
||||||
|
fingerprint for a device by other clients.
|
||||||
|
|
||||||
|
A device will generally need to generate a number of additional keys. Details
|
||||||
|
of these will vary depending on the messaging algorithm in use.
|
||||||
|
|
||||||
|
Algorithms generally require device identity keys as well as signing keys. Some
|
||||||
|
algorithms also require one-time keys to improve their secrecy and deniability.
|
||||||
|
These keys are used once during session establishment, and are then thrown
|
||||||
|
away.
|
||||||
|
|
||||||
|
For Olm version 1, each device requires a single Curve25519 identity key, and a
|
||||||
|
number of signed Curve25519 one-time keys.
|
||||||
|
|
||||||
|
Uploading keys
|
||||||
|
~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
A device uploads the public parts of identity keys to their homeserver as a
|
||||||
|
signed JSON object, using the |/keys/upload|_ API.
|
||||||
|
The JSON object must include the public part of the device's Ed25519 key, and
|
||||||
|
must be signed by that key, as described in `Signing JSON`_.
|
||||||
|
|
||||||
|
One-time keys are also uploaded to the homeserver using the |/keys/upload|_
|
||||||
|
API.
|
||||||
|
|
||||||
|
Devices must store the private part of each key they upload. They can
|
||||||
|
discard the private part of a one-time key when they receive a message using
|
||||||
|
that key. However it's possible that a one-time key given out by a homeserver
|
||||||
|
will never be used, so the device that generates the key will never know that
|
||||||
|
it can discard the key. Therefore a device could end up trying to store too
|
||||||
|
many private keys. A device that is trying to store too many private keys may
|
||||||
|
discard keys starting with the oldest.
|
||||||
|
|
||||||
|
Tracking the device list for a user
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Before Alice can send an encrypted message to Bob, she needs a list of each of
|
||||||
|
his devices and the associated identity keys, so that she can establish an
|
||||||
|
encryption session with each device. This list can be obtained by calling
|
||||||
|
|/keys/query|_, passing Bob's user ID in the ``device_keys`` parameter.
|
||||||
|
|
||||||
|
From time to time, Bob may add new devices, and Alice will need to know this so
|
||||||
|
that she can include his new devices for later encrypted messages. A naive
|
||||||
|
solution to this would be to call |/keys/query|_ before sending each message -
|
||||||
|
however, the number of users and devices may be large and this would be
|
||||||
|
inefficient.
|
||||||
|
|
||||||
|
It is therefore expected that each client will maintain a list of devices for a
|
||||||
|
number of users (in practice, typically each user with whom we share an
|
||||||
|
encrypted room). Furthermore, it is likely that this list will need to be
|
||||||
|
persisted between invocations of the client application (to preserve device
|
||||||
|
verification data and to alert Alice if Bob suddently gets a new
|
||||||
|
device).
|
||||||
|
|
||||||
|
Alice's client can maintain a list of Bob's devices via the following
|
||||||
|
process:
|
||||||
|
|
||||||
|
#. It first sets a flag to record that it is now tracking Bob's device list,
|
||||||
|
and a separate flag to indicate that its list of Bob's devices is
|
||||||
|
outdated. Both flags should be in storage which persists over client
|
||||||
|
restarts.
|
||||||
|
|
||||||
|
#. It then makes a request to |/keys/query|_, passing Bob's user ID in the
|
||||||
|
``device_keys`` parameter. When the request completes, it stores the
|
||||||
|
resulting list of devices in persistent storage, and clears the 'outdated'
|
||||||
|
flag.
|
||||||
|
|
||||||
|
#. During its normal processing of responses to |/sync|_, Alice's client
|
||||||
|
inspects the |device_lists|_ field. If it is tracking the device lists of
|
||||||
|
any of the listed users, then it marks the device lists for those users
|
||||||
|
outdated, and initiates another request to |/keys/query|_ for them.
|
||||||
|
|
||||||
|
#. Periodically, Alice's client stores the ``next_batch`` field of the result
|
||||||
|
from |/sync|_ in persistent storage. If Alice later restarts her client, it
|
||||||
|
can obtain a list of the users who have updated their device list while it
|
||||||
|
was offline by calling |/keys/changes|_, passing the recorded ``next_batch``
|
||||||
|
field as the ``from`` parameter. If the client is tracking the device list
|
||||||
|
of any of the users listed in the response, it marks them as outdated. It
|
||||||
|
combines this list with those already flagged as outdated, and initiates a
|
||||||
|
|/keys/query|_ requests for all of them.
|
||||||
|
|
||||||
|
.. Warning::
|
||||||
|
|
||||||
|
Bob may update one of his devices while Alice has a request to
|
||||||
|
``/keys/query`` in flight. Alice's client may therefore see Bob's user ID in
|
||||||
|
the ``device_lists`` field of the ``/sync`` response while the first request
|
||||||
|
is in flight, and initiate a second request to ``/keys/query``. This may
|
||||||
|
lead to either of two related problems.
|
||||||
|
|
||||||
|
The first problem is that, when the first request completes, the client will
|
||||||
|
clear the 'outdated' flag for Bob's devices. If the second request fails, or
|
||||||
|
the client is shut down before it completes, this could lead to Alice using
|
||||||
|
an outdated list of Bob's devices.
|
||||||
|
|
||||||
|
The second possibility is that, under certain conditions, the second request
|
||||||
|
may complete *before* the first one. When the first request completes, the
|
||||||
|
client could overwrite the later results from the second request with those
|
||||||
|
from the first request.
|
||||||
|
|
||||||
|
Clients MUST guard against these situations. For example, a client could
|
||||||
|
ensure that only one request to ``/keys/query`` is in flight at a time for
|
||||||
|
each user, by queuing additional requests until the first completes.
|
||||||
|
Alternatively, the client could make a new request immediately, but ensure
|
||||||
|
that the first request's results are ignored (possibly by cancelling the
|
||||||
|
request).
|
||||||
|
|
||||||
|
.. |device_lists| replace:: ``device_lists``
|
||||||
|
.. _`device_lists`: `device_lists_sync`_
|
||||||
|
|
||||||
|
Claiming one-time keys
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
A client wanting to set up a session with another device can claim a one-time
|
||||||
|
key for that device. This is done by making a request to the |/keys/claim|_
|
||||||
|
API.
|
||||||
|
|
||||||
|
A homeserver should rate-limit the number of one-time keys that a given user or
|
||||||
|
remote server can claim. A homeserver should discard the public part of a one
|
||||||
|
time key once it has given that key to another user.
|
||||||
|
|
||||||
|
|
||||||
|
Protocol definitions
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
{{keys_cs_http_api}}
|
||||||
|
|
||||||
|
|
||||||
|
.. anchor for link from /sync api spec
|
||||||
|
.. |device_lists_sync| replace:: End-to-end encryption
|
||||||
|
.. _device_lists_sync:
|
||||||
|
|
||||||
|
Extensions to /sync
|
||||||
|
~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
This module adds an optional ``device_lists`` property to the |/sync|_
|
||||||
|
response, as specified below. The server need only populate this property for
|
||||||
|
an incremental ``/sync`` (ie, one where the ``since`` parameter was
|
||||||
|
specified). The client is expected to use |/keys/query|_ or |/keys/changes|_
|
||||||
|
for the equivalent functionality after an initial sync, as documented in
|
||||||
|
`Tracking the device list for a user`_.
|
||||||
|
|
||||||
|
.. todo: generate this from a swagger definition?
|
||||||
|
|
||||||
|
.. device_lists: { changed: ["@user:server", ... ]},
|
||||||
|
|
||||||
|
============ =========== =====================================================
|
||||||
|
Parameter Type Description
|
||||||
|
============ =========== =====================================================
|
||||||
|
device_lists DeviceLists Optional. Information on e2e device updates. Note:
|
||||||
|
only present on an incremental sync.
|
||||||
|
============ =========== =====================================================
|
||||||
|
|
||||||
|
``DeviceLists``
|
||||||
|
|
||||||
|
========= ========= =============================================
|
||||||
|
Parameter Type Description
|
||||||
|
========= ========= =============================================
|
||||||
|
changed [string] List of users who have updated their device identity keys
|
||||||
|
since the previous sync response.
|
||||||
|
========= ========= =============================================
|
||||||
|
|
||||||
|
|
||||||
|
Example response:
|
||||||
|
|
||||||
|
.. code:: json
|
||||||
|
|
||||||
|
{
|
||||||
|
"next_batch": "s72595_4483_1934",
|
||||||
|
"rooms": {"leave": {}, "join": {}, "invite": {}},
|
||||||
|
"device_lists": {
|
||||||
|
"changed": [
|
||||||
|
"@alice:example.com",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
.. References
|
||||||
|
|
||||||
|
.. _ed25519: http://ed25519.cr.yp.to/
|
||||||
|
.. _curve25519: https://cr.yp.to/ecdh.html
|
||||||
|
|
||||||
|
.. _`Signing JSON`: ../appendices.html#signing-json
|
||||||
|
|
||||||
|
.. |m.olm.v1.curve25519-aes-sha2| replace:: ``m.olm.v1.curve25519-aes-sha2``
|
||||||
|
|
||||||
|
.. |/keys/upload| replace:: ``/keys/upload``
|
||||||
|
.. _/keys/upload: #post-matrix-client-%CLIENT_MAJOR_VERSION%-keys-upload
|
||||||
|
|
||||||
|
.. |/keys/query| replace:: ``/keys/query``
|
||||||
|
.. _/keys/query: #post-matrix-client-%CLIENT_MAJOR_VERSION%-keys-query
|
||||||
|
|
||||||
|
.. |/keys/claim| replace:: ``/keys/claim``
|
||||||
|
.. _/keys/claim: #post-matrix-client-%CLIENT_MAJOR_VERSION%-keys-claim
|
||||||
|
|
||||||
|
.. |/keys/changes| replace:: ``/keys/changes``
|
||||||
|
.. _/keys/changes: #get-matrix-client-%CLIENT_MAJOR_VERSION%-keys-changes
|
||||||
|
|
|
@ -12,11 +12,12 @@
|
||||||
.. See the License for the specific language governing permissions and
|
.. See the License for the specific language governing permissions and
|
||||||
.. limitations under the License.
|
.. limitations under the License.
|
||||||
|
|
||||||
|
.. _module:to_device:
|
||||||
|
.. _`to-device`:
|
||||||
|
|
||||||
Send-to-Device messaging
|
Send-to-Device messaging
|
||||||
========================
|
========================
|
||||||
|
|
||||||
.. _module:to_device:
|
|
||||||
|
|
||||||
This module provides a means by which clients can exchange signalling messages
|
This module provides a means by which clients can exchange signalling messages
|
||||||
without them being stored permanently as part of a shared communication
|
without them being stored permanently as part of a shared communication
|
||||||
history. A message is delivered exactly once to each client device.
|
history. A message is delivered exactly once to each client device.
|
||||||
|
@ -35,10 +36,13 @@ have the same event type. The device ID in the request body can be set to ``*``
|
||||||
to request that the message be sent to all known devices.
|
to request that the message be sent to all known devices.
|
||||||
|
|
||||||
If there are send-to-device messages waiting for a client, they will be
|
If there are send-to-device messages waiting for a client, they will be
|
||||||
returned by |/sync|_, as detailed in `Extensions to /sync`_. Clients should
|
returned by |/sync|_, as detailed in |Extensions|_. Clients should
|
||||||
inspect the ``type`` of each returned event, and ignore any they do not
|
inspect the ``type`` of each returned event, and ignore any they do not
|
||||||
understand.
|
understand.
|
||||||
|
|
||||||
|
.. |Extensions| replace:: Extensions to /sync
|
||||||
|
.. _Extensions: `send_to_device_sync`_
|
||||||
|
|
||||||
Server behaviour
|
Server behaviour
|
||||||
----------------
|
----------------
|
||||||
Servers should store pending messages for local users until they are
|
Servers should store pending messages for local users until they are
|
||||||
|
|
|
@ -123,11 +123,6 @@ def get_json_schema_object_fields(obj, enforce_title=False):
|
||||||
|
|
||||||
logger.debug("Processing object with title '%s'", obj_title)
|
logger.debug("Processing object with title '%s'", obj_title)
|
||||||
|
|
||||||
if enforce_title and not obj_title:
|
|
||||||
# Force a default titile of "NO_TITLE" to make it obvious in the
|
|
||||||
# specification output which parts of the schema are missing a title
|
|
||||||
obj_title = 'NO_TITLE'
|
|
||||||
|
|
||||||
additionalProps = obj.get("additionalProperties")
|
additionalProps = obj.get("additionalProperties")
|
||||||
props = obj.get("properties")
|
props = obj.get("properties")
|
||||||
if additionalProps and not props:
|
if additionalProps and not props:
|
||||||
|
@ -151,14 +146,21 @@ def get_json_schema_object_fields(obj, enforce_title=False):
|
||||||
props[pretty_key] = props[key_name]
|
props[pretty_key] = props[key_name]
|
||||||
del props[key_name]
|
del props[key_name]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Sometimes you just want to specify that a thing is an object without
|
# Sometimes you just want to specify that a thing is an object without
|
||||||
# doing all the keys.
|
# doing all the keys.
|
||||||
if not props:
|
if not props:
|
||||||
return {
|
return {
|
||||||
"type": obj_title,
|
"type": obj_title if obj_title else 'object',
|
||||||
"tables": [],
|
"tables": [],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if enforce_title and not obj_title:
|
||||||
|
# Force a default titile of "NO_TITLE" to make it obvious in the
|
||||||
|
# specification output which parts of the schema are missing a title
|
||||||
|
obj_title = 'NO_TITLE'
|
||||||
|
|
||||||
required_keys = set(obj.get("required", []))
|
required_keys = set(obj.get("required", []))
|
||||||
|
|
||||||
first_table_rows = []
|
first_table_rows = []
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue