Merge pull request #1423 from turt2live/travis/s2s/keys
Improve the server key exchange portion of the s2s specification
This commit is contained in:
commit
b96ee3e393
7 changed files with 148 additions and 152 deletions
|
@ -20,50 +20,62 @@ properties:
|
|||
server_name:
|
||||
type: string
|
||||
description: DNS name of the homeserver.
|
||||
required: true # TODO: Verify
|
||||
required: true
|
||||
example: "example.org"
|
||||
verify_keys:
|
||||
type: object
|
||||
description: Public keys of the homeserver for verifying digital signatures.
|
||||
required: true # TODO: Verify
|
||||
description: |-
|
||||
Public keys of the homeserver for verifying digital signatures.
|
||||
|
||||
The object's key is the algorithm and version combined (``ed25519`` being the
|
||||
algorithm and ``abc123`` being the version in the example below). Together,
|
||||
this forms the Key ID. The version must have characters matching the regular
|
||||
expression ``[a-zA-Z0-9_]``.
|
||||
required: true
|
||||
additionalProperties:
|
||||
type: object
|
||||
title: Verify Key
|
||||
example: {
|
||||
"ed25519:auto2": {
|
||||
"key": "Base+64+Encoded+Signature+Verification+Key"
|
||||
"ed25519:abc123": {
|
||||
"key": "VGhpcyBzaG91bGQgYmUgYSByZWFsIGVkMjU1MTkgcGF5bG9hZA"
|
||||
}
|
||||
}
|
||||
properties:
|
||||
key:
|
||||
type: string
|
||||
description: The key
|
||||
description: The `Unpadded Base64`_ encoded key.
|
||||
required: true
|
||||
example: "Base+64+Encoded+Signature+Verification+Key"
|
||||
example: "VGhpcyBzaG91bGQgYmUgYSByZWFsIGVkMjU1MTkgcGF5bG9hZA"
|
||||
old_verify_keys:
|
||||
type: object
|
||||
description: The public keys that the server used to use and when it stopped using them.
|
||||
description: |-
|
||||
The public keys that the server used to use and when it stopped using them.
|
||||
|
||||
The object's key is the algorithm and version combined (``ed25519`` being the
|
||||
algorithm and ``0ldK3y`` being the version in the example below). Together,
|
||||
this forms the Key ID. The version must have characters matching the regular
|
||||
expression ``[a-zA-Z0-9_]``.
|
||||
additionalProperties:
|
||||
type: object
|
||||
title: Old Verify Key
|
||||
example: {
|
||||
"ed25519:auto1": {
|
||||
"expired_ts": 922834800000,
|
||||
"key": "Base+64+Encoded+Signature+Verification+Key"
|
||||
"ed25519:0ldK3y": {
|
||||
"expired_ts": 1532645052628,
|
||||
"key": "VGhpcyBzaG91bGQgYmUgeW91ciBvbGQga2V5J3MgZWQyNTUxOSBwYXlsb2FkLg"
|
||||
}
|
||||
}
|
||||
properties:
|
||||
expired_ts:
|
||||
type: integer
|
||||
format: int64
|
||||
description: The expiration time.
|
||||
description: POSIX timestamp in milliseconds for when this key expired.
|
||||
required: true
|
||||
example: 922834800000
|
||||
example: 1532645052628
|
||||
key:
|
||||
type: string
|
||||
description: The key.
|
||||
description: The `Unpadded Base64`_ encoded key.
|
||||
required: true
|
||||
example: "Base+64+Encoded+Signature+Verification+Key"
|
||||
example: "VGhpcyBzaG91bGQgYmUgeW91ciBvbGQga2V5J3MgZWQyNTUxOSBwYXlsb2FkLg"
|
||||
signatures:
|
||||
type: object
|
||||
description: Digital signatures for this object signed using the ``verify_keys``.
|
||||
|
@ -72,7 +84,7 @@ properties:
|
|||
title: Signed Server
|
||||
example: {
|
||||
"example.org": {
|
||||
"ad25519:auto2": "Base+64+Encoded+Signature+Verification+Key"
|
||||
"ad25519:abc123": "VGhpcyBzaG91bGQgYWN0dWFsbHkgYmUgYSBzaWduYXR1cmU"
|
||||
}
|
||||
}
|
||||
additionalProperties:
|
||||
|
@ -80,17 +92,19 @@ properties:
|
|||
name: Encoded Signature Verification Key
|
||||
tls_fingerprints:
|
||||
type: array
|
||||
description: Hashes of X.509 TLS certificates used by this server encoded as `Unpadded Base64`_.
|
||||
description: Hashes of X.509 TLS certificates used by this server.
|
||||
items:
|
||||
type: object
|
||||
title: TLS Fingerprint
|
||||
properties:
|
||||
sha256:
|
||||
type: string
|
||||
description: The encoded fingerprint.
|
||||
example: Base+64+Encoded+SHA-256-Fingerprint
|
||||
description: The `Unpadded Base64`_ encoded fingerprint.
|
||||
example: "VGhpcyBpcyBoYXNoIHdoaWNoIHNob3VsZCBiZSBieXRlcw"
|
||||
valid_until_ts:
|
||||
type: integer
|
||||
format: int64
|
||||
description: POSIX timestamp when the list of valid keys should be refreshed.
|
||||
description: |-
|
||||
POSIX timestamp when the list of valid keys should be refreshed. Keys used beyond this
|
||||
timestamp are no longer valid.
|
||||
example: 1052262000000
|
||||
|
|
|
@ -15,13 +15,13 @@ type: object
|
|||
description: Server keys
|
||||
example: {
|
||||
"server_keys": [{
|
||||
$ref: "../examples/server_key.json"
|
||||
$ref: "../examples/server_key_notary_signed.json"
|
||||
}]
|
||||
}
|
||||
properties:
|
||||
server_keys:
|
||||
type: array
|
||||
title: Server Keys
|
||||
description: The server keys.
|
||||
description: The queried server's keys, signed by the notary server.
|
||||
items:
|
||||
$ref: "keys.yaml"
|
||||
|
|
|
@ -1,23 +1,23 @@
|
|||
{
|
||||
"server_name": "example.org",
|
||||
"verify_keys": {
|
||||
"ed25519:auto2": {
|
||||
"key": "Base+64+Encoded+Signature+Verification+Key"
|
||||
"ed25519:abc123": {
|
||||
"key": "VGhpcyBzaG91bGQgYmUgYSByZWFsIGVkMjU1MTkgcGF5bG9hZA"
|
||||
}
|
||||
},
|
||||
"old_verify_keys": {
|
||||
"ed25519:auto1": {
|
||||
"expired_ts": 922834800000,
|
||||
"key": "Base+64+Encoded+Old+Verify+Key"
|
||||
"ed25519:0ldk3y": {
|
||||
"expired_ts": 1532645052628,
|
||||
"key": "VGhpcyBzaG91bGQgYmUgeW91ciBvbGQga2V5J3MgZWQyNTUxOSBwYXlsb2FkLg"
|
||||
}
|
||||
},
|
||||
"signatures": {
|
||||
"example.org": {
|
||||
"ed25519:auto2": "Base+64+Encoded+Signature"
|
||||
"ed25519:auto2": "VGhpcyBzaG91bGQgYWN0dWFsbHkgYmUgYSBzaWduYXR1cmU"
|
||||
}
|
||||
},
|
||||
"tls_fingerprints": [{
|
||||
"sha256": "Base+64+Encoded+SHA-256-Fingerprint"
|
||||
"sha256": "VGhpcyBpcyBoYXNoIHdoaWNoIHNob3VsZCBiZSBieXRlcw"
|
||||
}],
|
||||
"valid_until_ts": 1052262000000
|
||||
"valid_until_ts": 1652262000000
|
||||
}
|
11
api/server-server/examples/server_key_notary_signed.json
Normal file
11
api/server-server/examples/server_key_notary_signed.json
Normal file
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"$ref": "server_key.json",
|
||||
"signatures": {
|
||||
"example.org": {
|
||||
"ed25519:abc123": "VGhpcyBzaG91bGQgYWN0dWFsbHkgYmUgYSBzaWduYXR1cmU"
|
||||
},
|
||||
"notary.server.com": {
|
||||
"ed25519:010203": "VGhpcyBpcyBhbm90aGVyIHNpZ25hdHVyZQ"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -25,49 +25,61 @@ produces:
|
|||
paths:
|
||||
"/query/{serverName}/{keyId}":
|
||||
get:
|
||||
summary: Retrieve a server key.
|
||||
description: Retrieve a server key.
|
||||
summary: Query for another server's keys
|
||||
description: |-
|
||||
Query for another server's keys. The receiving (notary) server must
|
||||
sign the keys returned by the queried server.
|
||||
operationId: perspectivesKeyQuery
|
||||
parameters:
|
||||
- in: path
|
||||
name: serverName
|
||||
type: string
|
||||
description: Server name.
|
||||
description: The server's DNS name to query
|
||||
required: true
|
||||
x-example: matrix.org
|
||||
- in: path
|
||||
name: keyId
|
||||
type: string
|
||||
description: Key ID.
|
||||
required: true
|
||||
x-example: TODO # No examples in spec so far
|
||||
description: |-
|
||||
**Deprecated**. Servers should not use this parameter and instead
|
||||
opt to return all keys, not just the requested one. The key ID to
|
||||
look up.
|
||||
required: false
|
||||
x-example: "ed25519:abc123"
|
||||
- in: query
|
||||
name: minimum_valid_until_ts
|
||||
type: integer
|
||||
format: int64
|
||||
description: Minimum Valid Until Milliseconds.
|
||||
required: true # TODO: Verify
|
||||
description: |-
|
||||
A millisecond POSIX timestamp in milliseconds indicating when the returned
|
||||
certificates will need to be valid until to be useful to the requesting server.
|
||||
|
||||
If not supplied, the current time as determined by the notary server is used.
|
||||
required: false
|
||||
x-example: 1234567890
|
||||
responses:
|
||||
200:
|
||||
description: The keys for the server
|
||||
description: |-
|
||||
The keys for the server, or an empty array if the server could not be reached
|
||||
and no cached keys were available.
|
||||
schema:
|
||||
$ref: "definitions/keys_query_response.yaml"
|
||||
"/query":
|
||||
post:
|
||||
summary: Retrieve a server key
|
||||
description: Retrieve a server key.
|
||||
summary: Query for several server's keys
|
||||
description: |-
|
||||
Query for keys from multiple servers in a batch format. The receiving (notary)
|
||||
server must sign the keys returned by the queried servers.
|
||||
operationId: bulkPerspectivesKeyQuery
|
||||
parameters:
|
||||
- in: body
|
||||
name: body
|
||||
schema:
|
||||
type: object
|
||||
# TODO: Improve example
|
||||
example: {
|
||||
"server_keys": {
|
||||
"{server_name}": {
|
||||
"{key_id}": {
|
||||
"example.org": {
|
||||
"ed25519:abc123": {
|
||||
"minimum_valid_until_ts": 1234567890
|
||||
}
|
||||
}
|
||||
|
@ -76,7 +88,16 @@ paths:
|
|||
properties:
|
||||
server_keys:
|
||||
type: object
|
||||
description: The query criteria.
|
||||
description: |-
|
||||
The query criteria. The outer ``string`` key on the object is the
|
||||
server name (eg: ``matrix.org``). The inner ``string`` key is the
|
||||
Key ID to query for the particular server. If no key IDs are given
|
||||
to be queried, the notary server should query for all keys. If no
|
||||
servers are given, the notary server must return an empty ``server_keys``
|
||||
array in the response.
|
||||
|
||||
The notary server may return multiple keys regardless of the Key IDs
|
||||
given.
|
||||
additionalProperties:
|
||||
type: object
|
||||
name: ServerName
|
||||
|
@ -84,16 +105,25 @@ paths:
|
|||
additionalProperties:
|
||||
type: object
|
||||
title: Query Criteria
|
||||
description: The server keys to query.
|
||||
description: The server key IDs to query.
|
||||
properties:
|
||||
minimum_valid_until_ts:
|
||||
type: integer
|
||||
format: int64
|
||||
description: Minimum Valid Until MS.
|
||||
description: |-
|
||||
A millisecond POSIX timestamp in milliseconds indicating when
|
||||
the returned certificates will need to be valid until to be
|
||||
useful to the requesting server.
|
||||
|
||||
If not supplied, the current time as determined by the notary
|
||||
server is used.
|
||||
example: 1234567890
|
||||
required: ['server_keys']
|
||||
responses:
|
||||
200:
|
||||
description: The keys for the server.
|
||||
description: |-
|
||||
The keys for the queried servers, signed by the notary server. Servers which
|
||||
are offline and have no cached keys will not be included in the result. This
|
||||
may result in an empty array.
|
||||
schema:
|
||||
$ref: "definitions/keys_query_response.yaml"
|
||||
|
|
|
@ -25,18 +25,37 @@ produces:
|
|||
paths:
|
||||
"/server/{keyId}":
|
||||
get:
|
||||
summary: Get the server's key
|
||||
description: Get the server's key.
|
||||
summary: Get the homeserver's public key(s)
|
||||
description: |-
|
||||
Gets the homeserver's published TLS fingerprints and signing keys.
|
||||
The homeserver may have any number of active keys and may have a
|
||||
number of old keys.
|
||||
|
||||
Intermediate notary servers should cache a response for half of its
|
||||
lifetime to avoid serving a stale response. Originating servers should
|
||||
avoid returning responses that expire in less than an hour to avoid
|
||||
repeated reqests for a certificate that is about to expire. Requesting
|
||||
servers should limit how frequently they query for certificates to
|
||||
avoid flooding a server with requests.
|
||||
|
||||
If the server fails to respond to this request, intermediate notary
|
||||
servers should continue to return the last response they received
|
||||
from the server so that the signatures of old events can still be
|
||||
checked.
|
||||
operationId: getServerKey
|
||||
parameters:
|
||||
- in: path
|
||||
name: keyId
|
||||
type: string
|
||||
description: Key ID
|
||||
description: |-
|
||||
**Deprecated**. Servers should not use this parameter and instead
|
||||
opt to return all keys, not just the requested one. The key ID to
|
||||
look up.
|
||||
required: false
|
||||
x-example: TODO # No examples in the spec so far
|
||||
x-example: "ed25519:abc123"
|
||||
deprecated: true
|
||||
responses:
|
||||
200:
|
||||
description: The server's keys.
|
||||
description: The homeserver's keys
|
||||
schema:
|
||||
$ref: "definitions/keys.yaml"
|
||||
|
|
|
@ -106,15 +106,17 @@ Server implementation
|
|||
Retrieving Server Keys
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Version 2
|
||||
+++++++++
|
||||
.. NOTE::
|
||||
There was once a "version 1" of the key exchange. It has been removed from the
|
||||
specification due to lack of significance. It may be reviewed `here
|
||||
<https://github.com/matrix-org/matrix-doc/blob/51faf8ed2e4a63d4cfd6d23183698ed169956cc0/specification/server_server_api.rst#232version-1>`_.
|
||||
|
||||
Each homeserver publishes its public keys under ``/_matrix/key/v2/server/``.
|
||||
Homeservers query for keys by either getting ``/_matrix/key/v2/server/``
|
||||
Each homeserver publishes its public keys under ``/_matrix/key/v2/server/{keyId}``.
|
||||
Homeservers query for keys by either getting ``/_matrix/key/v2/server/{keyId}``
|
||||
directly or by querying an intermediate notary server using a
|
||||
``/_matrix/key/v2/query`` API. Intermediate notary servers query the
|
||||
``/_matrix/key/v2/server/`` API on behalf of another server and sign the
|
||||
response with their own key. A server may query multiple notary servers to
|
||||
``/_matrix/key/v2/query/{serverName}/{keyId}`` API. Intermediate notary servers
|
||||
query the ``/_matrix/key/v2/server/{keyId}`` API on behalf of another server and
|
||||
sign the response with their own key. A server may query multiple notary servers to
|
||||
ensure that they all report the same public keys.
|
||||
|
||||
This approach is borrowed from the `Perspectives Project`_, but modified to
|
||||
|
@ -126,113 +128,33 @@ server by querying other servers.
|
|||
.. _Perspectives Project: https://web.archive.org/web/20170702024706/https://perspectives-project.org/
|
||||
|
||||
Publishing Keys
|
||||
^^^^^^^^^^^^^^^
|
||||
+++++++++++++++
|
||||
|
||||
Homeservers publish the allowed TLS fingerprints and signing keys in a JSON
|
||||
object at ``/_matrix/key/v2/server/{key_id}``. The response contains a list of
|
||||
``verify_keys`` that are valid for signing federation requests made by the
|
||||
server and for signing events. It contains a list of ``old_verify_keys`` which
|
||||
homeserver and for signing events. It contains a list of ``old_verify_keys`` which
|
||||
are only valid for signing events. Finally the response contains a list of TLS
|
||||
certificate fingerprints to validate any connection made to the server.
|
||||
|
||||
A server may have multiple keys active at a given time. A server may have any
|
||||
number of old keys. It is recommended that servers return a single JSON
|
||||
response listing all of its keys whenever any ``key_id`` is requested to reduce
|
||||
the number of round trips needed to discover the relevant keys for a server.
|
||||
However a server may return different responses for a different ``key_id``.
|
||||
|
||||
The ``tls_certificates`` field contains a list of hashes of the X.509 TLS
|
||||
certificates currently used by the server. The list must include SHA-256 hashes
|
||||
for every certificate currently in use by the server. These fingerprints are
|
||||
valid until the millisecond POSIX timestamp in ``valid_until_ts``.
|
||||
|
||||
The ``verify_keys`` can be used to sign requests and events made by the server
|
||||
until the millisecond POSIX timestamp in ``valid_until_ts``. If a homeserver
|
||||
receives an event with a ``origin_server_ts`` after the ``valid_until_ts`` then
|
||||
it should request that ``key_id`` for the originating server to check whether
|
||||
the key has expired.
|
||||
|
||||
The ``old_verify_keys`` can be used to sign events with an ``origin_server_ts``
|
||||
before the ``expired_ts``. The ``expired_ts`` is a millisecond POSIX timestamp
|
||||
of when the originating server stopped using that key.
|
||||
|
||||
Intermediate notary servers should cache a response for half of its remaining
|
||||
lifetime to avoid serving a stale response. Originating servers should avoid
|
||||
returning responses that expire in less than an hour to avoid repeated requests
|
||||
for a certificate that is about to expire. Requesting servers should limit how
|
||||
frequently they query for certificates to avoid flooding a server with
|
||||
requests.
|
||||
|
||||
If a server goes offline intermediate notary servers should continue to return
|
||||
the last response they received from that server so that the signatures of old
|
||||
events sent by that server can still be checked.
|
||||
certificate fingerprints to validate any connection made to the homeserver.
|
||||
|
||||
{{keys_server_ss_http_api}}
|
||||
|
||||
|
||||
Querying Keys Through Another Server
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
++++++++++++++++++++++++++++++++++++
|
||||
|
||||
Servers may offer a query API ``/_matrix/key/v2/query/`` for getting the keys
|
||||
for another server. This API can be used to GET a list of JSON objects for a
|
||||
given server or to POST a bulk query for a number of keys from a number of
|
||||
servers. Either way the response is a list of JSON objects containing the
|
||||
JSON published by the server under ``/_matrix/key/v2/server/`` signed by
|
||||
both the originating server and by this server.
|
||||
Servers may query another server's keys through a notary server. The notary
|
||||
server may be another homeserver. The notary server will retrieve keys from
|
||||
the queried servers through use of the ``/_matrix/key/v2/server/{keyId}``
|
||||
API. The notary server will additionally sign the response from the queried
|
||||
server before returning the results.
|
||||
|
||||
The ``minimum_valid_until_ts`` is a millisecond POSIX timestamp indicating
|
||||
when the returned certificate will need to be valid until to be useful to the
|
||||
requesting server. This can be set using the maximum ``origin_server_ts`` of
|
||||
a batch of events that a requesting server is trying to validate. This allows
|
||||
an intermediate notary server to give a prompt cached response even if the
|
||||
originating server is offline.
|
||||
|
||||
This API can return keys for servers that are offline by using cached responses
|
||||
taken from when the server was online. Keys can be queried from multiple
|
||||
servers to mitigate against DNS spoofing.
|
||||
Notary servers can return keys for servers that are offline or having issues
|
||||
serving their own keys by using cached responses. Keys can be queried from
|
||||
multiple servers to mitigate against DNS spoofing.
|
||||
|
||||
{{keys_query_ss_http_api}}
|
||||
|
||||
Version 1
|
||||
+++++++++
|
||||
.. WARNING::
|
||||
Version 1 of key distribution is obsolete.
|
||||
|
||||
|
||||
Homeservers publish their TLS certificates and signing keys in a JSON object
|
||||
at ``/_matrix/key/v1``.
|
||||
|
||||
==================== =================== ======================================
|
||||
Key Type Description
|
||||
==================== =================== ======================================
|
||||
``server_name`` String DNS name of the homeserver.
|
||||
``verify_keys`` Object Public keys of the homeserver for
|
||||
verifying digital signatures.
|
||||
``signatures`` Object Digital signatures for this object
|
||||
signed using the ``verify_keys``.
|
||||
``tls_certificate`` String The X.509 TLS certificate used by this
|
||||
this server encoded as `Unpadded Base64`_.
|
||||
==================== =================== ======================================
|
||||
|
||||
.. code:: json
|
||||
|
||||
{
|
||||
"server_name": "example.org",
|
||||
"signatures": {
|
||||
"example.org": {
|
||||
"ed25519:auto": "Base+64+Encoded+Signature"
|
||||
}
|
||||
},
|
||||
"tls_certificate": "Base+64+Encoded+DER+Encoded+X509+TLS+Certificate",
|
||||
"verify_keys": {
|
||||
"ed25519:auto": "Base+64+Encoded+Signature+Verification+Key"
|
||||
}
|
||||
}
|
||||
|
||||
When fetching the keys for a server the client should check that the TLS
|
||||
certificate in the JSON matches the TLS server certificate for the connection
|
||||
and should check that the JSON signatures are correct for the supplied
|
||||
``verify_keys``.
|
||||
|
||||
Transactions
|
||||
------------
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue