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

MSC1544: Key verification using QR codes #1544

Merged
merged 26 commits into from
Nov 25, 2020
Merged
Changes from 13 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
3aba9b1
initial dump of proposal
uhoreg Aug 20, 2018
3734471
mention option of having the QR code be a URL
uhoreg Aug 20, 2018
acd9a5d
add note about Bob mashing the "Verify" button prematurely
uhoreg Aug 20, 2018
95280d8
switch QR code to URL, add introductory text, add clarifications, reo…
uhoreg Sep 5, 2018
517754b
use common key verification message types as per MSC1717
uhoreg Jan 8, 2019
ba39779
add a conclusion
uhoreg Jan 8, 2019
3b0073a
allow for multiple keys to be verified, for cross-signing
uhoreg Jan 8, 2019
38689a8
add information about interacting with key requests and define cancel…
uhoreg Jan 8, 2019
10b6fd6
add more crypto magic, clarify things, add examples
uhoreg Sep 18, 2019
332b560
simplify protocol by embedding Alice's key in Bob's QR code
uhoreg Sep 19, 2019
4f83bd3
Update proposals/1543-qr_code_key_verification.md
uhoreg Jan 22, 2020
379bb79
Update proposals/1543-qr_code_key_verification.md
uhoreg Jan 22, 2020
a8c7fda
add some clarifications
uhoreg Jan 24, 2020
be9c37e
more clarifications, add comparison with SAS
uhoreg Jan 27, 2020
0b4411e
more words
uhoreg Jan 28, 2020
fcfd5d9
add examples for self-verification
uhoreg Jan 29, 2020
21ddf85
make other_user_key optional for one flow of self-verification
uhoreg Jan 29, 2020
7f93084
request can be transaction_id
uhoreg Jan 30, 2020
78b8133
use binary encoding of keys to reduce size of QR code
uhoreg Feb 6, 2020
405ac1e
add base32 option
uhoreg Feb 19, 2020
c77d04c
add base64 option
uhoreg Feb 19, 2020
ea0abe9
remove incorrect stuff
uhoreg Feb 19, 2020
a7279d9
Update proposals/1543-qr_code_key_verification.md
uhoreg Feb 27, 2020
7b3c98c
we're using the binary format
uhoreg Oct 17, 2020
0b97ac5
event IDs use $
uhoreg Nov 19, 2020
9db8cc9
Update proposals/1543-qr_code_key_verification.md
uhoreg Nov 21, 2020
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
188 changes: 188 additions & 0 deletions proposals/1543-qr_code_key_verification.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
Key verification using QR codes
===============================

Problem/Background
------------------

Key verification is essential in ensuring that end-to-end encrypted messages
cannot be read by unauthorized parties. Traditionally, key verification is
done by comparing long strings. To save users from the tedium of reading out
long strings, some systems allow one party to verify the other party by
scanning a QR code; by doing this twice, both parties can verify each other.
In this proposal, we present a method for both parties to verify each other by
only scanning one QR code.

Proposal
--------

When Alice and Bob meet in person to verify keys, Alice will scan a QR code
generated by Bob's device. The QR code will encode both Bob's key as well as what Bob
uhoreg marked this conversation as resolved.
Show resolved Hide resolved
thinks Alice's key is. When Alice scans the QR code, she will ensure that the
keys match what is expected, in which case, she relays this information to Bob,
who can then tell his device that the keys match.

Example flow:

1. Alice and Bob meet in person, and want to verify each other's keys.
2. Alice requests a key verification through her device by sending an
`m.key.verification.request` message (see
[MSC2241](https://github.com/matrix-org/matrix-doc/pull/2241)), with
`m.qr_code.show.v1`, `m.qr_code.scan.v1`, and `m.reciprocate.v1` listed in
`methods`.
3. Alice's client displays a QR code that Bob is able to scan, and an option to
uhoreg marked this conversation as resolved.
Show resolved Hide resolved
scan Bob's QR code.
4. Bob's client prompts Bob to verify Alice's key. The prompt includes a QR
code that Alice can scan (if the `m.key.verification.request` message listed
`m.qr_code.scan.v1`), and an option to scan Alice's QR code (if the
`m.key.verification.request` message listed `m.qr_code.show.v1`). The QR
code encodes:
- Bob's Matrix user ID,
- Bob's keys that he wants Alice to verify (should contain at least his
master cross-signing key),
- what Bob thinks Alice's master cross-signing key is,
- a random shared secret.
5. Alice scans Bob's QR code.
6. Alice's device ensures that:
- the user ID in the QR code is the same as the expected user ID (which it
knows because it is the recipient of her `m.key.verification.request`
message),
- Bob's keys encoded in the QR code match the keys that she already has for
Bob, and
- Alice's cross-signing key matches the cross-signing key encoded in the QR
code.

