libQuotient
A Qt library for building matrix clients
Loading...
Searching...
No Matches
keyverificationevent.h
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2021 Carl Schwan <carlschwan@kde.org>
2// SPDX-License-Identifier: LGPL-2.1-or-later
3
4#pragma once
5
6#include "roomevent.h"
7
8namespace Quotient {
9
10constexpr inline auto SasV1Method = "m.sas.v1"_L1;
11
12// Same story as with EncryptedEvent: because KeyVerificationEvent inheritors can be sent both
13// in-room and out-of-room, and RoomEvent doesn't restrict the shape of the event, rather just
14// adds accessors, KeyVerificationEvent is derived from RoomEvent but when used as a to-device
15// event room-specific attributes will be empty.
16class QUOTIENT_API KeyVerificationEvent : public RoomEvent {
17public:
18 QUO_BASE_EVENT(KeyVerificationEvent, RoomEvent, "m.key.*")
19
20 using RoomEvent::RoomEvent;
21
22 /// An opaque identifier for the verification request. Must
23 /// be unique with respect to the devices involved.
24 QUO_CONTENT_GETTER(QString, transactionId)
25};
26
27/// Requests a key verification with another user's devices.
28class QUOTIENT_API KeyVerificationRequestEvent : public KeyVerificationEvent {
29public:
30 QUO_EVENT(KeyVerificationRequestEvent, "m.key.verification.request")
31
32 using KeyVerificationEvent::KeyVerificationEvent;
33 KeyVerificationRequestEvent(const QString& transactionId,
34 const QString& fromDevice,
35 const QStringList& methods,
36 const QDateTime& timestamp)
37 : KeyVerificationRequestEvent(
38 basicJson(TypeId, { { "transaction_id"_L1, transactionId },
39 { "from_device"_L1, fromDevice },
40 { "methods"_L1, toJson(methods) },
41 { "timestamp"_L1, toJson(timestamp) } }))
42 {}
43
44 /// The device ID which is initiating the request.
45 QUO_CONTENT_GETTER(QString, fromDevice)
46
47 /// The verification methods supported by the sender.
48 QUO_CONTENT_GETTER(QStringList, methods)
49
50 /// The POSIX timestamp in milliseconds for when the request was
51 /// made. If the request is in the future by more than 5 minutes or
52 /// more than 10 minutes in the past, the message should be ignored
53 /// by the receiver.
54 QUO_CONTENT_GETTER(QDateTime, timestamp)
55};
56
57class QUOTIENT_API KeyVerificationReadyEvent : public KeyVerificationEvent {
58public:
59 QUO_EVENT(KeyVerificationReadyEvent, "m.key.verification.ready")
60
61 using KeyVerificationEvent::KeyVerificationEvent;
62 KeyVerificationReadyEvent(const QString& transactionId,
63 const QString& fromDevice,
64 const QStringList& methods)
65 : KeyVerificationReadyEvent(
66 basicJson(TypeId, { { "transaction_id"_L1, transactionId },
67 { "from_device"_L1, fromDevice },
68 { "methods"_L1, toJson(methods) } }))
69 {}
70
71 /// The device ID which is accepting the request.
72 QUO_CONTENT_GETTER(QString, fromDevice)
73
74 /// The verification methods supported by the sender.
75 QUO_CONTENT_GETTER(QStringList, methods)
76};
77
78constexpr inline auto HmacSha256Code = "hkdf-hmac-sha256"_L1;
79constexpr inline auto HmacSha256V2Code = "hkdf-hmac-sha256.v2"_L1;
80constexpr std::array SupportedMacs { HmacSha256Code, HmacSha256V2Code };
81
82/// Begins a key verification process.
83class QUOTIENT_API KeyVerificationStartEvent : public KeyVerificationEvent {
84public:
85 QUO_EVENT(KeyVerificationStartEvent, "m.key.verification.start")
86
87 using KeyVerificationEvent::KeyVerificationEvent;
88 KeyVerificationStartEvent(const QString& transactionId,
89 const QString& fromDevice)
90 : KeyVerificationStartEvent(
91 basicJson(TypeId, { { "transaction_id"_L1, transactionId },
92 { "from_device"_L1, fromDevice },
93 { "method"_L1, SasV1Method },
94 { "hashes"_L1, QJsonArray{ "sha256"_L1 } },
95 { "key_agreement_protocols"_L1,
96 QJsonArray{ "curve25519-hkdf-sha256"_L1 } },
97 { "message_authentication_codes"_L1,
98 toJson(SupportedMacs) },
99 { "short_authentication_string"_L1,
100 QJsonArray{ "decimal"_L1, "emoji"_L1 } } }))
101 {}
102
103 /// The device ID which is initiating the process.
104 QUO_CONTENT_GETTER(QString, fromDevice)
105
106 /// The verification method to use.
107 QUO_CONTENT_GETTER(QString, method)
108
109 /// Optional method to use to verify the other user's key with.
110 QUO_CONTENT_GETTER(std::optional<QString>, nextMethod)
111
112 // SAS.V1 methods
113
114 /// The key agreement protocols the sending device understands.
115 /// \note Only exist if method is m.sas.v1
116 QStringList keyAgreementProtocols() const
117 {
118 Q_ASSERT(method() == SasV1Method);
119 return contentPart<QStringList>("key_agreement_protocols"_L1);
120 }
121
122 /// The hash methods the sending device understands.
123 /// \note Only exist if method is m.sas.v1
124 QStringList hashes() const
125 {
126 Q_ASSERT(method() == SasV1Method);
127 return contentPart<QStringList>("hashes"_L1);
128 }
129
130 /// The message authentication codes that the sending device understands.
131 /// \note Only exist if method is m.sas.v1
132 QStringList messageAuthenticationCodes() const
133 {
134 Q_ASSERT(method() == SasV1Method);
135 return contentPart<QStringList>("message_authentication_codes"_L1);
136 }
137
138 /// The SAS methods the sending device (and the sending device's
139 /// user) understands.
140 /// \note Only exist if method is m.sas.v1
141 QString shortAuthenticationString() const
142 {
143 Q_ASSERT(method() == SasV1Method);
144 return contentPart<QString>("short_authentication_string"_L1);
145 }
146};
147
148/// Accepts a previously sent m.key.verification.start message.
149class QUOTIENT_API KeyVerificationAcceptEvent : public KeyVerificationEvent {
150public:
151 QUO_EVENT(KeyVerificationAcceptEvent, "m.key.verification.accept")
152
153 using KeyVerificationEvent::KeyVerificationEvent;
154 KeyVerificationAcceptEvent(const QString& transactionId,
155 const QString& commitment)
156 : KeyVerificationAcceptEvent(basicJson(
157 TypeId, { { "transaction_id"_L1, transactionId },
158 { "method"_L1, SasV1Method },
159 { "key_agreement_protocol"_L1, "curve25519-hkdf-sha256"_L1 },
160 { "hash"_L1, "sha256"_L1 },
161 { "message_authentication_code"_L1, HmacSha256V2Code },
162 { "short_authentication_string"_L1,
163 QJsonArray{ "decimal"_L1, "emoji"_L1, } },
164 { "commitment"_L1, commitment } }))
165 {}
166
167 /// The verification method to use. Must be 'm.sas.v1'.
168 QUO_CONTENT_GETTER(QString, method)
169
170 /// The key agreement protocol the device is choosing to use, out of
171 /// the options in the m.key.verification.start message.
172 QUO_CONTENT_GETTER(QString, keyAgreementProtocol)
173
174 /// The hash method the device is choosing to use, out of the
175 /// options in the m.key.verification.start message.
176 QUO_CONTENT_GETTER_X(QString, hashData, "hash"_L1)
177
178 /// The message authentication code the device is choosing to use, out
179 /// of the options in the m.key.verification.start message.
180 QUO_CONTENT_GETTER(QString, messageAuthenticationCode)
181
182 /// The SAS methods both devices involved in the verification process understand.
183 QUO_CONTENT_GETTER(QStringList, shortAuthenticationString)
184
185 /// The hash (encoded as unpadded base64) of the concatenation of the
186 /// device's ephemeral public key (encoded as unpadded base64) and the
187 /// canonical JSON representation of the m.key.verification.start message.
188 QUO_CONTENT_GETTER(QString, commitment)
189};
190
191class QUOTIENT_API KeyVerificationCancelEvent : public KeyVerificationEvent {
192public:
193 QUO_EVENT(KeyVerificationCancelEvent, "m.key.verification.cancel")
194
195 using KeyVerificationEvent::KeyVerificationEvent;
196 KeyVerificationCancelEvent(const QString& transactionId,
197 const QString& reason)
198 : KeyVerificationCancelEvent(
199 basicJson(TypeId, {
200 { "transaction_id"_L1, transactionId },
201 { "reason"_L1, reason },
202 { "code"_L1, reason } // Not a typo
203 }))
204 {}
205
206 /// A human readable description of the code. The client should only
207 /// rely on this string if it does not understand the code.
208 QUO_CONTENT_GETTER(QString, reason)
209
210 /// The error code for why the process/request was cancelled by the user.
211 QUO_CONTENT_GETTER(QString, code)
212};
213
214/// Sends the ephemeral public key for a device to the partner device.
215class QUOTIENT_API KeyVerificationKeyEvent : public KeyVerificationEvent {
216public:
217 QUO_EVENT(KeyVerificationKeyEvent, "m.key.verification.key")
218
219 using KeyVerificationEvent::KeyVerificationEvent;
220 KeyVerificationKeyEvent(const QString& transactionId, const QString& key)
221 : KeyVerificationKeyEvent(
222 basicJson(TypeId, { { "transaction_id"_L1, transactionId },
223 { "key"_L1, key } }))
224 {}
225
226 /// The device's ephemeral public key, encoded as unpadded base64.
227 QUO_CONTENT_GETTER(QString, key)
228};
229
230/// Sends the MAC of a device's key to the partner device.
231class QUOTIENT_API KeyVerificationMacEvent : public KeyVerificationEvent {
232public:
233 QUO_EVENT(KeyVerificationMacEvent, "m.key.verification.mac")
234
235 using KeyVerificationEvent::KeyVerificationEvent;
236 KeyVerificationMacEvent(const QString& transactionId, const QString& keys,
237 const QJsonObject& mac)
238 : KeyVerificationMacEvent(
239 basicJson(TypeId, { { "transaction_id"_L1, transactionId },
240 { "keys"_L1, keys },
241 { "mac"_L1, mac } }))
242 {}
243
244 /// The device's ephemeral public key, encoded as unpadded base64.
245 QUO_CONTENT_GETTER(QString, keys)
246
247 QHash<QString, QString> mac() const
248 {
249 return contentPart<QHash<QString, QString>>("mac"_L1);
250 }
251};
252
253class QUOTIENT_API KeyVerificationDoneEvent : public KeyVerificationEvent {
254public:
255 QUO_EVENT(KeyVerificationDoneEvent, "m.key.verification.done")
256
257 using KeyVerificationEvent::KeyVerificationEvent;
258 explicit KeyVerificationDoneEvent(const QString& transactionId)
259 : KeyVerificationDoneEvent(
260 basicJson(TypeId, { { "transaction_id"_L1, transactionId } }))
261 {}
262};
263} // namespace Quotient
#define QUO_CONTENT_GETTER_X(PartType_, PartName_, JsonKey_)
Definition event.h:450
#define QUO_CONTENT_GETTER(PartType_, PartName_)
Define an inline method obtaining a content part.
Definition event.h:465
#define QUO_EVENT(CppType_, MatrixType_)
Supply event metatype information in (specific) event types.
Definition event.h:436
#define QUO_BASE_EVENT(CppType_, BaseCppType_,...)
Supply event metatype information in base event types.
Definition event.h:408
#define QUOTIENT_API