Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MSC1680: cross-signing #1681

Closed
wants to merge 11 commits into from
273 changes: 273 additions & 0 deletions proposals/1680-cross-signing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,273 @@
Cross-signing devices
=====================

Problem/Background
------------------
A user with multiple devices will have a different key for end-to-end
encryption for each device. Other users who want to communicate securely with
this user must then verify each key on each of their devices. If Alice has *n*
devices, and Bob has *m* devices, then for Alice to be able to communicate with
Bob on any of their devices, this involves *n×m* key verifications.

One way in which key verification has historically been addressed is through a
web-of-trust system: if Alice trusts Bob, and Bob trusts Carol, then Alice may
trust Carol even though Alice is unable to verify Carol's key directly.
Cross-signing can be seen as a limited web-of-trust, in which one device can
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That would make working in encrypted work chats with lots of people a bit complicated.. Where does this limitation come from? As long as the users know how the trust is established, going over multiple users should be okay IMO

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Normal web-of-trusts (webs-of-trust?) are a bit tricky, because you need to determine how much you trust other people to have verified other people. For example, cryptogeek Alice might be very strict about checking identities, and may have verified Bob's device, but might not trust Bob to have properly verified Carol's identity, or may not trust him to not be maliciously signing fake devices for other people, so will not trust Bob's attestations. However, Bob, knowing how much of a paranoid cryptogeek Alice is, and knowing that she's a whitehat, might have no problems trusting Alice's attestations.

In the case of cross-signing, we make the assumption that people are generally sane and will only verify their own devices only they actually belong to them, as signing a fake device will harm themselves.

It may be possible that we implement a more extended web-of-trust later on, but for now, I think it's better to keep it simpler.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about still saying a device is unverified, but showing the user a dag of attestations from themselves to the other device? The more different paths there are, and the shorter they are, the more trustworthy a device would be. I think it's fine to limit cross signing to own devices for now, but I'm not sure that is a limitation that should be made at the protocol level instead of the UX level.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A more advanced WoT trust like that would be satisfying, but I do worry about the users who just verify devices because they like how the green lock looks, without actually checking it.

I also don't want to verify my mother's devices meaning that I trust all the random trust decisions she's making.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't want to verify my peers random devices either, but that just means I have to live with all the yellow exclamation marks.. As I said, I'd limit that via UX, but I wouldn't want to have a more advanced WoT blocked by protocol decisions worrying about what some users might do to avoid bad UX (because honestly, verifying devices to get green locks sounds like bad UX to me)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, the big concern here for me is the fact that it broadcasts metadata to all users on the network. Just because you’ve verified Lenin’s keys doesn’t mean that I want you know that I have too...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not saying we should publish any attestations for devices of other people here, I am just saying we shouldn't forbid that in the protocol, so that a more generalized WoT would be a client side extension, not a server side one.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It needs server-side changes anyways, since the server needs to control what attestations it shows to users, and what attestations it forwards to other server, so it can't be a purely client-side extension.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought the query endpoint would be used to query the attestations published by a user? Filtering out any that try to do attestations for devices not controlled by that user is something the client could do.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The query endpoint is used to query the attestations made about the device/user, not made by the device/user.

vouch for another device that belongs to the same user. For example if Alice
has an Osborne 2 and a PDP-11, and Bob has a Dynabook and a VAX, then Alice can
verify her Osborne 2 with her PDP-11 (and vice versa), and Bob can verify his
Dynabook with his VAX (and vice versa). When Alice and Bob meet in person,
Alice's Osborne 2 can verify Bob's Dynabook (and vice versa). These
verifications can be published, which will allow Alice's PDP-11 to trust Bob's
VAX (and vice versa) without having them directly verify each other, or even
without the PDP-11 having to directly verify any of Bob's devices, or any of
Alice's devices having to directly verify Bob's VAX.

See also:

- https://github.com/vector-im/riot-web/issues/2714

Proposal
--------

