Skip to content

Commit

Permalink
Improve the server key exchange portion of the s2s specification
Browse files Browse the repository at this point in the history
Most of the text has been shuffled into the swagger definitions to bring it closer to where it matters.

This also attempts to clarify what is out in the wild. Most importantly, the first version of the key exchange is outright removed from the specification. Other research points/questions are:

* What is a "Key ID"?
  * https://github.com/matrix-org/synapse/blob/1241156c82644d5609f45659607a356af5d8fe08/synapse/rest/key/v2/local_key_resource.py#L81-L83
  * https://github.com/matrix-org/synapse/blob/1241156c82644d5609f45659607a356af5d8fe08/synapse/rest/key/v2/local_key_resource.py#L88-L91
* Returning a cached response if the server throws a 400, 500, or otherwise not-offline status code
  * https://github.com/matrix-org/synapse/blob/1241156c82644d5609f45659607a356af5d8fe08/synapse/rest/key/v2/remote_key_resource.py#L227-L229
* `minimum_valid_until_ts` default
  * This branch of the ladder: https://github.com/matrix-org/synapse/blob/1241156c82644d5609f45659607a356af5d8fe08/synapse/rest/key/v2/remote_key_resource.py#L192
* Returning empty arrays when querying offline/no servers
  * Queried by hand against matrix.org as a notary server with a fake domain name to query
* Returning all keys even when querying for specific keys
  * Queried by hand using matrix.org as a notary server against a server publishing multiple keys.

The examples and descriptions were also improved as part of this commit.
  • Loading branch information
turt2live committed Jul 26, 2018
1 parent b0744aa commit 8e97b0c
Show file tree
Hide file tree
Showing 7 changed files with 144 additions and 150 deletions.
46 changes: 29 additions & 17 deletions api/server-server/definitions/keys.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,50 +20,60 @@ 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.
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.
additionalProperties:
type: object
title: Old Verify Key
example: {
"ed25519:auto1": {
"ed25519:0ldK3y": {
"expired_ts": 922834800000,
"key": "Base+64+Encoded+Signature+Verification+Key"
"key": "VGhpcyBzaG91bGQgYmUgeW91ciBvbGQga2V5J3MgZWQyNTUxOSBwYXlsb2FkLg=="
}
}
properties:
expired_ts:
type: integer
format: int64
description: The expiration time.
description: POSIX timestamp for when this key expired.
required: true
example: 922834800000
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``.
Expand All @@ -72,7 +82,7 @@ properties:
title: Signed Server
example: {
"example.org": {
"ad25519:auto2": "Base+64+Encoded+Signature+Verification+Key"
"ad25519:abc123": "VGhpcyBzaG91bGQgYWN0dWFsbHkgYmUgYSBzaWduYXR1cmU="
}
}
additionalProperties:
Expand All @@ -87,10 +97,12 @@ properties:
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
4 changes: 2 additions & 2 deletions api/server-server/definitions/keys_query_response.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
12 changes: 6 additions & 6 deletions api/server-server/examples/server_key.json
Original file line number Diff line number Diff line change
@@ -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": {
"ed25519:0ldk3y": {
"expired_ts": 922834800000,
"key": "Base+64+Encoded+Old+Verify+Key"
"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
}
11 changes: 11 additions & 0 deletions api/server-server/examples/server_key_notary_signed.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"$ref": "server_key.json",
"signatures": {
"example.org": {
"ed25519:abc123": "VGhpcyBzaG91bGQgYWN0dWFsbHkgYmUgYSBzaWduYXR1cmU="
},
"notary.server.com": {
"ed25519:010203": "VGhpcyBpcyBhbm90aGVyIHNpZ25hdHVyZQ=="
}
}
}
69 changes: 49 additions & 20 deletions api/server-server/keys_query.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,49 +25,60 @@ produces:
paths:
"/query/{serverName}/{keyId}":
get:
summary: Retrieve a server key.
description: Retrieve a server key.
operationId: perspectivesKeyQuery
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: getQueryKeys
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: |-
The key ID to look up. If omitted or empty, all the server's keys
are to be queried for.
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 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.
operationId: bulkPerspectivesKeyQuery
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: postQueryKeys
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
}
}
Expand All @@ -76,24 +87,42 @@ 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
description: The server names to query.
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 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"
30 changes: 25 additions & 5 deletions api/server-server/keys_server.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,38 @@ 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. Homeservers SHOULD return a single JSON object
listing all of its keys, regardless of the ``keyId`` path argument.
This is to reduce the number of round trips needed to discover the
relevant keys for a homeserver.
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: |-
The key ID to look up. If omitted or empty, all server keys are
to be returned.
required: false
x-example: TODO # No examples in the spec so far
x-example: "ed25519:abc123"
responses:
200:
description: The server's keys.
description: The homeserver's keys
schema:
$ref: "definitions/keys.yaml"
Loading

0 comments on commit 8e97b0c

Please sign in to comment.