Merge pull request #2536 from uhoreg/cross-signing-spec

initial spec for cross-signing
pull/2951/head
Hubert Chathi 3 years ago committed by GitHub
commit f352de90c3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,224 @@
# Copyright 2020 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.
swagger: '2.0'
info:
title: "Matrix Client-Server Cross Signing 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/device_signing/upload":
post:
summary: Upload cross-signing keys.
description: |-
Publishes cross-signing keys for the user.
This API endpoint uses the `User-Interactive Authentication API`_.
operationId: uploadCrossSigningKeys
security:
- accessToken: []
parameters:
- in: body
name: keys
description: |-
The keys to be published.
schema:
type: object
properties:
master_key:
description: |-
Optional. The user\'s master 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
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
request.
allOf:
- $ref: definitions/cross_signing_key.yaml
example: {
"master_key": {
"user_id": "@alice:example.com",
"usage": ["master"],
"keys": {
"ed25519:base64+master+public+key": "base64+master+public+key",
}
},
"self_signing_key": {
"user_id": "@alice:example.com",
"usage": ["self_signing"],
"keys": {
"ed25519:base64+self+signing+public+key": "base64+self+signing+master+public+key",
},
"signatures": {
"@alice:example.com": {
"ed25519:base64+master+public+key": "signature+of+self+signing+key"
}
}
},
"user_signing_key": {
"user_id": "@alice:example.com",
"usage": ["user_signing"],
"keys": {
"ed25519:base64+user+signing+public+key": "base64+user+signing+master+public+key",
},
"signatures": {
"@alice:example.com": {
"ed25519:base64+master+public+key": "signature+of+user+signing+key"
}
}
}
}
responses:
200:
description: The provided keys were successfully uploaded.
schema:
type: object
example: {}
400:
description: |-
The input was invalid in some way. This can include one of the
following error codes:
* ``M_INVALID_SIGNATURE``: For example, the self-signing or
user-signing key had an incorrect signature.
* ``M_MISSING_PARAM``: No master key is available.
schema:
type: object
example: {
"errcode": "M_INVALID_SIGNATURE",
"error": "Invalid signature"
}
403:
description: |-
The public key of one of the keys is the same as one of the user\'s
device IDs, or the request is not authorized for any other reason.
schema:
type: object
example: {
"errcode": "M_FORBIDDEN",
"error": "Key ID in use"
}
"/keys/signatures/upload":
post:
summary: Upload cross-signing signatures.
description: |-
Publishes cross-signing signatures for the user. The request body is a
map from user ID to key ID to signed JSON object.
operationId: uploadCrossSigningSignatures
security:
- accessToken: []
parameters:
- in: body
name: signatures
description: |-
The signatures to be published.
schema:
type: object
title: Signatures
additionalProperties:
type: object
additionalProperties:
type: object
example: {
"@alice:example.com": {
"HIJKLMN": {
"user_id": "@alice:example.com",
"device_id": "HIJKLMN",
"algorithms": [
"m.olm.curve25519-aes-sha256",
"m.megolm.v1.aes-sha"
],
"keys": {
"curve25519:HIJKLMN": "base64+curve25519+key",
"ed25519:HIJKLMN": "base64+ed25519+key"
},
"signatures": {
"@alice:example.com": {
"ed25519:base64+self+signing+public+key": "base64+signature+of+HIJKLMN"
}
}
},
"base64+master+public+key": {
"user_id": "@alice:example.com",
"usage": ["master"],
"keys": {
"ed25519:base64+master+public+key": "base64+master+public+key"
},
"signatures": {
"@alice:example.com": {
"ed25519:HIJKLMN": "base64+signature+of+master+key"
}
}
}
},
"@bob:example.com": {
"bobs+base64+master+public+key": {
"user_id": "@bob:example.com",
"keys": {
"ed25519:bobs+base64+master+public+key": "bobs+base64+master+public+key"
},
"usage": ["master"],
"signatures": {
"@alice:example.com": {
"ed25519:base64+user+signing+public+key": "base64+signature+of+bobs+master+key"
}
}
}
}
}
responses:
200:
description: The provided signatures were processed.
schema:
type: object
properties:
failures:
type: object
description: |-
A map from user ID to key ID to an error for any signatures
that failed. If a signature was invalid, the ``errcode`` will
be set to ``M_INVALID_SIGNATURE``.
additionalProperties:
type: object
additionalProperties:
type: object
title: Error
example: {
"@alice:example.com": {
"HIJKLMN": {
"errcode": "M_INVALID_SIGNATURE",
"error": "Invalid signature"
}
}
}