When one device verifies another device, it will publish an attestation (in the
form of a [signed JSON
object](https://matrix.org/docs/spec/appendices.html#signing-json)) indicating
this. Attestations can also be revoked by publishing another signed JSON
object. Other devices can use these attestations to trust other devices that
have not been directly verified. Users will only be able to see attestations
and revocations made by their own devices, or attestations and revocations made
between devices belonging to the same user. That is, Alice can see
attestations made by her own devices, or attestations made by Bob's devices
about Bob's devices, but she cannot see attestations made by Carol's devices
about Bob's devices, attestations made by Bob's devices about Carol's devices,
nor attestations made by Bob nor Carol about Alice's devices.

Attestations and revocations are published by using the `POST
/_matrix/client/r0/keys/upload` endpoint and are retrieved by using the `POST
/_matrix/client/r0/keys/query` endpoint. When new attestations or revocations
are published, then the user who owns the device that the attestation is about
will be included in the `changed` array in the `device_lists` property of the
`/sync` response for all users that share a room with that user.

Attestations form a directed graph (not necessarily acyclic) in which edges go
from the device making the attestation to the device that the attestation is
about, as long as the signature is valid, the data in the data in the
attestation matches the device key, and there is no corresponding
revocation. If Device A can construct a directed path in this graph starting
from a device it has verified and ending at Device B, consisting only of
devices owned by either Device A's owner or Device B's owner, then it may treat
Device B as trusted. Device A may do so automatically, or after prompting the
user, or may allow the user to disable this functionality completely.

TODO: should Device A then publish an attestation for Device B?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

our verification mechanisms are symmetrical so presumably the signing graph shouldn't actually be directional? (and could also be cyclic unless we explicitly stop cycles...)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The verification mechanisms are symmetrical, but the attestations are directed, as one device of the pair might not publish their attestation.

I should probably also spell out that the graph, although is directed, is not necessarily acyclic, unlike every other time that "directed graphs" are mentioned in Matrix.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i'm failing to think of a reason why you wouldn't publish symmetrical attestations between your own devices. and (unless i'm misunderstanding everything), you shouldn't be ever publishing attestations about other people's devices to anyone but yourself?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The attestation graph has to be directed, otherwise a malicious user could create a fake device under Alice's account and publish an attestation for one of her other devices, and trick the other devices into thinking that the trust is mutual.

Copy link
Contributor

@jcgruenhage jcgruenhage Sep 21, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The client could prompt the user whether it should do it or not.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to ensure this is presented in a friendly way to non-techies though.


### Client-Server API

#### Additions to `POST /_matrix/client/r0/keys/upload`

This proposal will add an additional property to the request body of the [`POST
/_matrix/client/r0/keys/upload`](https://matrix.org/docs/spec/client_server/r0.4.0.html#post-matrix-client-r0-keys-upload)
endpoint:

- `attestations` (`[Attestation]` (see below)): The attestations or revocations
to be published. Attestations that do not come from the user calling the
endpoint MUST be discarded.

#### Additions to `POST /_matrix/client/r0/keys/query`
jcgruenhage marked this conversation as resolved.
Show resolved Hide resolved

This proposal will add an additional property to the `UnsignedDeviceInfo` type
in the [`POST
/_matrix/client/r0/keys/query`](https://matrix.org/docs/spec/client_server/r0.4.0.html#post-matrix-client-r0-keys-query)
endpoint:

- `attestations` (`[Attestation]` (see below)): The published attestations or
revocations for the device. This array MUST only include the attestations or
revocations made by devices belonging to the user calling the endpoint, or
made by devices belonging to the owner of the device being queried. For
example, when Alice calls this endpoint to fetch information about Bob's
devices, this array will only include attestations or revocations made by
Alice's devices or by Bob's other devices.

Attestations that have the same contents (other than the `signatures`
property) may be combined by the server by changing the `signatures` property
to include multiple signatures for the given object contents.

Example return value:

```javascript
{
"failures": {},
"device_keys": {
"@alice:example.com": {
"JLAFKJWSCS": {
"user_id": "@alice:example.com",
"device_id": "JLAFKJWSCS",
"algorithms": [
"m.olm.v1.curve25519-aes-sha256",
"m.megolm.v1.aes-sha"
],
"keys": {
"curve25519:JLAFKJWSCS": "3C5BFWi2Y8MaVvjM8M22DBmh24PmgR0nPvJOIArzgyI",
"ed25519:JLAFKJWSCS": "lEuiRJBit0IG6nUf5pUzWTUEsRVVe/HJkoKuEww9ULI"
},
"signatures": {
"@alice:example.com": {
"ed25519:JLAFKJWSCS": "dSO80A01XiigH3uBiDVx/EjzaoycHcjq9lfQX0uWsqxl2giMIiSPR8a4d291W1ihKJL/a+myXS367WT6NAIcBA"
}
},
"unsigned": {
"device_display_name": "Alice's mobile phone",
"attestations": [
{
"user_id": "@alice:example.com",
"device_id": "JLAFKJWSCS",
"keys": {
"ed25519:JLAFKJWSCS": "base64+encoded+key"
},
"state": "verified",
"signatures": {
"@bob:example.org": {
"ed25519:ABCDEFG": "base64+encoded+signature"
}
}
}
]
}
}
}
}
}
```

TODO: `keys/query` may need to include devices that have been logged out, in
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you saying that we should distinguish between devices which were logged out but are still trustable versus ones which were logged out but whose trust should be explicitly revoked? This feels like we could end up with three classes of logouts:

  • soft-logout (where the device doesn't delete any data, is still trusted, but the user needs to be reauthenticated as a precaution after doing something like changing their password)
  • trusted-hard-logout (where the device destroys all local data and logs out the user... but its attestations are still trusted)
  • untrusted-hard-logout (same, but attestations now revoked).

I wonder if this is overengineered - do we really need the trusted-hard-logout state? It feels that if you have abandoned a device and logged it out, its attestations may not be worth very much any more, even if they seemed okay at the time...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you saying that we should distinguish between devices which were logged out but are still trustable versus ones which were logged out but whose trust should be explicitly revoked?

Yes, that's the idea. I'm not sure if it's needed, but it's something that we were thinking about when we were brainstorming. I think the situation we were thinking of was where Bob cycles through devices very quickly. So Alice verifies Bob's Osborne 2. The following week, Bob replaces his Osborne 2 with a Dynabook, and the week after, Bob replaces is Dynabook with a PADD. Alice logs on for the first time since verifying Bob's Osborne 2, and is unable to trust Bob's PADD, because the Dynabook and Osborne 2 are logged out.

order to avoid unexpectedly breaking trust chains, so we may want to recommend
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably include old devices (and the point when they were removed) anyway, for people who scroll back up. We might even want to store attestations from the new devices signing that the old device was trusted in some timeframe, so that new devices can read history and know that it's okay.

that devices remain in the result for *n* days after they log out? However, we
don't want to other devices to continue to encrypt for that device, so maybe
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
don't want to other devices to continue to encrypt for that device, so maybe
don't want other devices to continue to encrypt for that device, so maybe

add a flag saying that it's stale, or put stale devices in a separate parameter
(`stale_device_keys` instead of `device_keys`)?

#### `Attestation` type

Properties:

- `user_id` (string): Required. The ID of the user whose device has been verified
- `device_id` (string): Required. The ID of the device that has been verified.
- `keys` ({string: string}): Required. The public identity keys that have been
verified. This will normally just be the signing key (e.g. the ed25519 key).
- `state` (string): Required. The verification state. One of "verified" or
"revoked".
- `signatures` ({string: {string: string}}): A map from user ID, to a map
from <algorithm>:<device_id> to the signature. The signature is calculated
as described in [Signing
JSON](https://matrix.org/docs/spec/appendices.html#signing-json)

Example:

Alice's Osborne 2 verifies Bob's Dynabook

```json
{
"user_id": "@bob:example.com",
"device_id": "ABCDEFG",
"keys": {
"ed25519:ABCDEFG": "base64+encoded+key"
},
"state": "verified",
"signatures": {
"@alice:example.org": {
"ed25519:ZYXWVUT": "base64+encoded+signature"
}
}
}
```

#### Additions to extensions to /sync

The End-to-End encryption module defines [extensions to
`/sync`](https://matrix.org/docs/spec/client_server/r0.4.0.html#device-lists-sync).
This proposal will change the description of the `changed` parameter in the
`DeviceLists` type defined in those extensions to read:

> List of users who have updated their device identity keys, or who now share
> an encrypted room with the client, or who have received additional
> attestations or revocations that are visible to the user since the previous
> sync response.

#### Additions to `GET /_matrix/client/r0/keys/changes`

This proposal will change the [`GET /_matrix/client/r0/keys/changes`](GET
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

broken link here

/_matrix/client/r0/keys/changes) endpoint to include in the `changed` parameter
of the result users who have new attestations that are visible to the calling
user.

### Federation API

#### Additions to `POST /_matrix/federation/v1/user/keys/query`

This proposal will add an additional property to the `UnsignedDeviceInfo` type
in the [`POST
/_matrix/federation/v1/user/keys/query`](https://matrix.org/docs/spec/server_server/unstable.html#post-matrix-federation-v1-user-keys-query)
endpoint:

- `attestations` (`[Attestation]` (see above)): The published attestations or
revocations for the device. This array MUST only include the attestations or
revocations made by devices belonging to the owner of the device being queried.

Attestations that have the same contents (other than the `signatures`
property) may be combined by the server by changing the `signatures` property
to include multiple signatures for the given object contents.

#### Additions to `GET /_matrix/federation/v1/user/devices/{userId}`

This proposal will add an additional property to the `User Device` type, for
the `devices` return parameter in the [`GET
/_matrix/federation/v1/user/devices/{userId}`](https://matrix.org/docs/spec/server_server/unstable.html#post-matrix-federation-v1-user-keys-query)
endpoint:

- `attestations` (`[Attestation]` (see above)): The published attestations or
revocations for the device. This array MUST only include the attestations or
revocations made by devices belonging to the owner of the device being queried.

Attestations that have the same contents (other than the `signatures`
property) may be combined by the server by changing the `signatures` property
to include multiple signatures for the given object contents.

#### Additions to `m.device_list_update` schema

A new field will be added to the `m.device_list_update` EDU schema:

- `attestations` (`[Attestation]` (see above)): The published attestations or
revocations for the device. This array MUST only include the attestations or
revocations made by devices belonging to the owner of the device being
queried.

Tradeoffs
---------

Security Considerations
-----------------------

If an attacker gains access to a device, then they can send revocations for all
of the user's other devices, causing it to seem like the device controlled by
the attacker is the only valid device. For this reason, revocations should be
treated with caution, and may require manual intervention to sort out.

TODO: we probably need to spell out in more detail how revocations should be
handled.

Publishing attestations leaks metadata to server operators about what users
know each other. In order to address this, clients may give users the option
of whether to publish attestations or not.

A malicious hommeserver is able to prevent distribution of revocations. For
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
A malicious hommeserver is able to prevent distribution of revocations. For
A malicious homeserver is able to prevent distribution of revocations. For

example, a malicious user who takes control of a user's device *and* who
controls the user's homeserver could prevent revocations on that device from
being published, so that other users would not be aware that the device has
been compromised.

Other Issues
------------

Conclusion
----------