If any of these checks fail, Alice's device displays an error message
indicating that the code is incorrect, and sends a
`m.key.verification.cancel` message to Bob's device.

Otherwise, at this point, Alice's device has now verified Bob's key, and her
device will display a message saying that all is well.
7. Alice's device sends a `m.key.verification.start` message with `method` set
uhoreg marked this conversation as resolved.
Show resolved Hide resolved
to `m.reciprocate.v1` to Bob (see below). The message includes the shared
secret from the QR code.
8. Upon receipt of the `m.key.verification.start` message, Bob's device ensures
that the shared secret matches, and if so, presents a button for him to press
/after/ he has checked that Alice's device says that things match, and a
button for him to press if Alice's device indicates that the QR code is
invalid or if Alice has not yet scanned. If the shared secret does not
match, it should display an error message indicating that an attack was
attempted. (This does not affect Alice's verification of Bob's keys.)
9. Bob sees Alice's device confirm that the key matches, and presses the button
Copy link
Member

@ara4n ara4n Jan 24, 2020

Choose a reason for hiding this comment

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

If the m.key.verification.start isn't encrypted/signed, isn't there an attack where an evil HS admin called Eve shouldersurfs Bob's QR code and then MITMs Alice's reciprocate msg?

  • Bob shows his QR code
  • Eve scans it.
  • Alice scans it, and sends the reciprocate msg to Bob
  • Eve intercepts the reciprocate msg, dropping Alice's and replacing it with her own (using the same secret)
  • Bob confirms that Alice has indeed scanned him successfully
  • Bob trusts Eve.