@ -0,0 +1,55 @@
# Copyright 2020 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: CrossSigningKey
description: Cross signing key
properties:
user_id:
type: string
description: |-
The ID of the user the key belongs to.
example: "@alice:example.com"
usage:
type: array
description: |-
What the key is used for.
items:
type: string
enum: ["master", "self_signing", "user_signing"]
keys:
type: object
additionalProperties:
type: string
description: |-
The public key. The object must have exactly one property, whose name is
in the form ``<algorithm>:<unpadded_base64_public_key>``, and whose value
is the unpadded base64 public key.
example:
"ed25519:alice+base64+public+key": "alice+base64+public+key"
signatures:
type: object
title: Signatures
description: |-
Signatures of the key, calculated using the process described at `Signing
JSON`_. Optional for the master key. Other keys must be signed by the
user\'s master key.
example: {
"@alice:example.com": {
"ed25519:alice+base64+master+key": "signature+of+key"
}
}
required:
- user_id
- usage
- keys

@ -1,5 +1,6 @@
# Copyright 2016 OpenMarket Ltd
# Copyright 2018 New Vector Ltd
# Copyright 2020 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.
@ -236,7 +237,76 @@ paths:
"device_display_name": "Alice's mobile phone"
}
}
master_keys:
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 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
is allowed to see.
additionalProperties:
allOf:
- $ref: definitions/cross_signing_key.yaml
example: {
"@alice:example.com": {
"user_id": "@alice:example.com",
"usage": ["master"],
"keys": {
"ed25519:base64+master+public+key": "base64+master+public+key",
}
}
}
self_signing_keys:
type: object
description: |-
Information on the self-signing keys of the queried users. A map
from user ID, to self-signing key information. For each key, the
information returned will be the same as uploaded via
``/keys/device_signing/upload``.
additionalProperties:
allOf:
- $ref: definitions/cross_signing_key.yaml
example: {
"@alice:example.com": {
"user_id": "@alice:example.com",
"usage": ["self_signing"],
"keys": {
"ed25519:base64+self+signing+public+key": "base64+self+signing+master+public+key",
},
"signatures": {
"@alice:example.com": {
"ed25519:base64+master+public+key": "signature+of+self+signing+key"
}
}
}
}
user_signing_keys:
type: object
description: |-
Information on the user-signing key of the user making the
request, if they queried their own device information. A map
from user ID, to user-signing key information. The
information returned will be the same as uploaded via
``/keys/device_signing/upload``.
additionalProperties:
allOf:
- $ref: definitions/cross_signing_key.yaml
example: {
"@alice:example.com": {
"user_id": "@alice:example.com",
"usage": ["user_signing"],
"keys": {
"ed25519:base64+user+signing+public+key": "base64+user+signing+master+public+key",
},
"signatures": {
"@alice:example.com": {
"ed25519:base64+master+public+key": "signature+of+user+signing+key"
}
}
}
}
tags:
- End-to-end encryption
"/keys/claim":

