Merge pull request #2387 from uhoreg/key_backup_spec

initial version of spec for key backups
pull/2604/head
Hubert Chathi 4 years ago committed by GitHub
commit cf37688b7c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,50 @@
# Copyright 2019 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: KeyBackupData
description: "The key data"
properties:
first_message_index:
description: |-
The index of the first message in the session that the key can decrypt.
type: integer
example: 1
forwarded_count:
description: |-
The number of times this key has been forwarded via key-sharing between devices.
type: integer
example: 0
is_verified:
description: |-
Whether the device backing up the key verified the device that the key
is from.
type: boolean
example: false
session_data:
description: |-
Algorithm-dependent data. See the documentation for the backup
algorithms in `Server-side key backups`_ for more information on the
expected format of the data.
type: object
example: {
"ephemeral": "base64+ephemeral+key",
"ciphertext": "base64+ciphertext+of+JSON+data",
"mac": "base64+mac+of+ciphertext"
}
required:
- first_message_index
- forwarded_count
- is_verified
- session_data

@ -0,0 +1,940 @@
# 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.
# 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 Key Backup 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:
"/room_keys/version":
post:
summary: Create a new backup.
description: |-
Creates a new backup.
operationId: postRoomKeysVersion
security:
- accessToken: []
parameters:
- in: body
name: version
description: "The backup configuration."
schema:
type: object
properties:
algorithm:
description: The algorithm used for storing backups.
type: string
enum: ["m.megolm_backup.v1.curve25519-aes-sha2"]
example: "m.megolm_backup.v1.curve25519-aes-sha2"
auth_data:
description: |-
Algorithm-dependent data. See the documentation for the backup
algorithms in `Server-side key backups`_ for more information on the
expected format of the data.
type: object
example: {
"public_key": "abcdefg",
"signatures": {
"@alice:example.org": {
"ed25519:deviceid": "signature"
}
}
}
required:
- algorithm
- auth_data
responses:
200:
description:
The version id of the new backup.
schema:
type: object
properties:
version:
type: string
description: The backup version. This is an opaque string.
example: "1"
required:
- version
429:
description: This request was rate-limited.
schema:
"$ref": "definitions/errors/rate_limited.yaml"
tags:
- End-to-end encryption
get:
summary: Get information about the latest backup version.
description: |-
Get information about the latest backup version.
operationId: getRoomKeysVersionCurrent
security:
- accessToken: []
responses:
200:
description:
The information about the backup.
schema:
type: object
properties:
algorithm:
type: string
description: The algorithm used for storing backups.
enum: ["m.megolm_backup.v1.curve25519-aes-sha2"]
example: "m.megolm_backup.v1.curve25519-aes-sha2"
auth_data:
description: |-
Algorithm-dependent data. See the documentation for the backup
algorithms in `Server-side key backups`_ for more information on the
expected format of the data.
type: object
example: {
"public_key": "abcdefg",
"signatures": {
"@alice:example.org": {
"ed25519:deviceid": "signature"
}
}
}
count:
description: The number of keys stored in the backup.
type: integer
example: 42
etag:
description: |-
An opaque string representing stored keys in the backup.
Clients can compare it with the ``etag`` value they received
in the request of their last key storage request. If not
equal, another client has modified the backup.
type: string
example: "anopaquestring"
version:
type: string
description: The backup version
example: "1"
required:
- algorithm
- auth_data
- count
- etag
- version
404:
description:
No backup exists.
examples:
application/json: {
"errcode": "M_NOT_FOUND",
"error": "No current backup version"
}
schema:
"$ref": "definitions/errors/error.yaml"
429:
description: This request was rate-limited.
schema:
"$ref": "definitions/errors/rate_limited.yaml"
tags:
- End-to-end encryption
"/room_keys/version/{version}":
get:
summary: Get information about an existing backup.
description: |-
Get information about an existing backup.
operationId: getRoomKeysVersion
security:
- accessToken: []
parameters:
- in: path
type: string
name: version
description: |-
The backup version to get, as returned in the ``version`` parameter
of the response in `POST /_matrix/client/r0/room_keys/version`_ or
this endpoint.
required: true
x-example: "1"
responses:
200:
description:
The information about the requested backup.
schema:
type: object
properties:
algorithm:
type: string
description: The algorithm used for storing backups.
enum: ["m.megolm_backup.v1.curve25519-aes-sha2"]
example: "m.megolm_backup.v1.curve25519-aes-sha2"
auth_data:
description: |-
Algorithm-dependent data. See the documentation for the backup
algorithms in `Server-side key backups`_ for more information on the
expected format of the data.
type: object
example: {
"public_key": "abcdefg",
"signatures": {
"@alice:example.org": {
"ed25519:deviceid": "signature"
}
}
}
count:
description: The number of keys stored in the backup.
type: integer
example: 42
etag:
description: |-
An opaque string representing stored keys in the backup.
Clients can compare it with the ``etag`` value they received
in the request of their last key storage request. If not
equal, another client has modified the backup.
type: string
example: "anopaquestring"
version:
type: string
description: The backup version
example: "1"
required:
- algorithm
- auth_data
- count
- etag
- version
404:
description:
The backup specified does not exist.
examples:
application/json: {
"errcode": "M_NOT_FOUND",
"error": "Unknown backup version"
}
schema:
"$ref": "definitions/errors/error.yaml"
429:
description: This request was rate-limited.
schema:
"$ref": "definitions/errors/rate_limited.yaml"
tags:
- End-to-end encryption
put:
summary: Update information about an existing backup.
description: |-
Update information about an existing backup. Only ``auth_data`` can be modified.
operationId: putRoomKeysVersion
security:
- accessToken: []
parameters:
- in: path
type: string
name: version
description: |-
The backup version to update, as returned in the ``version``
parameter in the response of `POST
/_matrix/client/r0/room_keys/version`_ or `GET
/_matrix/client/r0/room_keys/version/{version}`_.
required: true
x-example: "1"
- in: body
name: version
description: "The backup configuration"
schema:
type: object
properties:
algorithm:
description: |-
The algorithm used for storing backups. Must be the same as
the algorithm currently used by the backup.
type: string
enum: ["m.megolm_backup.v1.curve25519-aes-sha2"]
example: "m.megolm_backup.v1.curve25519-aes-sha2"
auth_data:
description: |-
Algorithm-dependent data. See the documentation for the backup
algorithms in `Server-side key backups`_ for more information on the
expected format of the data.
type: object
example: {
"public_key": "abcdefg",
"signatures": {
"@alice:example.org": {
"ed25519:deviceid": "signature"
}
}
}
version:
description: |-
The backup version. If present, must be the same as the
version in the path parameter.
type: string
example: "1"
required:
- algorithm
- auth_data
responses:
200:
description: The update succeeded.
schema:
type: object
properties: {}
400:
description: |-
A parameter was incorrect. For example, the ``algorithm`` does not
match the current backup algorithm, or the ``version`` in the body
does not match the ``version`` in the path.
examples:
application/json: {
"errcode": "M_INVALID_PARAM",
"error": "Algorithm does not match"
}
schema:
"$ref": "definitions/errors/error.yaml"
404:
description: The backup specified does not exist.
examples:
application/json: {
"errcode": "M_NOT_FOUND",
"error": "Unknown backup version"
}
schema:
"$ref": "definitions/errors/error.yaml"
429:
description: This request was rate-limited.
schema:
"$ref": "definitions/errors/rate_limited.yaml"
tags:
- End-to-end encryption
delete:
summary: Delete an existing key backup.
description: |-
Delete an existing key backup. Both the information about the backup,
as well as all key data related to the backup will be deleted.
operationId: deleteRoomKeysVersion
security:
- accessToken: []
parameters:
- in: path
type: string
name: version
description: |-
The backup version to delete, as returned in the ``version``
parameter in the response of `POST
/_matrix/client/r0/room_keys/version`_ or `GET
/_matrix/client/r0/room_keys/version/{version}`_.
required: true
x-example: "1"
responses:
200:
description: |-
The delete succeeded, or the specified backup was previously
deleted.
schema:
type: object
properties: {}
404:
description: |-
The backup specified does not exist. If the backup was previously
deleted, the call should succeed rather than returning an error.
examples:
application/json: {
"errcode": "M_NOT_FOUND",
"error": "Unknown backup version"
}
schema:
"$ref": "definitions/errors/error.yaml"
429:
description: This request was rate-limited.
schema:
"$ref": "definitions/errors/rate_limited.yaml"
tags:
- End-to-end encryption
"/room_keys/keys/{roomId}/{sessionId}":
put:
summary: Store a key in the backup.
description: |-
Store a key in the backup.
operationId: postRoomKeysKeyRoomIdSessionId
security:
- accessToken: []
parameters:
- in: query
type: string
name: version
description: |-
The backup in which to store the key. Must be the current backup.
required: true
x-example: "1"
- in: path
type: string
name: roomId
description: The ID of the room that the key is for.
required: true
x-example: "!roomid:example.org"
- in: path
type: string
name: sessionId
description: The ID of the megolm session that the key is for.
required: true
x-example: "sessionid"
- in: body
name: data
description: "The key data."
schema:
"$ref": "definitions/key_backup_data.yaml"
responses:
200:
description: The update succeeded.
schema:
type: object
properties:
etag:
description: |-
The new etag value representing stored keys in the backup.
See ``GET /room_keys/version/{version}`` for more details.
type: string
example: "abcdefg"
count:
description: The number of keys stored in the backup
type: integer
example: 10
required:
- etag
- count
403:
description: |-
The version specified does not match the current backup version.
The current version will be included in the ``current_version``
field.
examples:
application/json: {
"errcode": "M_WRONG_ROOM_KEYS_VERSION",
"error": "Wrong backup version.",
"current_version": "42"
}
schema:
"$ref": "definitions/errors/error.yaml"
429:
description: This request was rate-limited.
schema:
"$ref": "definitions/errors/rate_limited.yaml"
tags:
- End-to-end encryption
get:
summary: Retrieve a key from the backup
description: |-
Retrieve a key from the backup.
operationId: getRoomKeysKeyRoomIdSessionId
security:
- accessToken: []
parameters:
- in: query
type: string
name: version
description: |-
The backup from which to retrieve the key
required: true
x-example: "1"
- in: path
type: string
name: roomId
description: The ID of the room that the requested key is for.
required: true
x-example: "!roomid:example.org"
- in: path
type: string
name: sessionId
description: The ID of the megolm session whose key is requested.
required: true
x-example: "sessionid"
responses:
200:
description: The key data
schema:
"$ref": "definitions/key_backup_data.yaml"
404:
description: The key or backup was not found.
examples:
application/json: {
"errcode": "M_NOT_FOUND",
"error": "Key not found."
}
schema:
"$ref": "definitions/errors/error.yaml"
429:
description: This request was rate-limited.
schema:
"$ref": "definitions/errors/rate_limited.yaml"
delete:
summary: Delete a key from the backup
description: |-
Delete a key from the backup.
operationId: deleteRoomKeysKeyRoomIdSessionId
security:
- accessToken: []
parameters:
- in: query
type: string
name: version
description: |-
The backup from which to delete the key
required: true
x-example: "1"
- in: path
type: string
name: roomId
description: The ID of the room that the specified key is for.
required: true
x-example: "!roomid:example.org"
- in: path
type: string
name: sessionId
description: The ID of the megolm session whose key is to be deleted.
required: true
x-example: "sessionid"
responses:
200:
description: The update succeeded
schema:
type: object
properties:
etag:
description: |-
The new etag value representing stored keys in the backup.
See ``GET /room_keys/version/{version}`` for more details.
type: string
example: "abcdefg"
count:
description: The number of keys stored in the backup
type: integer
example: 10
required:
- etag
- count
404:
description: |-
The backup was not found.
examples:
application/json: {
"errcode": "M_NOT_FOUND",
"error": "Unknown backup version"
}
schema:
"$ref": "definitions/errors/error.yaml"
429:
description: This request was rate-limited.
schema:
"$ref": "definitions/errors/rate_limited.yaml"
"/room_keys/keys/{roomId}":
put:
summary: Store several keys in the backup for a given room.
description: |-
Store a key in the backup.
operationId: postRoomKeysKeyRoomId
security:
- accessToken: []
parameters:
- in: query
type: string
name: version
description: |-
The backup in which to store the keys. Must be the current backup.
required: true
x-example: "1"
- in: path
type: string
name: roomId
description: The ID of the room that the keys are for.
required: true
x-example: "!roomid:example.org"
- in: body
description: "The backup data"
name: backupData
schema:
type: object
properties:
sessions:
type: object
description: |-
A map of session IDs to key data.
additionalProperties:
allOf:
- $ref: "definitions/key_backup_data.yaml"
example: {
"sessionid1": {
"ephemeral": "base64+ephemeral+key",
"ciphertext": "base64+ciphertext+of+JSON+data",
"mac": "base64+mac+of+ciphertext"
}
}
responses:
200:
description: The update succeeded
schema:
type: object
properties:
etag:
description: |-
The new etag value representing stored keys in the backup.
See ``GET /room_keys/version/{version}`` for more details.
type: string
example: "abcdefg"
count:
description: The number of keys stored in the backup
type: integer
example: 10
required:
- etag
- count
403:
description: |-
The version specified does not match the current backup version.
The current version will be included in the ``current_version``
field.
examples:
application/json: {
"errcode": "M_WRONG_ROOM_KEYS_VERSION",
"error": "Wrong backup version.",
"current_version": "42"
}
schema:
"$ref": "definitions/errors/error.yaml"
404:
description: |-
The backup was not found.
examples:
application/json: {
"errcode": "M_NOT_FOUND",
"error": "Unknown backup version"
}
schema:
"$ref": "definitions/errors/error.yaml"
429:
description: This request was rate-limited.
schema:
"$ref": "definitions/errors/rate_limited.yaml"
tags:
- End-to-end encryption
get:
summary: Retrieve the keys from the backup for a given room
description: |-
Retrieve the keys from the backup for a given room
operationId: getRoomKeysKeyRoomId
security:
- accessToken: []
parameters:
- in: query
type: string
name: version
description: |-
The backup from which to retrieve the key
required: true
x-example: "1"
- in: path
type: string
name: roomId
description: The ID of the room that the requested key is for.
required: true
x-example: "!roomid:example.org"
responses:
200:
description: |-
The key data. If no keys are found, then an object with an empty
``sessions`` property will be returned (``{"sessions": {}}``).
schema:
type: object
properties:
sessions:
type: object
description: |-
A map of session IDs to key data.
additionalProperties:
allOf:
- $ref: "definitions/key_backup_data.yaml"
example: {
"sessionid1": {
"ephemeral": "base64+ephemeral+key",
"ciphertext": "base64+ciphertext+of+JSON+data",
"mac": "base64+mac+of+ciphertext"
}
}
404:
description: |-
The backup was not found.
examples:
application/json: {
"errcode": "M_NOT_FOUND",
"error": "Unknown backup version"
}
schema:
"$ref": "definitions/errors/error.yaml"
429:
description: This request was rate-limited.
schema:
"$ref": "definitions/errors/rate_limited.yaml"
delete:
summary: Delete a key from the backup
description: |-
Delete a key from the backup.
operationId: deleteRoomKeysKeyRoomId
security:
- accessToken: []
parameters:
- in: query
type: string
name: version
description: |-
The backup from which to delete the key
required: true
x-example: "1"
- in: path
type: string
name: roomId
description: The ID of the room that the specified key is for.
required: true
x-example: "!roomid:example.org"
responses:
200:
description: The update succeeded
schema:
type: object
properties:
etag:
description: |-
The new etag value representing stored keys in the backup.
See ``GET /room_keys/version/{version}`` for more details.
type: string
example: "abcdefg"
count:
description: The number of keys stored in the backup
type: integer
example: 10
required:
- etag
- count
404:
description: |-
The backup was not found.
examples:
application/json: {
"errcode": "M_NOT_FOUND",
"error": "Unknown backup version"
}
schema:
"$ref": "definitions/errors/error.yaml"
429:
description: This request was rate-limited.
schema:
"$ref": "definitions/errors/rate_limited.yaml"
"/room_keys/keys":
put:
summary: Store several keys in the backup.
description: |-
Store several keys in the backup.
operationId: postRoomKeysKey
security:
- accessToken: []
parameters:
- in: query
type: string
name: version
description: |-
The backup in which to store the keys. Must be the current backup.
required: true
x-example: "1"
- in: body
description: "The backup data"
name: backupData
schema:
type: object
properties:
rooms:
type: object
description: |-
A map of room IDs to session IDs to key data.
additionalProperties:
type: object
additionalProperties:
allOf:
- $ref: "definitions/key_backup_data.yaml"
example: {
"!room:example.org": {
"sessions": {
"sessionid1": {
"ephemeral": "base64+ephemeral+key",
"ciphertext": "base64+ciphertext+of+JSON+data",
"mac": "base64+mac+of+ciphertext"
}
}
}
}
responses:
200:
description: The update succeeded
schema:
type: object
properties:
etag:
description: |-
The new etag value representing stored keys in the backup.
See ``GET /room_keys/version/{version}`` for more details.
type: string
example: "abcdefg"
count:
description: The number of keys stored in the backup
type: integer
example: 10
required:
- etag
- count
403:
description: |-
The version specified does not match the current backup version.
The current version will be included in the ``current_version``
field.
examples:
application/json: {
"errcode": "M_WRONG_ROOM_KEYS_VERSION",
"error": "Wrong backup version.",
"current_version": "42"
}
schema:
"$ref": "definitions/errors/error.yaml"
404:
description: |-
The backup was not found.
examples:
application/json: {
"errcode": "M_NOT_FOUND",
"error": "Unknown backup version"
}
schema:
"$ref": "definitions/errors/error.yaml"
429:
description: This request was rate-limited.
schema:
"$ref": "definitions/errors/rate_limited.yaml"
tags:
- End-to-end encryption
get:
summary: Retrieve the keys from the backup for a given room
description: |-
Retrieve the keys from the backup for a given room
operationId: getRoomKeysKeyRoomId
security:
- accessToken: []
parameters:
- in: query
type: string
name: version
description: |-
The backup from which to retrieve the keys. If omitted, the keys are
retrieved from the current backup.
x-example: "1"
responses:
200:
description: |-
The key data. If no keys are found, then an object with an empty
``rooms`` property will be returned (``{"rooms": {}}``).
schema:
type: object
properties:
rooms:
type: object
description: |-
A map of room IDs to session IDs to key data.
additionalProperties:
type: object
additionalProperties:
allOf:
- $ref: "definitions/key_backup_data.yaml"
example: {
"!room:example.org": {
"sessions": {
"sessionid1": {
"ephemeral": "base64+ephemeral+key",
"ciphertext": "base64+ciphertext+of+JSON+data",
"mac": "base64+mac+of+ciphertext"
}
}
}
}
404:
description: The backup was not found.
examples:
application/json: {
"errcode": "M_NOT_FOUND",
"error": "Unknown backup version."
}
schema:
"$ref": "definitions/errors/error.yaml"
429:
description: This request was rate-limited.
schema:
"$ref": "definitions/errors/rate_limited.yaml"
delete:
summary: Delete a key from the backup
description: |-
Delete a key from the backup.
operationId: deleteRoomKeysKeyRoomId
security:
- accessToken: []
parameters:
- in: query
type: string
name: version
description: |-
The backup from which to delete the key
required: true
x-example: "1"
responses:
200:
description: The update succeeded
schema:
type: object
properties:
etag:
description: |-
The new etag value representing stored keys in the backup.
See ``GET /room_keys/version/{version}`` for more details.
type: string
example: "abcdefg"
count:
description: The number of keys stored in the backup
type: integer
example: 10
required:
- etag
- count
404:
description: |-
The backup was not found.
examples:
application/json: {
"errcode": "M_NOT_FOUND",
"error": "Unknown backup version"
}
schema:
"$ref": "definitions/errors/error.yaml"
429:
description: This request was rate-limited.
schema:
"$ref": "definitions/errors/rate_limited.yaml"

