-
Notifications
You must be signed in to change notification settings - Fork 385
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
base: old_master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,213 @@ | ||
# MSC2882: Tempered Transitive Trust | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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? There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. There was a problem hiding this comment. Choose a reason for hiding this commentThe 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" There was a problem hiding this comment. Choose a reason for hiding this commentThe 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? There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 There was a problem hiding this comment. Choose a reason for hiding this commentThe 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` | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For consistency, shouldn't the usage be called |
||
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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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? There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. There was a problem hiding this comment. Choose a reason for hiding this commentThe 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? There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 There was a problem hiding this comment. Choose a reason for hiding this commentThe 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). There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 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.\] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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:
Now, saying that we only trust Bob to verify on behalf of 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.: or with some other wording. If we have verified the user then we don't show a label. There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. or, if the keyword |
||
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`. |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.