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

MSC2882: [WIP] Tempered Transitive Trust #2882

Draft
wants to merge 3 commits into
base: old_master
Choose a base branch
from
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
213 changes: 213 additions & 0 deletions proposals/2882-tempered-transitive-trust.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
# MSC2882: Tempered Transitive Trust
Copy link
Contributor

Choose a reason for hiding this comment

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

If you publish now signatures visible for others, the need to unpublish signatures you previously published is greater and greater. Perhaps it is a good idea to tackle that, too? Maybe in another MSC?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yup, good point. It may make sense to include it in this MSC, but we'll see how it goes.

Copy link
Contributor

Choose a reason for hiding this comment

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

Fluffychat at least currently only subscribes to the device list of people you share an e2ee room with, currently.

If soru understands this correctly, this will also have to expand to all people who are part of a signature chain you want to potentially verify, is that correct?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes. I think this is also a limitation on the server side, where it will only send you device updates from people that you share rooms with. I should probably note that in this MSC somewhere.

It may or may not be a problem in practice since you'll want to verify people in the signature chain, which generally involves creating a DM with them.

Copy link
Contributor

@Sorunome Sorunome Jan 8, 2021

Choose a reason for hiding this comment

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

It'll be a problem as soon as there is an additional hop: we don't only trust who bob trusts, we also trust people who bob trusts and who those trust. This MSC doesn't cover that usecase, so maybe it is enough to state this "for later".

Sorus usecase is again with a "trust management" of a company, that if you query the "trust management" keys separately and verify them somehow, without needing a DM (remember the talk / suggestion of other kind of signatures to master keys we had?) an external person can easily know who all in that company is trusted, without having to create a DM with "trust management"

Copy link
Contributor

@Sorunome Sorunome Jan 8, 2021

Choose a reason for hiding this comment

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

Just for some clarification help:

Let's say we have a company with a trust managing team, said trust managing team signs the master key of all their employees with their public user signing key.

Now, if someone from outside the company wants to contact that company, after verifying the trust management team somehow (up to the future / a future MSC?) they can then see that the specific device was signed by trust management and trust management is valid. What they CAN'T do, though, is query all signatures that trust management made, so they CAN'T just query the entire list of employee accounts, as the signatures are attached to the device that got signed. Is that correct?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes. If "Trust Management" signs Alice's key, then Bob will only see that signature when he queries Alice's key. Nothing from "Trust Management" will point to Alice just by querying "Trust Management"

uhoreg marked this conversation as resolved.
Show resolved Hide resolved

There are many situations in which two people are unable to verify each other
directly, but they both trust a third party to mediate the verification. For
Copy link
Member

Choose a reason for hiding this comment

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

I don't think we need a requirement that they both trust the middleman to mediate? If Alice wants to verify Bob via Michael, then Alice needs to trust Michael, but Bob doesn't get a say in whether Michael signs and publishes Bob's key?

example, it may be impractical for all employees in a company to verify each
other, but the company may be able to provide a trusted agent who can verify
all employees.

In order to do this, we need to a mechanism for users to share their
verifications with other users. However, this sharing needs to be done in a
Copy link
Member

Choose a reason for hiding this comment

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

Do these need to be users? I think the common case is for these to be more organisation level stuff, e.g. a business publishing a list of signed employee keys. It would be nice to be able to support very noddy implementations that don't require a real account and client

Copy link
Contributor

Choose a reason for hiding this comment

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

It would be trivial to make a trust-signing-only client and making it users reduces the need to introduce a new entity which can have device keys etc.

If you are more thinking about third party signatures, that's a separate MSC: #2961

Copy link
Member

Choose a reason for hiding this comment

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

Yeah, I guess I'm mostly just saying let's keep that use case in mind. Especially if it actually becomes the dominant use of this feature (which I think it very well might).

controlled, or tempered, fashion so that we maintain the privacy of a user's
contacts: if Alice has verified Bob, Alice should be able to choose whether she
makes that fact public or not.