@ -0,0 +1 @@
Add key backup (``/room_keys/*``) endpoints.

@ -781,6 +781,136 @@ previously-received ``request`` message with the same ``request_id`` and
A reasonable strategy is for a user's client to only send keys requested by the
verified devices of the same user.
Server-side key backups
~~~~~~~~~~~~~~~~~~~~~~~
Devices may upload encrypted copies of keys to the server. When a device tries
to read a message that it does not have keys for, it may request the key from
the server and decrypt it. Backups are per-user, and users may replace backups
with new backups.
In contrast with `Key requests`_, Server-side key backups do not require another
device to be online from which to request keys. However, as the session keys are
stored on the server encrypted, it requires users to enter a decryption key to
decrypt the session keys.
To create a backup, a client will call `POST
/_matrix/client/r0/room_keys/version`_ and define how the keys are to be
encrypted through the backup's ``auth_data``; other clients can discover the
backup by calling `GET /_matrix/client/r0/room_keys/version`_. Keys are
encrypted according to the backup's ``auth_data`` and added to the backup by
calling `PUT /_matrix/client/r0/room_keys/keys`_ or one of its variants, and
can be retrieved by calling `GET /_matrix/client/r0/room_keys/keys`_ or one of
its variants. Keys can only be written to the most recently created version of
the backup. Backups can also be deleted using `DELETE
/_matrix/client/r0/room_keys/version/{version}`_, or individual keys can be
deleted using `DELETE /_matrix/client/r0/room_keys/keys`_ or one of its
variants.
Clients must only store keys in backups after they have ensured that the
``auth_data`` is trusted, either by checking the signatures on it, or by
deriving the public key from a private key that it obtained from a trusted
source.
When a client uploads a key for a session that the server already has a key
for, the server will choose to either keep the existing key or replace it with
the new key based on the key metadata as follows:
- if the keys have different values for ``is_verified``, then it will keep the
key that has ``is_verified`` set to ``true``;
- if they have the same values for ``is_verified``, then it will keep the key
with a lower ``first_message_index``;
- and finally, is ``is_verified`` and ``first_message_index`` are equal, then
it will keep the key with a lower ``forwarded_count``.
Recovery key
<<<<<<<<<<<<
If the recovery key (the private half of the backup encryption key) is
presented to the user to save, it is presented as a string constructed as
follows:
1. The 256-bit curve25519 private key is prepended by the bytes ``0x8B`` and
``0x01``
2. All the bytes in the string above, including the two header bytes, are XORed
together to form a parity byte. This parity byte is appended to the byte
string.
3. The byte string is encoded using base58, using the same `mapping as is used
for Bitcoin addresses
<https://en.bitcoin.it/wiki/Base58Check_encoding#Base58_symbol_chart>`_,
that is, using the alphabet
``123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz``.
4. A space should be added after every 4th character.
When reading in a recovery key, clients must disregard whitespace, and perform
the reverse of steps 1 through 3.
Backup algorithm: ``m.megolm_backup.v1.curve25519-aes-sha2``
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
When a backup is created with the ``algorithm`` set to
``m.megolm_backup.v1.curve25519-aes-sha2``, the ``auth_data`` should have the
following format:
``AuthData``
.. table::
:widths: auto
========== =========== ======================================================
Parameter Type Description
========== =========== ======================================================
public_key string **Required.** The curve25519 public key used to encrypt
the backups, encoded in unpadded base64.
signatures Signatures Optional. Signatures of the ``auth_data``, as Signed
JSON
========== =========== ======================================================
The ``session_data`` field in the backups is constructed as follows:
1. Encode the session key to be backed up as a JSON object with the properties:
.. table::
:widths: auto
=============================== ======== =========================================
Parameter Type Description
=============================== ======== =========================================
algorithm string **Required.** The end-to-end message
encryption algorithm that the key is
for. Must be ``m.megolm.v1.aes-sha2``.
forwarding_curve25519_key_chain [string] **Required.** Chain of Curve25519 keys
through which this session was
forwarded, via
`m.forwarded_room_key`_ events.
sender_key string **Required.** Unpadded base64-encoded
device curve25519 key.
sender_claimed_keys {string: **Required.** A map from algorithm name
string} (``ed25519``) to the identity key
for the sending device.
session_key string **Required.** Unpadded base64-encoded
session key in `session-sharing format
<https://gitlab.matrix.org/matrix-org/olm/blob/master/docs/megolm.md#session-sharing-format>`_.
=============================== ======== =========================================
2. Generate an ephemeral curve25519 key, and perform an ECDH with the ephemeral
key and the backup's public key to generate a shared secret. The public
half of the ephemeral key, encoded using unpadded base64, becomes the ``ephemeral``
property of the ``session_data``.
3. Using the shared secret, generate 80 bytes by performing an HKDF using
SHA-256 as the hash, with a salt of 32 bytes of 0, and with the empty string
as the info. The first 32 bytes are used as the AES key, the next 32 bytes
are used as the MAC key, and the last 16 bytes are used as the AES
initialization vector.
4. Stringify the JSON object, and encrypt it using AES-CBC-256 with PKCS#7
padding. This encrypted data, encoded using unpadded base64, becomes the
``ciphertext`` property of the ``session_data``.
5. Pass the raw encrypted data (prior to base64 encoding) through HMAC-SHA-256
using the MAC key generated above. The first 8 bytes of the resulting MAC
are base64-encoded, and become the ``mac`` property of the ``session_data``.
{{key_backup_cs_http_api}}
Key exports
~~~~~~~~~~~
@ -854,6 +984,9 @@ described as follows:
session_key string Required. The key for the session.
=============================== =========== ====================================
This is similar to the format before encryption used for the session keys in
`Server-side key backups`_ but adds the ``room_id`` and ``session_id`` fields.
Example:
.. code:: json

Loading…
Cancel
Save