Merge branch 'master' into travis/msc/global-versioning
commit
8d6642aaa7
@ -0,0 +1 @@
|
|||||||
|
Fix various typos throughout the specification.
|
@ -0,0 +1 @@
|
|||||||
|
Document how clients can advise recipients that it is withholding decryption keys as per `MSC2399 <https://github.com/matrix-org/matrix-doc/pull/2399>`_.
|
@ -0,0 +1 @@
|
|||||||
|
Fix various typos throughout the specification.
|
@ -0,0 +1 @@
|
|||||||
|
Fix various typos throughout the specification.
|
@ -0,0 +1 @@
|
|||||||
|
Fix various typos throughout the specification.
|
@ -0,0 +1 @@
|
|||||||
|
Fix various typos throughout the specification.
|
@ -0,0 +1 @@
|
|||||||
|
Fix various typos throughout the specification.
|
@ -0,0 +1,66 @@
|
|||||||
|
{
|
||||||
|
"Pin": "Кабърче",
|
||||||
|
"Folder": "Папка",
|
||||||
|
"Headphones": "Слушалки",
|
||||||
|
"Anchor": "Котва",
|
||||||
|
"Bell": "Звънец",
|
||||||
|
"Trumpet": "Тромпет",
|
||||||
|
"Guitar": "Китара",
|
||||||
|
"Ball": "Топка",
|
||||||
|
"Trophy": "Трофей",
|
||||||
|
"Rocket": "Ракета",
|
||||||
|
"Aeroplane": "Самолет",
|
||||||
|
"Bicycle": "Колело",
|
||||||
|
"Train": "Влак",
|
||||||
|
"Flag": "Флаг",
|
||||||
|
"Telephone": "Телефон",
|
||||||
|
"Hammer": "Чук",
|
||||||
|
"Key": "Ключ",
|
||||||
|
"Lock": "Катинар",
|
||||||
|
"Scissors": "Ножици",
|
||||||
|
"Paperclip": "Кламер",
|
||||||
|
"Pencil": "Молив",
|
||||||
|
"Book": "Книга",
|
||||||
|
"Light Bulb": "Лампа",
|
||||||
|
"Gift": "Подарък",
|
||||||
|
"Clock": "Часовник",
|
||||||
|
"Hourglass": "Пясъчен часовник",
|
||||||
|
"Umbrella": "Чадър",
|
||||||
|
"Thumbs Up": "Палец нагоре",
|
||||||
|
"Santa": "Дядо Коледа",
|
||||||
|
"Spanner": "Гаечен ключ",
|
||||||
|
"Glasses": "Очила",
|
||||||
|
"Hat": "Шапка",
|
||||||
|
"Robot": "Робот",
|
||||||
|
"Smiley": "Усмивка",
|
||||||
|
"Heart": "Сърце",
|
||||||
|
"Cake": "Торта",
|
||||||
|
"Pizza": "Пица",
|
||||||
|
"Corn": "Царевица",
|
||||||
|
"Strawberry": "Ягода",
|
||||||
|
"Apple": "Ябълка",
|
||||||
|
"Banana": "Банан",
|
||||||
|
"Fire": "Огън",
|
||||||
|
"Cloud": "Облак",
|
||||||
|
"Moon": "Луна",
|
||||||
|
"Globe": "Глобус",
|
||||||
|
"Mushroom": "Гъба",
|
||||||
|
"Cactus": "Кактус",
|
||||||
|
"Tree": "Дърво",
|
||||||
|
"Flower": "Цвете",
|
||||||
|
"Butterfly": "Пеперуда",
|
||||||
|
"Octopus": "Октопод",
|
||||||
|
"Fish": "Риба",
|
||||||
|
"Turtle": "Костенурка",
|
||||||
|
"Penguin": "Пингвин",
|
||||||
|
"Rooster": "Петел",
|
||||||
|
"Panda": "Панда",
|
||||||
|
"Rabbit": "Заек",
|
||||||
|
"Elephant": "Слон",
|
||||||
|
"Pig": "Прасе",
|
||||||
|
"Unicorn": "Еднорог",
|
||||||
|
"Horse": "Кон",
|
||||||
|
"Lion": "Лъв",
|
||||||
|
"Cat": "Котка",
|
||||||
|
"Dog": "Куче"
|
||||||
|
}
|
@ -0,0 +1,66 @@
|
|||||||
|
{
|
||||||
|
"Cactus": "Cactus",
|
||||||
|
"Globe": "Globus terraqüi",
|
||||||
|
"Rooster": "Gall",
|
||||||
|
"Pin": "Xinxeta",
|
||||||
|
"Folder": "Carpeta",
|
||||||
|
"Headphones": "Auriculars",
|
||||||
|
"Anchor": "Àncora",
|
||||||
|
"Bell": "Campana",
|
||||||
|
"Trumpet": "Trompeta",
|
||||||
|
"Guitar": "Guitarra",
|
||||||
|
"Ball": "Pilota",
|
||||||
|
"Trophy": "Trofeu",
|
||||||
|
"Rocket": "Coet",
|
||||||
|
"Aeroplane": "Avió",
|
||||||
|
"Bicycle": "Bicicleta",
|
||||||
|
"Train": "Tren",
|
||||||
|
"Flag": "Bandera",
|
||||||
|
"Telephone": "Telèfon",
|
||||||
|
"Hammer": "Martell",
|
||||||
|
"Lock": "Cadenat",
|
||||||
|
"Key": "Clau",
|
||||||
|
"Scissors": "Tisores",
|
||||||
|
"Paperclip": "Clip",
|
||||||
|
"Pencil": "Llapis",
|
||||||
|
"Book": "Llibre",
|
||||||
|
"Light Bulb": "Bombeta",
|
||||||
|
"Gift": "Regal",
|
||||||
|
"Clock": "Rellotge",
|
||||||
|
"Hourglass": "Rellotge de sorra",
|
||||||
|
"Umbrella": "Paraigües",
|
||||||
|
"Thumbs Up": "Polzes amunt",
|
||||||
|
"Santa": "Pare Noél",
|
||||||
|
"Spanner": "Clau anglesa",
|
||||||
|
"Glasses": "Ulleres",
|
||||||
|
"Hat": "Barret",
|
||||||
|
"Robot": "Robot",
|
||||||
|
"Smiley": "Somrient",
|
||||||
|
"Heart": "Cor",
|
||||||
|
"Cake": "Pastís",
|
||||||
|
"Pizza": "Pizza",
|
||||||
|
"Corn": "Blat de moro",
|
||||||
|
"Strawberry": "Maduixa",
|
||||||
|
"Apple": "Poma",
|
||||||
|
"Banana": "Plàtan",
|
||||||
|
"Fire": "Foc",
|
||||||
|
"Cloud": "Núvol",
|
||||||
|
"Moon": "Lluna",
|
||||||
|
"Mushroom": "Bolet",
|
||||||
|
"Tree": "Arbre",
|
||||||
|
"Flower": "Flor",
|
||||||
|
"Butterfly": "Papallona",
|
||||||
|
"Octopus": "Pop",
|
||||||
|
"Fish": "Peix",
|
||||||
|
"Turtle": "Tortuga",
|
||||||
|
"Penguin": "Pingüí",
|
||||||
|
"Panda": "Panda",
|
||||||
|
"Rabbit": "Conill",
|
||||||
|
"Elephant": "Elefant",
|
||||||
|
"Unicorn": "Unicorn",
|
||||||
|
"Pig": "Porc",
|
||||||
|
"Horse": "Cavall",
|
||||||
|
"Lion": "Lleó",
|
||||||
|
"Cat": "Gat",
|
||||||
|
"Dog": "Gos"
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"$ref": "core/event.json",
|
||||||
|
"type": "m.room_key.withheld",
|
||||||
|
"content": {
|
||||||
|
"algorithm": "m.megolm.v1.aes-sha2",
|
||||||
|
"room_id": "!Cuyf34gef24t:localhost",
|
||||||
|
"session_id": "X3lUlvLELLYxeTx4yOVu6UDpasGEVO0Jbu+QFnm0cKQ",
|
||||||
|
"sender_key": "RF3s+E7RkTQTGF2d8Deol0FkQvgII2aJDf3/Jp5mxVU",
|
||||||
|
"code": "m.unverified",
|
||||||
|
"reason": "Device not verified"
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,86 @@
|
|||||||
|
---
|
||||||
|
allOf:
|
||||||
|
- $ref: core-event-schema/event.yaml
|
||||||
|
|
||||||
|
description: |-
|
||||||
|
This event type is used to indicate that the sender is not sharing room keys
|
||||||
|
with the recipient. It is sent as a to-device event.
|
||||||
|
|
||||||
|
Possible values for ``code`` include:
|
||||||
|
|
||||||
|
* ``m.blacklisted``: the user/device was blacklisted.
|
||||||
|
* ``m.unverified``: the user/device was not verified, and the sender is only
|
||||||
|
sharing keys with verified users/devices.
|
||||||
|
* ``m.unauthorised``: the user/device is not allowed to have the key. For
|
||||||
|
example, this could be sent in response to a key request if the user/device
|
||||||
|
was not in the room when the original message was sent.
|
||||||
|
* ``m.unavailable``: sent in reply to a key request if the device that the
|
||||||
|
key is requested from does not have the requested key.
|
||||||
|
* ``m.no_olm``: an olm session could not be established.
|
||||||
|
|
||||||
|
In most cases, this event refers to a specific room key. The one exception to
|
||||||
|
this is when the sender is unable to establish an olm session with the
|
||||||
|
recipient. When this happens, multiple sessions will be affected. In order
|
||||||
|
to avoid filling the recipient\'s device mailbox, the sender should only send
|
||||||
|
one ``m.room_key.withheld`` message with no ``room_id`` nor ``session_id``
|
||||||
|
set. If the sender retries and fails to create an olm session again in the
|
||||||
|
future, it should not send another ``m.room_key.withheld`` message with a
|
||||||
|
``code`` of ``m.no_olm``, unless another olm session was previously
|
||||||
|
established successfully. In response to receiving an
|
||||||
|
``m.room_key.withheld`` message with a ``code`` of ``m.no_olm``, the
|
||||||
|
recipient may start an olm session with the sender and send an ``m.dummy``
|
||||||
|
message to notify the sender of the new olm session. The recipient may
|
||||||
|
assume that this ``m.room_key.withheld`` message applies to all encrypted
|
||||||
|
room messages sent before it receives the message.
|
||||||
|
properties:
|
||||||
|
content:
|
||||||
|
properties:
|
||||||
|
algorithm:
|
||||||
|
type: string
|
||||||
|
enum: ["m.megolm.v1.aes-sha2"]
|
||||||
|
description: |-
|
||||||
|
The encryption algorithm for the key that this event is about.
|
||||||
|
room_id:
|
||||||
|
type: string
|
||||||
|
description: |-
|
||||||
|
Required if ``code`` is not ``m.no_olm``. The room for the key that
|
||||||
|
this event is about.
|
||||||
|
session_id:
|
||||||
|
type: string
|
||||||
|
description: |-
|
||||||
|
Required of ``code`` is not ``m.no_olm``. The session ID of the key
|
||||||
|
that this event is aboutis for.
|
||||||
|
sender_key:
|
||||||
|
type: string
|
||||||
|
description: |-
|
||||||
|
The unpadded base64-encoded device curve25519 key of the event\'s
|
||||||
|
sender.
|
||||||
|
code:
|
||||||
|
type: string
|
||||||
|
enum:
|
||||||
|
- m.blacklisted
|
||||||
|
- m.unverified
|
||||||
|
- m.unauthorised
|
||||||
|
- m.unavailable
|
||||||
|
- m.no_olm
|
||||||
|
description: |-
|
||||||
|
A machine-readable code for why the key was not sent. Codes beginning
|
||||||
|
with `m.` are reserved for codes defined in the Matrix
|
||||||
|
specification. Custom codes must use the Java package naming
|
||||||
|
convention.
|
||||||
|
reason:
|
||||||
|
type: string
|
||||||
|
description: |-
|
||||||
|
A human-readable reason for why the key was not sent. The receiving
|
||||||
|
client should only use this string if it does not understand the
|
||||||
|
``code``.
|
||||||
|
required:
|
||||||
|
- algorithm
|
||||||
|
- sender_key
|
||||||
|
- code
|
||||||
|
type: object
|
||||||
|
type:
|
||||||
|
enum:
|
||||||
|
- m.room_key.withheld
|
||||||
|
type: string
|
||||||
|
type: object
|
@ -0,0 +1,297 @@
|
|||||||
|
Bi-directional 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
|
||||||
|
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`, and Bob responds with a `m.key.verification.ready` message.
|
||||||
|
3. Alice's client displays a QR code that Bob is able to scan, and an option to
|
||||||
|
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 master cross-signing public key,
|
||||||
|
- what Bob thinks Alice's master cross-signing public key is,
|
||||||
|
- a random shared secret.
|
||||||
|
5. Alice scans Bob's QR code.
|
||||||
|
6. Alice's device ensures that:
|
||||||
|
- Bob's key encoded in the QR code matches the key 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
|
||||||
|
- Alice's device knows that Bob has the correct key for her.
|
||||||
|
|
||||||
|
Thus for Bob to verify Alice's key, Alice needs to tell Bob that he has the
|
||||||
|
right key.
|
||||||
|
7. Alice's device displays a message saying that all is well. This message
|
||||||
|
tells Alice that she has the right key for Bob, and tells Bob that he has
|
||||||
|
the right key for Alice.
|
||||||
|
8. Alice's device sends a `m.key.verification.start` message with `method` set
|
||||||
|
to `m.reciprocate.v1` to Bob (see below). The message includes the shared
|
||||||
|
secret from the QR code. This signals to Bob's device that Alice has
|
||||||
|
scanned Bob's QR code.
|
||||||
|
|
||||||
|
This message is merely a signal for Bob's device to proceed to the next
|
||||||
|
step, and is not used for verification purposes.
|
||||||
|
9. Upon receipt of the `m.key.verification.start` message, Bob's device ensures
|
||||||
|
that the shared secret matches.
|
||||||
|
|
||||||
|
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.)
|
||||||
|
|
||||||
|
If the shared secret does match, it asks Bob to confirm that Alice
|
||||||
|
has scanned the QR code.
|
||||||
|
10. Bob sees Alice's device confirm that the key matches, and presses the button
|
||||||
|
on his device to indicate that Alice's key is verified.
|
||||||
|
|
||||||
|
Bob's verification of Alice's key hinges on Alice telling Bob the result of
|
||||||
|
her scan. Since the QR code includes what Bob thinks Alice's key is,
|
||||||
|
Alice's device can check whether Bob has the right key for her. Alice has
|
||||||
|
no motivation to lie about the result, as getting Bob to trust an incorrect
|
||||||
|
key would only affect communications between herself and Bob. Thus Alice
|
||||||
|
telling Bob that the code was scanned successfully is sufficient for Bob to
|
||||||
|
trust Alice's key, under the assumption that this communication is done
|
||||||
|
over a trusted medium (such as in-person).
|
||||||
|
11. Both devices send an `m.key.verification.done` message.
|
||||||
|
|
||||||
|
This flow allows Alice to verify Bob's key, and Bob to verify Alice's key.
|
||||||
|
Alice verifies Bob's key because she can trust the QR code that Bob displays
|
||||||
|
for her, as this is done over a trusted medium. Bob verifies Alice's key
|
||||||
|
because Alice can trust the QR code that Bob displays, and Bob can trust Alice
|
||||||
|
to tell him the result of the verification.
|
||||||
|
|
||||||
|
#### Self-verification
|
||||||
|
|
||||||
|
QR codes can also be used by a user to verify their own devices. These examples
|
||||||
|
shows Alice verifying two devices, one of them (Osborne2) having cross-signing
|
||||||
|
already set up, and the other one (Dynabook) having just logged in.
|
||||||
|
|
||||||
|
In the first example, Osborne2 scans Dynabook:
|
||||||
|
|
||||||
|
1. Alice logs into her new Dynabook and wants other users to be able to trust
|
||||||
|
it via cross-signing, and to trust other devices via cross-signing.
|
||||||
|
2. Dynabook retrieves Alice's public cross-signing key from the server, and
|
||||||
|
displays a QR code that encodes:
|
||||||
|
- Dynabook's device key,
|
||||||
|
- what it thinks Alice's master key is, and
|
||||||
|
- a random shared secret.
|
||||||
|
|
||||||
|
Note that in this case, the QR code does not include Alice's master key in a
|
||||||
|
`key_<key_id>` parameter, since Dynabook does not know whether it is trusted
|
||||||
|
or not.
|
||||||
|
3. Osborne2 scans the QR code displayed by Dynabook. At this point, Osborne2
|
||||||
|
knows Dynabook's device key and can sign it with the self-signing key and
|
||||||
|
upload the signature, and can trust Dynabook for sending secrets via SSSS.
|
||||||
|
It also knows that Dynabook has the correct cross-signing key.
|
||||||
|
4. Osborne2 tells Alice that the scan was successful, and sends the
|
||||||
|
`reciprocate` message containing the shared secret.
|
||||||
|
5. Upon receipt of the `reciprocate` message, Dynabook (after checking the
|
||||||
|
shared secret) confirms with Alice that she successfully scanned the QR
|
||||||
|
code.
|
||||||
|
6. Alice confirms.
|
||||||
|
7. Dynabook now knows that it can trust Alice's cross-signing keys that it
|
||||||
|
fetched from the server.
|
||||||
|
|
||||||
|
In the second example, Dynabook scans Osborne2:
|
||||||
|
|
||||||
|
1. Alice logs into her new Dynabook and wants other users to be able to trust
|
||||||
|
it via cross-signing, and to trust other devices via cross-signing.
|
||||||
|
2. Osborne2 notices that Dynabook is a new device. Osborne2 fetches Dynabook's
|
||||||
|
identity key and displays a QR code that encodes:
|
||||||
|
- what it thinks Dynabook's key is,
|
||||||
|
- Alice's master key, and
|
||||||
|
- a random shared secret.
|
||||||
|
3. Dynabook scans the QR code shown by Osborne2. At this point, Dynabook knows
|
||||||
|
Alice's cross-signing key, and so it can trust it to sign other devices. It
|
||||||
|
also knows that Osborne2 as the correct key for it.
|
||||||
|
4. Dynabook tells Alice that the scan is successful, and sends the
|
||||||
|
`reciprocate` message containing the shared secret.
|
||||||
|
5. Upon receipt of the `reciprocate` message, Osborne2 (after checking the
|
||||||
|
shared secret) confirms with Alice that she successfully scanned the QR
|
||||||
|
code.
|
||||||
|
6. Alice confirms.
|
||||||
|
7. Osborne2 now knows that it has the correct device key for Dynabook, and can
|
||||||
|
sign it with the self-signing key and upload the signature. Osborne2 can
|
||||||
|
also trust Dynabook for sending secrets via SSSS.
|
||||||
|
|
||||||
|
### 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.v2`: 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.v2`: 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 binary
|
||||||
|
strings in the general form:
|
||||||
|
|
||||||
|
- the ASCII string "MATRIX"
|
||||||
|
- one byte indicating the QR code version (must be `0x02`)
|
||||||
|
- one byte indicating the QR code verification mode. May be one of the
|
||||||
|
following values:
|
||||||
|
- `0x00` verifying another user with cross-signing
|
||||||
|
- `0x01` self-verifying in which the current device does trust the master key
|
||||||
|
- `0x02` self-verifying in which the current device does not yet trust the
|
||||||
|
master key
|
||||||
|
- the event ID or `transaction_id` of the associated verification
|
||||||
|
request event, encoded as:
|
||||||
|
- two bytes in network byte order (big-endian) indicating the length in
|
||||||
|
bytes of the ID as a UTF-8 string
|
||||||
|
- the ID as a UTF-8 string
|
||||||
|
- the first key, as 32 bytes. The key to use depends on the mode field:
|
||||||
|
- if `0x00` or `0x01`, then the current user's own master cross-signing public key
|
||||||
|
- if `0x02`, then the current device's device key
|
||||||
|
- the second key, as 32 bytes. The key to use depends on the mode field:
|
||||||
|
- if `0x00`, then what the device thinks the other user's master
|
||||||
|
cross-signing key is
|
||||||
|
- if `0x01`, then what the device thinks the other device's device key is
|
||||||
|
- if `0x02`, then what the device thinks the user's master cross-signing key
|
||||||
|
is
|
||||||
|
- a random shared secret, as a byte string. It is suggested to use a secret
|
||||||
|
that is about 8 bytes long. Note: as we do not share the length of the
|
||||||
|
secret, and it is not a fixed size, clients will just use the remainder of
|
||||||
|
binary string as the shared secret.
|
||||||
|
|
||||||
|
For example, if Alice displays a QR code encoding the following binary string:
|
||||||
|
|
||||||
|
```
|
||||||
|
"MATRIX" |ver|mode| len | event ID
|
||||||
|
4D 41 54 52 49 58 02 00 00 2D 21 41 42 43 44 ...
|
||||||
|
| user's cross-signing key | other user's cross-signing key | shared secret
|
||||||
|
00 01 02 03 04 05 06 07 ... 10 11 12 13 14 15 16 17 ... 20 21 22 23 24 25 26 27
|
||||||
|
```
|
||||||
|
|
||||||
|
this indicates that Alice is verifying another user (say Bob), in response to
|
||||||
|
the request from event "$ABCD...", her cross-signing key is
|
||||||
|
`0001020304050607...` (which is "AAECAwQFBg..." in base64), she thinks that
|
||||||
|
Bob's cross-signing key is `1011121314151617...` (which is "EBESExQVFh..." in
|
||||||
|
base64), and the shared secret is `2021222324252627` (which is "ICEiIyQlJic" in
|
||||||
|
base64).
|
||||||
|
|
||||||
|
### Message types
|
||||||
|
|
||||||
|
#### `m.key.verification.start`
|
||||||
|
|
||||||
|
Alice's device tells Bob's device that the QR code has been scanned.
|
||||||
|
|
||||||
|
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, encoded using unpadded base64
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"method": "m.reciprocate.v1",
|
||||||
|
"m.relates_to": {
|
||||||
|
"rel_type": "m.reference",
|
||||||
|
"event_id": "$event_id_of_verification_request"
|
||||||
|
},
|
||||||
|
"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). Since the key
|
||||||
|
verification framework allows for multiple methods to be supported, clients can
|
||||||
|
allow users to use different methods depending on their capability.
|
||||||
|
|
||||||
|
Rather than embedding the keys in the QR codes directly, the two clients could
|
||||||
|
perform an exchange similar to
|
||||||
|
[MSC1267](https://github.com/matrix-org/matrix-doc/issues/1267), and encoding
|
||||||
|
the Short Authentication String code in the QR code. However, this means that
|
||||||
|
the clients must exchange several messages before they can verify each other,
|
||||||
|
which would delay showing the QR codes. This proposal is also simpler to
|
||||||
|
implement.
|
||||||
|
|
||||||
|
This proposal does not support the case of asynchronous verification, such as
|
||||||
|
printing a QR code on a business card for others to scan. That may be address
|
||||||
|
in a separate MSC.
|
||||||
|
|
||||||
|
Security Considerations
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
The security of verifying Alice's key depends on Bob not hitting the "Verified"
|
||||||
|
button (step 10 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.
|
@ -0,0 +1,51 @@
|
|||||||
|
# MSC2765: Widget avatars
|
||||||
|
|
||||||
|
Currently widgets have a name and title associated with them, though no opportunity for avatars
|
||||||
|
for a favicon-like experience. This proposal introduces such a concept.
|
||||||
|
|
||||||
|
## Proposal
|
||||||
|
|
||||||
|
A new optional paramater named `avatar_url` is added to the widget definition. This parameter is
|
||||||
|
an MXC URI to an image clients can use to associate with the widget, likely alongside the `name`
|
||||||
|
and/or `title`.
|
||||||
|
|
||||||
|
Widget avatars SHOULD be legible at small sizes, such as 20x20. The MXC URI in the `avatar_url`
|
||||||
|
should be the source material to allow clients to use the `/thumbnail` API to get a size for their
|
||||||
|
use case.
|
||||||
|
|
||||||
|
Rendering avatars is optional for clients, much like how clients are not required to use the `name`
|
||||||
|
or `title` of a widget.
|
||||||
|
|
||||||
|
An example widget would be:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"creatorUserId": "@alice:example.org",
|
||||||
|
"data": {
|
||||||
|
"custom_key": "This is a custom key",
|
||||||
|
"title": "This is a witty description for the widget"
|
||||||
|
},
|
||||||
|
"id": "20200827_WidgetExample",
|
||||||
|
"name": "My Cool Widget",
|
||||||
|
"type": "m.custom",
|
||||||
|
"url": "https://example.org/my/widget.html?roomId=$matrix_room_id",
|
||||||
|
"waitForIframeLoad": true,
|
||||||
|
"avatar_url": "mxc://example.org/abc123"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Alternatives
|
||||||
|
|
||||||
|
We could define a whole structured system for different thumbnail sizes, though we have a thumbnail
|
||||||
|
API which can be used to request whatever size is needed by the client.
|
||||||
|
|
||||||
|
## Security considerations
|
||||||
|
|
||||||
|
Widget avatars could be non-images. Clients should use the thumbnail API to encourage error responses
|
||||||
|
from the server when a widget avatar is a non-image.
|
||||||
|
|
||||||
|
## Unstable prefix
|
||||||
|
|
||||||
|
While this MSC is not in a released version of the specification, clients should use an alternative
|
||||||
|
event type for widgets or use `org.matrix.msc2765.avatar_url` when using `m.widget` or `m.widgets`
|
||||||
|
as an event type.
|
@ -0,0 +1,54 @@
|
|||||||
|
# MSC2774: Giving widgets their ID so they can communicate
|
||||||
|
|
||||||
|
Under the [current specification](https://github.com/matrix-org/matrix-doc/pull/2764), widgets are
|
||||||
|
able to communicate with their client host, however doing so is a bit difficult if they don't already
|
||||||
|
know their widget ID. Some widgets will be able to get their ID from another source like an
|
||||||
|
integration manager, however this is not the case for all widgets.
|
||||||
|
|
||||||
|
[MSC2762](https://github.com/matrix-org/matrix-doc/pull/2762) has a fair amount of background
|
||||||
|
information on widgets, as does the current specification linked above.
|
||||||
|
|
||||||
|
## Proposal
|
||||||
|
|
||||||
|
Currently widgets can expect a `?widgetId` query parameter sent to them in clients like Element,
|
||||||
|
however this has some issues and as such is not proposed to exist any further. One of the issues
|
||||||
|
is that the widget must retain the query string, which isn't entirely possible for some frontends
|
||||||
|
(they would instead prefer to use the fragment). It's also a privacy risk in that by being sent
|
||||||
|
through the query string, the server can be made aware of the widget ID. The widget ID doesn't
|
||||||
|
normally contain any useful information (it's an opaque string), however it's not required for
|
||||||
|
the server to function under typical usage.
|
||||||
|
|
||||||
|
The proposal is to introduce a `$matrix_widget_id` template variable for the URL, similar to the
|
||||||
|
existing `$matrix_room_id` variable. Widgets can then have their widget ID wherever they want in
|
||||||
|
the widget URL, making it easier on them to find and use.
|
||||||
|
|
||||||
|
This carries the same risks as a room ID being passed to the widget: the client can easily lie about
|
||||||
|
it, however there's no real risk involved in doing so because it's used for communication only. So
|
||||||
|
long as the client is able to identify which widget is talking to it, it doesn't really matter. It's
|
||||||
|
more of a problem if the client uses a widget ID from another widget as that could confuse the
|
||||||
|
client, however this is believed to be a bug. Clients should also be performing origin checks to
|
||||||
|
ensure the widget is talking from a sane origin and not somewhere else, like another tab or browser.
|
||||||
|
|
||||||
|
## Potential issues
|
||||||
|
|
||||||
|
This is not backwards compatible with the history of widgets so far, so clients and widgets will
|
||||||
|
need to be modified to support it. Clients which currently use the `?widgetId` parameter are
|
||||||
|
encouraged to continue supporting the parameter until sufficient adoption is reached.
|
||||||
|
|
||||||
|
## Alternatives
|
||||||
|
|
||||||
|
As mentioned, a query parameter could be used, though this has the issues previously covered. Another
|
||||||
|
solution might be to allow a single widget API action which has no widget ID solely for the purpose
|
||||||
|
of finding the widget ID, however clients are unlikely to be able to differentiate between two widgets
|
||||||
|
if this were the case.
|
||||||
|
|
||||||
|
Another solution would be to let the widget discover its widget ID by harvesting it out of the first
|
||||||
|
widget API request it sees. This can't always be relied upon (some flows require the widget to
|
||||||
|
speak first), and as the widget API becomes more capable it could become a security risk. A malicious
|
||||||
|
browser extension could spam the widget with fake requests to try and convince it to talk to it
|
||||||
|
instead of the client, thus redirecting some information to the wrong place.
|
||||||
|
|
||||||
|
## Unstable prefix
|
||||||
|
|
||||||
|
Implementations should use `$org.matrix.msc2774_widget_id` as a variable until this lands in a
|
||||||
|
released version of the specification.
|
Loading…
Reference in New Issue