@ -123,8 +123,10 @@ paths:
type: string
description: |-
ID of the client device. If this does not correspond to a
known client device, a new device will be created. The server
will auto-generate a device_id if this is not specified.
known client device, a new device will be created. The given
device ID must not be the same as a `cross-signing key ID
<#cross-signing>`_. The server will auto-generate a device_id
if this is not specified.
initial_device_display_name:
type: string
description: |-
@ -195,7 +197,9 @@ paths:
403:
description: |-
The login attempt failed. This can include one of the following error codes:
* ``M_FORBIDDEN``: The provided authentication data was incorrect.
* ``M_FORBIDDEN``: The provided authentication data was incorrect
or the requested device ID is the same as a cross-signing key
ID.
* ``M_USER_DEACTIVATED``: The user has been deactivated.
examples:
application/json: {

@ -1,4 +1,5 @@
# Copyright 2018 New Vector Ltd
# Copyright 2020 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.
@ -17,7 +18,8 @@ title: m.device_list_update
description: |-
An EDU that lets servers push details to each other when one of their users
adds a new device to their account, required for E2E encryption to correctly
target the current set of devices for a given user.
target the current set of devices for a given user. This event will also be
sent when an existing device gets a new cross-signing signature.
# FIXME: It's very unclear why we have this API surface for synchronising
# device lists, rather than just using a room (which could also be used for

@ -0,0 +1,64 @@
# Copyright 2020 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: m.signing_key_update
description: |-
An EDU that lets servers push details to each other when one of their users
updates their cross-signing keys.
allOf:
- $ref: ../edu.yaml
- type: object
properties:
edu_type:
type: enum
enum: ['m.signing_key_update']
description: The string ``m.signing_update``.
example: "m.signing_key_update"
content:
type: object
description: The updated signing keys.
title: Signing Key Update
properties:
user_id:
type: string
description: The user ID whose cross-signing keys have changed.
example: "@alice:example.com"
master_key:
type: object
$ref: ../../../client-server/definitions/cross_signing_key.yaml
example: {
"user_id": "@alice:example.com",
"usage": ["master"],
"keys": {
"ed25519:base64+master+public+key": "base64+master+public+key",
}
}
self_signing_key:
type: object
$ref: ../../../client-server/definitions/cross_signing_key.yaml
example: {
"user_id": "@alice:example.com",
"usage": ["self_signing"],
"keys": {
"ed25519:base64+self+signing+public+key": "base64+self+signing+master+public+key",
},
"signatures": {
"@alice:example.com": {
"ed25519:base64+master+public+key": "signature+of+self+signing+key"
}
}
}
required:
- user_id

@ -1,4 +1,5 @@
# Copyright 2018 New Vector Ltd
# Copyright 2020 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.
@ -81,4 +82,37 @@ paths:
description: Optional display name for the device.
example: "Alice's Mobile Phone"
required: ['device_id', 'keys']
master_key:
type: object
description: |-
The user\'s master cross-signing key.
allOf:
- $ref: ../client-server/definitions/cross_signing_key.yaml
# FIXME: why isn't the doc generator picking up this example?
- example: {
"user_id": "@alice:example.com",
"usage": ["master"],
"keys": {
"ed25519:base64+master+public+key": "base64+master+public+key",
}
}
self_signing_keys:
type: object
description: |-
The user\'s self-signing key.
allOf:
- $ref: ../client-server/definitions/cross_signing_key.yaml
# FIXME: why isn't the doc generator picking up this example?
- example: {
"user_id": "@alice:example.com",
"usage": ["self_signing"],
"keys": {
"ed25519:base64+self+signing+public+key": "base64+self+signing+master+public+key",
},
"signatures": {
"@alice:example.com": {
"ed25519:base64+master+public+key": "signature+of+self+signing+key"
}
}
}
required: ['user_id', 'stream_id', 'devices']

@ -1,4 +1,5 @@
# Copyright 2018 New Vector Ltd
# Copyright 2020 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.
@ -177,6 +178,51 @@ paths:
type: string
description:
The display name which the user set on the device.
master_keys:
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 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
allowed to see.
additionalProperties:
allOf:
- $ref: ../client-server/definitions/cross_signing_key.yaml
example: {
"@alice:example.com": {
"user_id": "@alice:example.com",
"usage": ["master"],
"keys": {
"ed25519:base64+master+public+key": "base64+master+public+key",
}
}
}
self_signing_keys:
type: object
description: |-
Information on the self-signing keys of the queried users. A map
from user ID, to self-signing key information. For each key, the
information returned will be the same as uploaded via
``/keys/device_signing/upload``.
additionalProperties:
allOf:
- $ref: ../client-server/definitions/cross_signing_key.yaml
example: {
"@alice:example.com": {
"user_id": "@alice:example.com",
"usage": ["self_signing"],
"keys": {
"ed25519:base64+self+signing+public+key": "base64+self+signing+master+public+key",
},
"signatures": {
"@alice:example.com": {
"ed25519:base64+master+public+key": "signature+of+self+signing+key"
}
}
}
}
required: ['device_keys']
examples:
application/json: {

@ -0,0 +1 @@
Add cross-signing properties to the response of ``POST /keys/query`` per [MSC1756](https://github.com/matrix-org/matrix-doc/pull/1756).

@ -0,0 +1 @@
Add ``POST /keys/device_signing/upload`` and ``POST /keys/signatures/upload`` per [MSC1756](https://github.com/matrix-org/matrix-doc/pull/1756).

@ -0,0 +1,9 @@
Add cross-signing:
- Add properties to the response of ``GET /user/keys`` and ``GET
/user/devices/{userId}``.
- The ``m.device_list_update`` EDU is sent when a device gets a new signature.
- A new ``m.signing_key_update`` EDU is sent when a user's cross-signing keys
are changed.
per [MSC1756](https://github.com/matrix-org/matrix-doc/pull/1756).

@ -1,5 +1,5 @@
.. Copyright 2016 OpenMarket Ltd
.. Copyright 2019 The Matrix.org Foundation C.I.C.
.. Copyright 2019-2020 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.
@ -776,6 +776,149 @@ common set of translations for all languages.
translated online: https://translate.riot.im/projects/matrix-doc/sas-emoji-v1
Cross-signing
~~~~~~~~~~~~~
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 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:
* a master key (MSK) that serves as the user's identity in cross-signing and signs
their other cross-signing keys;
* a user-signing key (USK) -- only visible to the user that it belongs to --
that signs other users' master 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 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 with her user-signing key.
Users upload their cross-signing keys to the server using `POST
/_matrix/client/r0/keys/device_signing/upload`_. When Alice uploads new
cross-signing 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/r0/keys/query`_ to retrieve Alice's device and
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 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
- Bob's self-signing key has signed Bob's device key.
The following diagram illustrates how keys are signed:
.. code::
+------------------+ .................. +----------------+
| +--------------+ | .................. : | +------------+ |
| | v v v : : v v v | |
| | +-----------+ : : +-----------+ | |
| | | Alice MSK | : : | Bob MSK | | |
| | +-----------+ : : +-----------+ | |
| | | : : : : | | |
| | +--+ :... : : ...: +--+ | |
| | v v : : v v | |
| | +-----------+ ............. : : ............. +-----------+ | |
| | | Alice SSK | : Alice USK : : : : Bob USK : | Bob SSK | | |
| | +-----------+ :...........: : : :...........: +-----------+ | |
| | | ... | : : : : | ... | | |
| | V V :........: :........: V V | |
| | +---------+ -+ +---------+ -+ | |
| | | Devices | ...| | Devices | ...| | |
| | +---------+ -+ +---------+ -+ | |
| | | ... | | ... | | |
| +------+ | | +----+ |
+----------------+ +--------------+
.. based on https://jcg.re/blog/quick-overview-matrix-cross-signing/
In the diagram, boxes represent keys and lines represent signatures with the
arrows pointing from the signing key to the key being signed. Dotted boxes and
lines represent keys and signatures that are only visible to the user who
created them.
The following diagram illustrates Alice's view, hiding the keys and signatures
that she cannot see:
.. code::
+------------------+ +----------------+ +----------------+
| +--------------+ | | | | +------------+ |
| | v v | v v v | |
| | +-----------+ | +-----------+ | |
| | | Alice MSK | | | Bob MSK | | |
| | +-----------+ | +-----------+ | |
| | | | | | | |
| | +--+ +--+ | +--+ | |
| | v v | v | |
| | +-----------+ +-----------+ | +-----------+ | |
| | | Alice SSK | | Alice USK | | | Bob SSK | | |
| | +-----------+ +-----------+ | +-----------+ | |
| | | ... | | | | ... | | |
| | V V +--------+ V V | |
| | +---------+ -+ +---------+ -+ | |
| | | Devices | ...| | Devices | ...| | |
| | +---------+ -+ +---------+ -+ | |
| | | ... | | ... | | |
| +------+ | | +----+ |
+----------------+ +--------------+
`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 ``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.
Key and signature security
<<<<<<<<<<<<<<<<<<<<<<<<<<
A user's master 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 storage system provided by
the operating system), then clients must not store the private part.
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.
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. 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 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 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
self-signing key, or
* signatures made by other users' devices about their respective master keys.
Users will not be able to see signatures made by other users' user-signing keys.
{{cross_signing_cs_http_api}}
.. section name changed, so make sure that old links keep working
.. _key-sharing:
@ -1302,7 +1445,8 @@ device_lists DeviceLists Optional. Information on e2e device updates. Note:
========= ========= =============================================
Parameter Type Description
========= ========= =============================================
changed [string] List of users who have updated their device identity keys,
changed [string] List of users who have updated their device identity or
cross-signing keys,
or who now share an encrypted room with the client since
the previous sync response.
left [string] List of users with whom we do not share any encrypted rooms
@ -1312,7 +1456,8 @@ left [string] List of users with whom we do not share any encrypted rooms
.. NOTE::
For optimal performance, Alice should be added to ``changed`` in Bob's sync only
when she adds a new device, or when Alice and Bob now share a room but didn't
when she updates her devices or cross-signing keys, or when Alice and Bob now
share a room but didn't
share any room previously. However, for the sake of simpler logic, a server
may add Alice to ``changed`` when Alice and Bob share a new room, even if they
previously already shared a room.

@ -1037,6 +1037,8 @@ through to federation, and have the response also be proxied through to the clie
{{user_keys_ss_http_api}}
{{definition_ss_event_schemas_m_signing_key_update}}
Send-to-device messaging
------------------------

Loading…
Cancel
Save