In addition, Bob should be able to select which of Alice's public verifications
he wants to trust. For example, he may wish to trust Alice to verify her
co-workers, but not any other people.

To do this, we introduce one new per-user key for making public attestations on
other users' identities. We define a new account-data event for storing (via
SSSS) which users to trust for verifying other users. We also replace the
`POST /keys/signatures/upload` endpoint defined in
[MSC1756](/~https://github.com/matrix-org/matrix-doc/pull/1756) with an endpoint
that provides more flexibility, and create a new endpoint to delete signatures.

## Proposal

Each user has a new Ed25519 key, a public user signing key, which is used for
making public signatures on other users' master or public user keys. The
public part of this key can be uploaded to `POST /keys/device_signing/upload`
by using the name `public_user_signing_key`. When uploaded, it must be signed
with the user's master key, and must have `public-user` in the `usage`
Copy link
Contributor

Choose a reason for hiding this comment

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

#2757 also introduces a new key, an event-signing key. Implementations might want to create both keys at the same time to only have to do one migration for both features.

Copy link
Contributor

Choose a reason for hiding this comment

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

For consistency, shouldn't the usage be called public_user_signing?

property. The private part of this key can be stored in the
`m.cross_signig.public_user_signing` account-data using
[SSSS](/~https://github.com/matrix-org/matrix-doc/pull/1946), using the same
format as the other cross-signing keys.

### Publishing signatures

When Alice wants to publish the fact that she has verified Bob, she will upload
a signature of Bob's master key signed with her public user signing key.
Similarly, she can also publish the fact that she trusts Bob to verify other
people by upload a signature of Bob's public user signing key signed with her
own public user signing key. \[FIXME: Should we have some way for Alice to
Copy link
Member

Choose a reason for hiding this comment

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

I think we need to be careful here, handing out trust is quite a big deal to begin with, and doing so transitively to large degrees is going to lead to some surprising situations where someone in Alaska has accidentally verified a scammer and now I trust the scammer because I'm friends of friends of friends of someone in Alaska. I don't really think saying that you should trust who you trust really works here.

indicate who she trusts Bob to verify?\] Signing public user signing keys
allows for multi-hop transitive trust: by publishing the fact that Alice trusts
Bob to verify users and to sign them with a given public user signing key,
Carol can verify with Alice and (if she believes that Alice is a good judge of
character) can then trust the users that Bob has publicly signed.
Copy link
Member

Choose a reason for hiding this comment

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

If Bob trusts Alice to verify people, and Alice uploads new signatures, how does Bob get those updates? Do those get pushed to him?

Copy link
Contributor

Choose a reason for hiding this comment

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

Probably the same as with x-singing: Bob trusts alice to verify people, and alice adds a signature to....clair.

If Bob already has an open room with Clair, bob will get in his /sync that clairs device is out-of-date and re-query it, including alice new signature

Copy link
Member

Choose a reason for hiding this comment

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

Should we add an option for a single snapshot approach? I.e. Bob can verify everyone who Alice has currently verified? That way you can a) manually see who Alice has verified (you could even have an advanced mode where you select a subset of users to copy across), and b) you don't need to worry about Alice doing something stupid later.

Copy link
Contributor

Choose a reason for hiding this comment

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

Isn't that an implementation detail, for when a client generates signatures of other devices directly?

Copy link
Member

Choose a reason for hiding this comment

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

Yup, though I think its probably worth calling out explicitly as something clients can/should support


We introduce a new endpoint, `POST /...FIXME: what name should we use?` for
uploading signatures for devices and cross-signing keys. The request body has
two parameters, both optional: `public` and `private`. Both of these
parameters are an mapping of user ID to key ID to signed key. The signatures
given in the `public` parameter will be made public and may be visible to any
Matrix user, while the signatures given in the `private` parameter will only be
seen by the user who uploaded it.

