diff --git a/FEDERATION.md b/FEDERATION.md index 934d844..05ca9b6 100644 --- a/FEDERATION.md +++ b/FEDERATION.md @@ -105,10 +105,6 @@ contains not just the key itself, but also a code specifying the key type. The Fediverse de-facto standard is RSA, more precisely PKCS#1 v1.5, and used with the SHA-256 hash algorithm. This is often referred to as RSA-SHA256. -If the `algorithm` is specified in the Signature header, it must match the key -type in the PEM. But `algorithm` isn't required, and we should probably stop -using it. - #### (1) Actor key(s) in a separate document Allow an actor's signing key to be a separate document, rather than embedded in @@ -273,9 +269,105 @@ Requirements for authentication using a server-scope key: #### (4) Actor key expiration and revocation +Allow to improve the secure handling of signing keys by supporting expiration +and revocation. Expiration means the key specifies a time at which it stops +being valid, and once that time comes, signatures made by that key are +considered invalid. Revocation similary means the key specifies a time at which +it stops being valid. + +`GET /users/aviva/keys/key1` + +```json +{ "@context": "https://w3id.org/security/v1" +, "@id": "https://example.dev/users/aviva/keys/key1" +, "@type": "Key" +, "owner": "https://example.dev/users/aviva" +, "created": "2019-01-13T11:00:00+0000" +, "expires": "2021-01-13T11:00:00+0000" +, "publicKeyPem": "-----BEGIN PUBLIC KEY----- ..." +} +``` + +Requirement: When verifying a signature, compare `expires` and `revoked`, if +one of them or both of them are present, to the current time. If at least one +of the 2 times is the current time or earlier, then consider the signature +invalid. If using a cached version of the key, try to HTTP GET the key and try +to authenticate once more, because it's possible the key has been replaced with +a new valid one. + #### (5) Ed25519 actor keys -#### (6) Key rotation using a pair of server-scope keys +Allows actor keys to be [Ed25519](https://ed25519.cr.yp.to) keys, by allowing +the `publicKeyPem` field to simply contain a PEM encoded Ed25519 public key. +The [HTTP Signatures draft](https://tools.ietf.org/html/draft-cavage-http-signatures-11#appendix-E.2) +lists more algorithms; we could support them too. This proposal just suggests +that we all start supporting Ed25519 in addition to RSA. + +#### (6) HTTP Signature draft 11 + +The draft linked above, from April 2019, makes some changes and +recommendations. This proposal suggests we adopt them: + +- For the `algorithm` parameter, use the value `hs2019`, or none, and start + deprecating the old values (such as `rsa-sha256`). +- The new `created` and `expires` parameters seem to be mostly useful to web + browser based clients, while our usage of HTTP Signatures is between servers. + So perhaps they aren't very useful here. But if someone finds them useful, + let's support them. +- Support at least Ed25519 in addition to RSA, see proposal A.5 above. + +#### (7) Key rotation using a pair of server-scope keys + +Allows to easily and computationally-cheaply perform periodic key rotation. + +Rationale: + +If you deliver an activity and then rotate the key, the target servers will +want to fetch the old key to verify your signatures, but, the old key has been +replaced, so they will fail to authenticate your requests. When using per-actor +keys, it's possible to try waiting for a time the user is inactive (which is +hopefully common because most people probably sleep for a few hours every day), +and use that as a safer chance to rotate the key. During the quiet time, other +servers will have had enough time to process their activity inbox queues, and +by the time we rotate, nobody will want the old key anymore. + +The weakness of that solution is that: + +- It's limited to periods of inactivity, which may limit rotation to once per + day or less (what if you want to rotate more often? Hmm is there a good + reason to? I'm not sure, just saying hypothetically) +- It doesn't work for users that don't have inactivity periods, e.g. a user + that uses scheduled activities, automatic responses etc. +- It involves the computation of generating a new key for every user every day + (assuming we don't want to rotate more often), which I suppose can be + somewhat heavy, especially for RSA (but I haven't done any measurements) +- It involves lots of network activity because other servers will be fetching + the new rotated keys all the time, keys can't be cached for days or weeks or + more if they keep being replaced every day or every hour (but I haven't done + measurements of the effect on the amount of network requests) + +The proposal: + +- Each server has 2 or more server-scope keys. For simplicity of discussion, + let's assume a server has exactly 2 keys, key A and key B. +- The server does periodic rotation, but each time, it rotates one of the keys + and leaves the other intact. It rotates key A, then next time it rotates key + B, next time it rotates key A again, next time it rotates key B again... and + so on. +- When signing HTTP requests, the server always uses the newer key. For + example, if it just rotated key A, it will sign the next requests with key A. + When time comes for the next rotation, it will rotate key B and stop using + key A, switching to using key B for signing requests. +- The time frame suggested here for letting other servers finish processing our + activities in their inbox queues is **one hour**, although this is just a + suggestion and open to discussion. So it's suggested you do periodic rotation + at most once an hour (or at least leave a key available for at least an hour + without change after you stop using it) + +That way, when one of the keys is rotated, the other key is still available for +another hour and other servers are able to use it to verify the signatures we +sent. There's no need to wait for users to be inactive, and it's very cheap: +Rotate 1 key per hour. Especially if that key is Ed25519. ### (B) ActivityPub