pull/2787/merge
Neil 2 months ago committed by GitHub
commit 68ec903fe6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,317 @@
# MSC2787: Portable Identities
## Background
This is an evolution of [MSC1228](https://github.com/matrix-org/matrix-doc/pull/1228)
which aims to make it simpler to implement portable identities and decentralised
accounts.
It is still a work-in-progress—some things that need attention include:
- How to handle multiple homeservers joining the same room, since they will have
their own membership events, and clients may wish to disambiguate these;
- How to handle invites, given that you won't know a UDK until after the user has
joined the room;
- How to adequately disconnect UDKs from UPKs as a part of a data removal request
for GDPR compliance;
- Whether UPKs should really be a "one true identity" for a user or whether a user
may actually have multiple UPKs if they want;
- How to handle device list syncing and send-to-device messages;
- The extent to which users should be involved in attesting MXID-to-UPK mappings.
## Goals
The goals of this proposal are:
- To enable account portability by breaking the link between a user identity and a
specific homeserver;
- To allow breaking the link between delegated and permanent user identities at a
later date, e.g. as a part of a data deletion request;
- To allow a user to grant permission to one or more homeservers to act on behalf of
the user in a given room, e.g. allowing them to creating and sign events from a
user;
- To remove the need for servers to have a single static signing key, as they do
today.
## Proposal
This proposal includes specifications to:
- To give a user a single cryptographic User Permanent Key (herein referred to as
a "UPK"), which they will use as part of a cryptographic challenge login;
- To give a server a set of User Delegated Keys (herein referred to as a "UDK"),
which will represent servers acting on behalf of users within rooms;
- To allow users to attest one or more UDKs using their UPK;
- To remove Matrix IDs (MXIDs) and server names from events, similar to MSC1228;
- To allow a user to receive one or more server-provided MXIDs mapped to a UPK.
### User Permanent Key (UPK)
The UPK is an ed25519 public key which represents a user entity. The initial
intention is that a user will use this UPK to perform a challenge-response login
to a homeserver and that it will become their "one true identity".
Central to this design is that the UPKs are user-owned and therefore the private
key portion to each UPK is held by the user, although they could be protected with
a passphrase and backed up to key storage on one or more homeservers if needed.
The UPK private portion must not be decrypted nor used serverside.
#### UPK Format
The UDK is prefixed with a version byte, then URL-safe base64-encoded, and then
prefixed with the `~` sigil. The version byte for ed25519 is `0x01`.
### User Delegated Key (UDK)
Homeservers create a new UDK, which is an ed25519 key, on behalf of each user in
each room. These keys are generated and stored by the server when a user joins a
room:
1. The user requests to join a room;
2. The server generates a UDK and sends the public key to the client;
3. The client signs a UDK attestation using a UPK - this forms the link between
the UDK and the UPK;
4. The server generates the membership event, including the attestation, and sends
it into the room/to federated servers, signed using the new UDK.
The homeserver should store all active UPK-UDK links.
#### UDK Format
The UDK is prefixed with a version byte, then URL-safe base64-encoded, and then
prefixed with the `^` sigil. The version byte for ed25519 is `0x01`.
### Membership UDK Attestation
An attestation will include the UDK that is being attested to, and an expiry time. The
attestation will be valid for events up until the expiry time, at which point a new
attestation will be required.
The attestation `"content"` is built by the client, and then is signed with the UPK
before being sent to the server. The attested server will then add its own signature
using the UDK.
The completed attestation will take a format similar to this:
```
"attestation": {
"content": {
"identity": ~upk_that_is_attesting",
"delegate": "^udk_that_is_being_attested",
"server_name": "example.com",
"expires": 15895491111111
},
"signatures": {
"~upk_that_is_attesting": {
"ed25519": "upk_signature"
},
"~udk_that_is_being_attested": {
"ed25519": "udk_signature"
}
}
}
```
The attestation contains a `"server_name"` field which contains the name of the server
that manages the UDK. This is necessary as, without this, other servers in the room
will not be able to work out where to route messages for this UDK.
The attestation `"content"` key will then be canonicalised and signed, once by the UPK
and then once by the homeserver that issued the UDK.
#### Validity
The attestation will be valid from the point that it is sent (in effect, from the
`"origin_server_ts"` timestamp) up until the `"expires"` timestamp.
Since there may be multiple membership state events with renewals over time, event
validity is based on the attestation in the room state at (before) the event. If the attestation has expired in the room state at (before) the event, the attestation is
considered invalid - newer attestations must not be considered when determining the
validity period.
#### Authorisation rules
Events will continue to refer to the membership event as an auth event, with the
main difference being that the referred-to membership event will now contain one or
more attestations.
Authorisation rules will be updated to include extra clauses, that events should
only be accepted for a specific UDK as long as there is:
1. A valid attestation for the UDK in the referred membership event;
2. The event falls inclusive of the `"origin_server_ts"` and the `"expires"` of
the attestation;
3. An `m.room.member` event with an `"attestation"` section must contain a signature
from the UPK.
To cover the possibility of an attestation not being renewed, soft-fail rules will
be updated to include extra clauses, that events should be soft-failed when received as
new events unless there is:
1. A valid attestation for the UDK in the current room state;
2. The event falls before the `"expires"` timestamp of the attestation.
This prevents servers from continuing to impersonate the user with new events after
the attestation has expired - necessary as the server owns and maintains the UDK
keypair.
Some thought needs to be given on how to ban a UPK so that generating new UDKs is not
an effective measure for evading bans.
### Membership event format
A membership event including an attestation may look something like this:
```
{
"auth_events": [ ... ],
"prev_events": [ ... ],
"content": {
"avatar_url": "mxc://here/is/neilalexander.png",
"displayname": "neilalexander",
"membership": "join",
"attestation": {
"content": {
"identity": ~upk_that_is_attesting",
"delegate": "^udk_that_is_being_attested",
"server_name": "example.com",
"expires": 15895491111111
},
"signatures": {
"~upk_that_is_attesting": {
"ed25519": "upk_signature"
},
"~udk_that_is_being_attested": {
"ed25519": "udk_signature"
}
}
}
},
"origin_server_ts": 1589549295296,
"sender": "^udk_that_is_being_attested",
"signatures": {
"^udk_that_is_being_attested": ...
},
"hashes": {
"sha256": ...,
}
"state_key": "^udk_that_is_being_attested",
"type": "m.room.member",
"unsigned": {
"age": 25,
},
"event_id": "$eventid",
"room_id": "!roomid"
}
```
Note that there is no MXID in the `"sender"` and `"state_key"` fields, nor in the
`"signatures"` field of the event itself - these are now referencing the UPKs.
Multiple servers wanting to join on behalf of the same user should send their own
membership events, each with an attestation as created and signed by the user.
There may be a need for clients to disambiguate users.
### Timeline event format
Otherwise, the event format remains unchanged, with only one exception: that the
`"signatures"` contains the signature from the UDK, rather than from the server
itself as today:
```
{
"auth_events": [ ... ],
"prev_events": [ ... ],
"content": {
"body": "Hi!",
"msgtype": "m.text"
},
"origin_server_ts": 1589549295384,
"sender": "^udk_that_is_being_attested",
"signatures": {
"^udk_that_is_being_attested": ...
},
"hashes": {
"sha256": ...,
}
"type": "m.room.message",
"unsigned": {
"age": 26,
},
"event_id": "$eventid",
"room_id": "!roomid"
}
```
#### Renewing an attestation
At any time, the UPK holder can issue new attestations by sending updated membership
state events with a new attestation. This can be done either before or after the
validity of the previous attestation has expired.
The previous membership event with the previous attestation must appear in the
`auth_events` of the new membership event with the new attestation.
#### Removing an attestation
To remove an attestation, the membership event should be replaced with a new
membership event that no longer includes an attestation.
Assuming there is no need to remove evidence of the attestations ever existing,
then this will be sufficient. The previously attested servers will no longer be able
to send events into the room on behalf of the user.
#### Redacting an attestation
To satisfy data deletion requests, or where it may be important to fully remove links
between UDKs and UPKs for legal compliance, it should be possible to redact the
membership events to remove the `"attestation"` section from them.
This may need to be done recursively, following the `"auth_events"`, to remove all
historical attestations too.
TODO: Doing this may mean that other servers that try to backfill may not be able to
verify that the events were allowed to be sent?
As the redaction algorithms already have rules for `m.room.member` events which will
preserve the `"membership"` key, it should be possible to redact any other personally
identifiable information such as the `"attestation"`, the `"display_name"` or the
`"avatar_url"` without issue.
The UDK signature will remain in the event, but without the attestation, it will not
be possible to link it to a UPK.
### Matrix ID to UPK mapping
Public keys as identifiers may enable some portability but they aren't user-friendly
and somewhat difficult to put on a business card. For this, it is necessary to be
able to allow users to maintain MXID mappings much as they have today.
However, a homeserver returning a UPK for an MXID should ideally imply that the server
actually has some kind of association with the user and that the user is resident,
rather than third-party servers gratuitously providing MXID mappings for users that
they may not otherwise be aware of.
### User signalling
For things like invites, direct messages etc, it is not possible to know what the UDK
will be before a homeserver generates one to join the room. Therefore these endpoints
should be updated to use either:
- A UPK in combination with a previously-known resident server name;
- A MXID, from which a response will contain the UPK and a resident server name.
In these instances, you are addressing "the user" rather than a UDK.
### Invites
TODO.
### Device list syncing
TODO.
### Send-to-device
TODO.
Loading…
Cancel
Save