This endpoint may be used as a replacement for the `POST
/keys/signatures/upload` endpoint defined in
[MSC1756](/~https://github.com/matrix-org/matrix-doc/pull/1756) by putting
signatures made by the user's self-signing key in `public`, and signatures made
by the user's user-signing key in `private`. `POST /keys/signatures/upload` is
also now deprecated.

Example:

The example of `POST /keys/signatures/upload` given in MSC1756, with errors
corrected and with a public signature of another user, can be written
instead as:

```json
POST /...?

{
"public": {
"@alice:example.com": {
"HIJKLMN": {
"user_id": "@alice:example.com",
"device_id": "HIJKLMN",
"algorithms": [
"m.olm.curve25519-aes-sha256",
"m.megolm.v1.aes-sha"
],
"keys": {
"curve25519:HIJKLMN": "base64+curve25519+key",
"ed25519:HIJKLMN": "base64+ed25519+key"
},
"signatures": {
"@alice:example.com": {
"ed25519:base64+self+signing+public+key": "base64+signature+of+HIJKLMN"
}
}
},
"base64+master+public+key": {
"user_id": "@alice:example.com",
"usage": ["master"],
"keys": {
"ed25519:base64+master+public+key": "base64+master+public+key"
},
"signatures": {
"@alice:example.com": {
"ed25519:HIJKLMN": "base64+signature+of+master+key"
}
}
}
},
"@carol:example.com": {
"carols+base64+master+public+key": {
"user_id": "@carol:example.com",
"keys": {
"ed25519:carols+base64+master+public+key": "carols+base64+master+public+key"
},
"usage": ["master"],
"signatures": {
"@alice:example.com": {
"ed25519:alices+base64+public+user+signing+key": "base64+signature"
}
}
}
}
},
"private": {
"@bob:example.com": {
"bobs+base64+master+public+key": {
"user_id": "@bob:example.com",
"keys": {
"ed25519:bobs+base64+master+public+key": "bobs+base64+master+public+key"
},
"usage": ["master"],
"signatures": {
"@alice:example.com": {
"ed25519:base64+user+signing+public+key": "base64+signature+of+bobs+master+key"
}
}
}
}
}
}
```

To avoid abuse by flooding a user's devices/keys with signatures, each user may
only make one public signature on another user's device/key; if they make
Copy link
Contributor

Choose a reason for hiding this comment

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

What limits, if any, does this bring?

another signature, on a device/key, the old signature will be removed. \[We
should also add a size limit on signatures. ~1KB should be sufficient per
signature.\]

When Alice makes a public signature is made on Bob's device/key, Alice's
homeserver will inform Bob's homeserver of the new signature using an EDU of
type `m.device.signature`. \[FIXME: define the properties.\]

\[FIXME: should we also replace `POST /keys/device_signing/upload` with something
that's more flexible with the key types? We need to have *some* checking,
since we check that the USK/SSK/PUSK are signed by the master key, so it can't
just be divided into public and private. But maybe we can have master, public
and private under the assumption that anything that isn't master must be signed
by the master key?\]

### Trusting trust

If Bob wants to trust Alice's signatures for some users, he will store
information in the `m.trust.transitive` event type in account-data. This
Copy link
Contributor

Choose a reason for hiding this comment

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

Account data is private anyways, shouldn't signing with the event signing MSC be sufficient? Otherwise we also end in a situation that the user will have to enter their recovery passphrase on every single device every time they updated their trust model.

As only the homeserver admin could review whom bob trusts, one could argue that that isn't much of a breach as the homeserver admin sees whom bob communicates with, anyways.

information will be encrypted using SSSS; encryption performs two functions: it
prevents others from seeing who Bob trusts, and it ensures that others cannot
change who Bob trusts since the encryption used by SSSS also authenticates the
data.

\[FIXME: define how `m.trust.transitive` is formatted. Initial ideas are
something along the lines of having a mapping of trusted users to users that
they are trusted for (e.g. I trust Alice to verify `@carol:matrix.org` and
`*:example.org`), plus a list of exceptions (e.g. even though I said I trust
Copy link
Contributor

Choose a reason for hiding this comment

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

perhaps also a user suggesting what to trust for them, that way for e2be the bridge bot could suggest @_discord_*:example.org or something

Copy link
Contributor

Choose a reason for hiding this comment

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

though it might be easier to only add that once profiles-as-rooms is a thing

Copy link
Member Author

Choose a reason for hiding this comment

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

Yup, agreed on both points (that it would be a good feature, and that it may be better to wait for profiles-as-rooms).

Copy link
Contributor

Choose a reason for hiding this comment

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

Another good thing might be, again in profiles-as-rooms, define in a signed event whom all to use as trust source, too.

Example of what soru means:
A company has a trust management, with which each new employee verifies. Now, the company grows, and the need for multiple trust managements arise. So, the company sets up a "Main Trust", with sub-trust-managements for different parts., so like

    Main trust
     /        \
Trust A     Trust B

A new employee should now be able to verify with either Trust A, or Trust B. Those, in turn, say things trusted by "Main trust" are to be trusted, and "Main trust" says people trusted by both "Trust A" and "Trust B" are to be trusted.

This could be modeled by having a signed event in profile-as-room with an array of MXIDs whos transitive-trust level are to be seen the same as your own.

Alice to verify `*:example.org`, I don't want to trust her for
`@dave:example.org` (e.g. because I have coffee with him regularly and can
easily verify him myself).) Perhaps we could also do something like "I trust
Alice to verify all the users who are in a given room", which could be helpful
if, e.g. all of a company's employees are in a common company chat room, but
could allow a server admin to lie about someone being in the room so that you
will trust a signature on that user. Specifying multi-hop trust may be
complicated.\]
Copy link
Member

Choose a reason for hiding this comment

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

So this actually touches on my main concern with transitive trust, and that's that verification is really the linchpin of our security model: if someone manages to break it then it opens up lots of attacks. This then leads to some competing concerns:

  1. we're saying you should be really careful who you trust, and that you should trust how they handle security of their devices; and
  2. we want to allow users to easily verify organisations and large groups of people at once, to avoid everyone having to manually verify each other.

Now, saying that we only trust Bob to verify on behalf of *:example.com sort of alleviates this, but a) doesn't help for groups/organisations that have users from multiple (or event just public) homeservers.