I think there's also a variation of this where Eve doesn't MITM the reciprocate but just sends her own - but times it right so that Bob gets confused and thinks Alice did scan him when it was actually Eve, and hits the "confirm" button (to Eve's horror) and gets pwned.

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 reciprocate message doesn't affect what key that Bob trusts. The only way that Bob would trust Eve is if Bob's server sent Eve's key to Bob when he asks for Alice's key. In this case, the QR code that Bob shows to Alice will contain Eve's key rather than Alice's key. But then, when Alice scans the QR code, she will notice that the QR code has the wrong key, and her device will display an error message. Unless Alice manages to move her device away from in front of Bob's device faster than her device can compare a few strings (i.e. within a couple milliseconds), her device will display an error before Bob can react to his devices prompting him to verify.

Copy link
Member

Choose a reason for hiding this comment

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

oh right - the penny finally dropped; for my notes (and anyone else ever reading this): we're just confirming that Bob's copy of the keys matches Alice's copy of the keys, by sending them out-of-band via QR from Bob to Alice, having Alice compare them, and then if Alice says she's happy, Bob infers he must be happy too. The secret is just there to make it harder for Eve to spoof a reciprocate message to try to cause confusion (although if she colludes with the HS admin, she can MITM the secret anyway). (@uhoreg, is this right?)

So the actual worst-case scenario attack here is:

  • Eve makes Bob's server send him Eve's keys rather than Alice's
  • Bob shows his QR code
  • Eve shoulder-surfs it to get the secret
  • Alice is faffing around trying to scan Bob's QR code
  • Eve spoofs the reciprocate message with that secret from Alice to Bob
  • Bob sees a big green button appear, assumes that Alice must have scanned it successfully, yanks his phone away before Alice can protest, and blindly hits 'ok', trusts Eve, who immediately keyshare requests all his megolm keys.
  • ...or... Alice's phone manages to scan the compromised code, shows a big red "you're under attack" warning, but this races with the spoofed reciprocate message to Bob, who sees a big green button and hits "ok", before he registers Alice's panicking noises.

The fact they can know they've been pwned and revoke Eve is not much use if she's already stolen history or SSSS keys etc.

It feels like there's a concrete risk of this attack being viable.

Assuming i've got it right, this time, is there an equivalent attack for SAS verif? If not, this feels like another slight advantage in favour of showing SAS codes in QR rather than the blunt keys.

Copy link
Member Author

Choose a reason for hiding this comment

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

SAS-over-QR would have a similar issue. With SAS, Alice and Bob both need to check that the emoji match, and they need to hit the confirm button. With SAS-over-QR, Alice would be in charge of making sure that the QR code matches what's expected, and then telling Bob whether to hit the OK or the Panic button, so if we're worried about Bob hitting the OK button before Alice says whether it's OK or not, then we get the same thing.

Perhaps instead of presenting it as a "Confirm" or "Panic", we can have Bob's device, when it receives the "reciprocate" message, say "Did Alice successfully scan the code? Yes/No", which at least will indicate that Bob should ask Alice for the verdict rather than just blindly hitting "OK".

on his device to indicate that Alice's key is verified.
10. Both devices send an `m.key.verification.done` message.

### Verification methods

This proposal defines three verification methods that can be used in
`m.key.verification.request` messages (see
[MSC2241](https://github.com/matrix-org/matrix-doc/pull/2241)).

- `m.qr_code.show.v1`: means that the sender of the
`m.key.verification.request` message can show a QR code that the recipient
can scan. If the recipient can scan the QR code, it should allow the user to
do so. This method is never sent as part of a `m.key.verification.start`
message.
- `m.qr_code.scan.v1`: means that the sender of the
`m.key.verification.request` message can scan a QR code displayed by the
recipient. If the recipient can display a QR code, it should allow the user
to display it so that the sender can scan it. This method is never sent as
part of a `m.key.verification.start` message.
- `m.reciprocate.v1`: means that the sender can participate in a reciprocal
verification, either as initiator or responder, as described in the [Message
types](#message-types) section below.

### QR code format

The QR codes to be displayed and scanned using this format will encode URLs of
the form:
`https://matrix.to/#/<user-id>?request=<event-id>&action=verify&key_<keyid>=<key-in-base64>...&secret=<shared-secret>&other_user_key=<master-key-in-base64>`
(when `matrix:` URLs are specced, this will be used instead).

- `request`: is the event ID of the associated verification request event.
uhoreg marked this conversation as resolved.
Show resolved Hide resolved
- `key_<key_id>`: each key that the user wants verified will have an entry of
this form, where the value is the key in unpadded base64. The QR code should
contain at least the user's master cross-signing key.
- `secret`: is a random single-use shared secret in unpadded base64. It must be
uhoreg marked this conversation as resolved.
Show resolved Hide resolved
at least 256-bits long (43 characters when base64-encoded).
- `other_user_key`: the other user's master cross-signing key, in unpadded
base64. In other words, if Alice is displaying the QR code, this would be
the copy of Bob's master cross-signing key that Alice has.

The QR codes to be displayed and scanned, which are not a part of an in-person
verification (for example, for printing on business cards), will encode URLs of
the form:
`https://matrix.to/#/<user-id>?action=verify&key_<keyid>=<key-in-base64>...`
In this case, only the user scanning the QR code will verify the key of the
user whose QR code was scanned; bi-directional verification is not possible.

### Message types

#### `m.key.verification.start`

Alice's device tells Bob's device that the keys are verified. The request is
MAC'ed using the verification algorithm and verification key from the QR code.

message contents:

- `method`: `m.reciprocate.v1`
- `m.relates_to`: as per [key verification framework](https://github.com/matrix-org/matrix-doc/pull/2241)
- `secret`: the shared secret from the QR code

Example:

```json
{
"method": "m.reciprocate.v1",
"m.relates_to": {
"rel_type": "m.reference",
"event_id": "!event_id_of_verification_request"
uhoreg marked this conversation as resolved.
Show resolved Hide resolved
},
"secret": "shared+secret"
}
```

Note that this message could be sent by either the sender or the recipient of
the `m.key.verification.request` message, depending on which user scanned the
QR code.

### Cancellation

In addition to the cancellation codes specified in [the spec for
`m.key.verification.cancel`](https://matrix.org/docs/spec/client_server/r0.5.0#m-key-verification-cancel),
the following cancellation codes may be used:

- `m.qr_code.invalid`: The QR code is invalid (e.g. it is not a URL of the
required form)

The verification can also be cancelled with the error codes:

- `m.key_mismatch`: if the QR code has keys that do not match the expected
value
- `m.user_mismatch`: if the QR code is for a different user from what was expected

Tradeoffs/Alternatives
----------------------

Other methods of verifying keys, which do not require scanning QR codes, are
needed for devices that are unable to scan QR codes. One such method is
[MSC1267](https://github.com/matrix-org/matrix-doc/issues/1267).

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

The first check in Step 6 in the example flow is to ensure that Bob does not
present a QR code claiming to be Carol's key. Without this check, Bob will be
able to trick Alice into verifying a key under his control, and evesdropping on
Alice's communications with Carol.

The security of verifying Alice's key depends on Bob not hitting the "Verified"
button (step 9 in the example flow) until after Alice's device indicates
success or failure. Users have a tendency to click on buttons without reading
what the screen says, but this is partially mitigated by the fact that it is
unlikely that Bob will be interacting with the device while Alice is scanning
and Alice's device will display the verification results immediately upon
scanning. Also, Bob's device will not display the button until it receives the
`m.key.verification.start` message that contains the shared secret from the QR
code, which means that an attacker would need to be physically present while
Alice and Bob verify. This issue can also be addressed by allowing Bob to
easily undo the verification if Alice's device displays an error.