Skip to content

Commit bce1bf3

Browse files
authored
Merge pull request #1544 from uhoreg/qr_key_verification
MSC1544: Key verification using QR codes
2 parents 940bb49 + 9db8cc9 commit bce1bf3

File tree

1 file changed

+297
-0
lines changed

1 file changed

+297
-0
lines changed
Lines changed: 297 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,297 @@
1+
Bi-directional Key verification using QR codes
2+
==============================================
3+
4+
Problem/Background
5+
------------------
6+
7+
Key verification is essential in ensuring that end-to-end encrypted messages
8+
cannot be read by unauthorized parties. Traditionally, key verification is
9+
done by comparing long strings. To save users from the tedium of reading out
10+
long strings, some systems allow one party to verify the other party by
11+
scanning a QR code; by doing this twice, both parties can verify each other.
12+
In this proposal, we present a method for both parties to verify each other by
13+
only scanning one QR code.
14+
15+
Proposal
16+
--------
17+
18+
When Alice and Bob meet in person to verify keys, Alice will scan a QR code
19+
generated by Bob's device. The QR code will encode both Bob's key as well as what Bob
20+
thinks Alice's key is. When Alice scans the QR code, she will ensure that the
21+
keys match what is expected, in which case, she relays this information to Bob,
22+
who can then tell his device that the keys match.
23+
24+
### Example flow
25+
26+
1. Alice and Bob meet in person, and want to verify each other's keys.
27+
2. Alice requests a key verification through her device by sending an
28+
`m.key.verification.request` message (see
29+
[MSC2241](https://github.com/matrix-org/matrix-doc/pull/2241)), with
30+
`m.qr_code.show.v1`, `m.qr_code.scan.v1`, and `m.reciprocate.v1` listed in
31+
`methods`, and Bob responds with a `m.key.verification.ready` message.
32+
3. Alice's client displays a QR code that Bob is able to scan, and an option to
33+
scan Bob's QR code.
34+
4. Bob's client prompts Bob to verify Alice's key. The prompt includes a QR
35+
code that Alice can scan (if the `m.key.verification.request` message listed
36+
`m.qr_code.scan.v1`), and an option to scan Alice's QR code (if the
37+
`m.key.verification.request` message listed `m.qr_code.show.v1`). The QR
38+
code encodes:
39+
- Bob's master cross-signing public key,
40+
- what Bob thinks Alice's master cross-signing public key is,
41+
- a random shared secret.
42+
5. Alice scans Bob's QR code.
43+
6. Alice's device ensures that:
44+
- Bob's key encoded in the QR code matches the key that she already has for
45+
Bob, and
46+
- Alice's cross-signing key matches the cross-signing key encoded in the QR
47+
code.
48+
49+
If any of these checks fail, Alice's device displays an error message
50+
indicating that the code is incorrect, and sends a
51+
`m.key.verification.cancel` message to Bob's device.
52+
53+
Otherwise, at this point:
54+
- Alice's device has now verified Bob's key, and
55+
- Alice's device knows that Bob has the correct key for her.
56+
57+
Thus for Bob to verify Alice's key, Alice needs to tell Bob that he has the
58+
right key.
59+
7. Alice's device displays a message saying that all is well. This message
60+
tells Alice that she has the right key for Bob, and tells Bob that he has
61+
the right key for Alice.
62+
8. Alice's device sends a `m.key.verification.start` message with `method` set
63+
to `m.reciprocate.v1` to Bob (see below). The message includes the shared
64+
secret from the QR code. This signals to Bob's device that Alice has
65+
scanned Bob's QR code.
66+
67+
This message is merely a signal for Bob's device to proceed to the next
68+
step, and is not used for verification purposes.
69+
9. Upon receipt of the `m.key.verification.start` message, Bob's device ensures
70+
that the shared secret matches.
71+
72+
If the shared secret does not match, it should display an error message
73+
indicating that an attack was attempted. (This does not affect Alice's
74+
verification of Bob's keys.)
75+
76+
If the shared secret does match, it asks Bob to confirm that Alice
77+
has scanned the QR code.
78+
10. Bob sees Alice's device confirm that the key matches, and presses the button
79+
on his device to indicate that Alice's key is verified.
80+
81+
Bob's verification of Alice's key hinges on Alice telling Bob the result of
82+
her scan. Since the QR code includes what Bob thinks Alice's key is,
83+
Alice's device can check whether Bob has the right key for her. Alice has
84+
no motivation to lie about the result, as getting Bob to trust an incorrect
85+
key would only affect communications between herself and Bob. Thus Alice
86+
telling Bob that the code was scanned successfully is sufficient for Bob to
87+
trust Alice's key, under the assumption that this communication is done
88+
over a trusted medium (such as in-person).
89+
11. Both devices send an `m.key.verification.done` message.
90+
91+
This flow allows Alice to verify Bob's key, and Bob to verify Alice's key.
92+
Alice verifies Bob's key because she can trust the QR code that Bob displays
93+
for her, as this is done over a trusted medium. Bob verifies Alice's key
94+
because Alice can trust the QR code that Bob displays, and Bob can trust Alice
95+
to tell him the result of the verification.
96+
97+
#### Self-verification
98+
99+
QR codes can also be used by a user to verify their own devices. These examples
100+
shows Alice verifying two devices, one of them (Osborne2) having cross-signing
101+
already set up, and the other one (Dynabook) having just logged in.
102+
103+
In the first example, Osborne2 scans Dynabook:
104+
105+
1. Alice logs into her new Dynabook and wants other users to be able to trust
106+
it via cross-signing, and to trust other devices via cross-signing.
107+
2. Dynabook retrieves Alice's public cross-signing key from the server, and
108+
displays a QR code that encodes:
109+
- Dynabook's device key,
110+
- what it thinks Alice's master key is, and
111+
- a random shared secret.
112+
113+
Note that in this case, the QR code does not include Alice's master key in a
114+
`key_<key_id>` parameter, since Dynabook does not know whether it is trusted
115+
or not.
116+
3. Osborne2 scans the QR code displayed by Dynabook. At this point, Osborne2
117+
knows Dynabook's device key and can sign it with the self-signing key and
118+
upload the signature, and can trust Dynabook for sending secrets via SSSS.
119+
It also knows that Dynabook has the correct cross-signing key.
120+
4. Osborne2 tells Alice that the scan was successful, and sends the
121+
`reciprocate` message containing the shared secret.
122+
5. Upon receipt of the `reciprocate` message, Dynabook (after checking the
123+
shared secret) confirms with Alice that she successfully scanned the QR
124+
code.
125+
6. Alice confirms.
126+
7. Dynabook now knows that it can trust Alice's cross-signing keys that it
127+
fetched from the server.
128+
129+
In the second example, Dynabook scans Osborne2:
130+
131+
1. Alice logs into her new Dynabook and wants other users to be able to trust
132+
it via cross-signing, and to trust other devices via cross-signing.
133+
2. Osborne2 notices that Dynabook is a new device. Osborne2 fetches Dynabook's
134+
identity key and displays a QR code that encodes:
135+
- what it thinks Dynabook's key is,
136+
- Alice's master key, and
137+
- a random shared secret.
138+
3. Dynabook scans the QR code shown by Osborne2. At this point, Dynabook knows
139+
Alice's cross-signing key, and so it can trust it to sign other devices. It
140+
also knows that Osborne2 as the correct key for it.
141+
4. Dynabook tells Alice that the scan is successful, and sends the
142+
`reciprocate` message containing the shared secret.
143+
5. Upon receipt of the `reciprocate` message, Osborne2 (after checking the
144+
shared secret) confirms with Alice that she successfully scanned the QR
145+
code.
146+
6. Alice confirms.
147+
7. Osborne2 now knows that it has the correct device key for Dynabook, and can
148+
sign it with the self-signing key and upload the signature. Osborne2 can
149+
also trust Dynabook for sending secrets via SSSS.
150+
151+
### Verification methods
152+
153+
This proposal defines three verification methods that can be used in
154+
`m.key.verification.request` messages (see
155+
[MSC2241](https://github.com/matrix-org/matrix-doc/pull/2241)).
156+
157+
- `m.qr_code.show.v2`: means that the sender of the
158+
`m.key.verification.request` message can show a QR code that the recipient
159+
can scan. If the recipient can scan the QR code, it should allow the user to
160+
do so. This method is never sent as part of a `m.key.verification.start`
161+
message.
162+
- `m.qr_code.scan.v2`: means that the sender of the
163+
`m.key.verification.request` message can scan a QR code displayed by the
164+
recipient. If the recipient can display a QR code, it should allow the user
165+
to display it so that the sender can scan it. This method is never sent as
166+
part of a `m.key.verification.start` message.
167+
- `m.reciprocate.v1`: means that the sender can participate in a reciprocal
168+
verification, either as initiator or responder, as described in the [Message
169+
types](#message-types) section below.
170+
171+
### QR code format
172+
173+
The QR codes to be displayed and scanned using this format will encode binary
174+
strings in the general form:
175+
176+
- the ASCII string "MATRIX"
177+
- one byte indicating the QR code version (must be `0x02`)
178+
- one byte indicating the QR code verification mode. May be one of the
179+
following values:
180+
- `0x00` verifying another user with cross-signing
181+
- `0x01` self-verifying in which the current device does trust the master key
182+
- `0x02` self-verifying in which the current device does not yet trust the
183+
master key
184+
- the event ID or `transaction_id` of the associated verification
185+
request event, encoded as:
186+
- two bytes in network byte order (big-endian) indicating the length in
187+
bytes of the ID as a UTF-8 string
188+
- the ID as a UTF-8 string
189+
- the first key, as 32 bytes. The key to use depends on the mode field:
190+
- if `0x00` or `0x01`, then the current user's own master cross-signing public key
191+
- if `0x02`, then the current device's device key
192+
- the second key, as 32 bytes. The key to use depends on the mode field:
193+
- if `0x00`, then what the device thinks the other user's master
194+
cross-signing key is
195+
- if `0x01`, then what the device thinks the other device's device key is
196+
- if `0x02`, then what the device thinks the user's master cross-signing key
197+
is
198+
- a random shared secret, as a byte string. It is suggested to use a secret
199+
that is about 8 bytes long. Note: as we do not share the length of the
200+
secret, and it is not a fixed size, clients will just use the remainder of
201+
binary string as the shared secret.
202+
203+
For example, if Alice displays a QR code encoding the following binary string:
204+
205+
```
206+
"MATRIX" |ver|mode| len | event ID
207+
4D 41 54 52 49 58 02 00 00 2D 21 41 42 43 44 ...
208+
| user's cross-signing key | other user's cross-signing key | shared secret
209+
00 01 02 03 04 05 06 07 ... 10 11 12 13 14 15 16 17 ... 20 21 22 23 24 25 26 27
210+
```
211+
212+
this indicates that Alice is verifying another user (say Bob), in response to
213+
the request from event "$ABCD...", her cross-signing key is
214+
`0001020304050607...` (which is "AAECAwQFBg..." in base64), she thinks that
215+
Bob's cross-signing key is `1011121314151617...` (which is "EBESExQVFh..." in
216+
base64), and the shared secret is `2021222324252627` (which is "ICEiIyQlJic" in
217+
base64).
218+
219+
### Message types
220+
221+
#### `m.key.verification.start`
222+
223+
Alice's device tells Bob's device that the QR code has been scanned.
224+
225+
message contents:
226+
227+
- `method`: `m.reciprocate.v1`
228+
- `m.relates_to`: as per [key verification framework](https://github.com/matrix-org/matrix-doc/pull/2241)
229+
- `secret`: the shared secret from the QR code, encoded using unpadded base64
230+
231+
Example:
232+
233+
```json
234+
{
235+
"method": "m.reciprocate.v1",
236+
"m.relates_to": {
237+
"rel_type": "m.reference",
238+
"event_id": "$event_id_of_verification_request"
239+
},
240+
"secret": "shared+secret"
241+
}
242+
```
243+
244+
Note that this message could be sent by either the sender or the recipient of
245+
the `m.key.verification.request` message, depending on which user scanned the
246+
QR code.
247+
248+
### Cancellation
249+
250+
In addition to the cancellation codes specified in [the spec for
251+
`m.key.verification.cancel`](https://matrix.org/docs/spec/client_server/r0.5.0#m-key-verification-cancel),
252+
the following cancellation codes may be used:
253+
254+
- `m.qr_code.invalid`: The QR code is invalid (e.g. it is not a URL of the
255+
required form)
256+
257+
The verification can also be cancelled with the error codes:
258+
259+
- `m.key_mismatch`: if the QR code has keys that do not match the expected
260+
value
261+
- `m.user_mismatch`: if the QR code is for a different user from what was expected
262+
263+
Tradeoffs/Alternatives
264+
----------------------
265+
266+
Other methods of verifying keys, which do not require scanning QR codes, are
267+
needed for devices that are unable to scan QR codes. One such method is
268+
[MSC1267](https://github.com/matrix-org/matrix-doc/issues/1267). Since the key
269+
verification framework allows for multiple methods to be supported, clients can
270+
allow users to use different methods depending on their capability.
271+
272+
Rather than embedding the keys in the QR codes directly, the two clients could
273+
perform an exchange similar to
274+
[MSC1267](https://github.com/matrix-org/matrix-doc/issues/1267), and encoding
275+
the Short Authentication String code in the QR code. However, this means that
276+
the clients must exchange several messages before they can verify each other,
277+
which would delay showing the QR codes. This proposal is also simpler to
278+
implement.
279+
280+
This proposal does not support the case of asynchronous verification, such as
281+
printing a QR code on a business card for others to scan. That may be address
282+
in a separate MSC.
283+
284+
Security Considerations
285+
-----------------------
286+
287+
The security of verifying Alice's key depends on Bob not hitting the "Verified"
288+
button (step 10 in the example flow) until after Alice's device indicates
289+
success or failure. Users have a tendency to click on buttons without reading
290+
what the screen says, but this is partially mitigated by the fact that it is
291+
unlikely that Bob will be interacting with the device while Alice is scanning
292+
and Alice's device will display the verification results immediately upon
293+
scanning. Also, Bob's device will not display the button until it receives the
294+
`m.key.verification.start` message that contains the shared secret from the QR
295+
code, which means that an attacker would need to be physically present while
296+
Alice and Bob verify. This issue can also be addressed by allowing Bob to
297+
easily undo the verification if Alice's device displays an error.

0 commit comments

Comments
 (0)