One suggestion here would be that all transitive trust are associated with a label (that the user can select, though the remote user can give a default), and every time we render that user in the app we include the label, e.g.:

Screenshot from 2021-02-19 16-58-28

or with some other wording.

If we have verified the user then we don't show a label.

Copy link
Member

Choose a reason for hiding this comment

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

We should be explicit that we trust local verification over transitive ones, i.e. if we have verified Bob then we ignore any other claims for Bob (concretely, if a transitive user has verified a different key than we have, we should not trust the other key)


## Potential issues

When a user makes their signatures public, this is visible to all Matrix users.
Copy link
Contributor

Choose a reason for hiding this comment

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

What if signatures are only made public to all users of a specific homeserver?

This could be used, for example, to find all the employees of a company by
checking which users have signatures made by the company's agent.

## Alternatives

Rather than classifying signatures as "public" and "private", we could also
have some signatures with a limited distribution, where they will only be seen
by certain people. This would prevent the issue listed in the "Security
considerations" section, but would increase the complexity.

Rather than replacing `POST /keys/signatures/upload` with a new endpoint, we
could just use the current `POST /keys/signatures/upload` endpoint and have the
Copy link
Contributor

Choose a reason for hiding this comment

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

or, if the keyword public and private are lacking, it does the fallback by key type

server infer the distribution based on the key type. However, this does not
allow for easy additions of new key types, and increases the complexity of the
server implementation.

## Security considerations

When a user makes their signatures public, this is visible to all Matrix users.
This could be used, for example, to find all the employees of a company by
checking which users have signatures made by the company's agent.

## Unstable prefix

The new endpoints will be prefixed with `/unstable/msc2882` until they land in
a released version of the spec, and event types should be prefixed with
`org.matrix.msc2882.` instead of `m.`.

Clients can discover if a server supports this feature by checking for the
`org.matrix.msc2882` unstable feature flag in `GET /versions`.