aboutsummaryrefslogtreecommitdiff
path: root/lib/events
diff options
context:
space:
mode:
authorCarl Schwan <carl@carlschwan.eu>2021-02-05 18:45:30 +0100
committerTobias Fella <fella@posteo.de>2021-12-01 21:56:11 +0100
commit5f3e33e1c15be19f09d83a0d6f44d551021a9d44 (patch)
treefd1218293f6ee0e92361fd9d32eccfdefbeb0d0d /lib/events
parent265f105d77bf91c127c363b0c880357f91df7db4 (diff)
downloadlibquotient-5f3e33e1c15be19f09d83a0d6f44d551021a9d44.tar.gz
libquotient-5f3e33e1c15be19f09d83a0d6f44d551021a9d44.zip
Implement key verification events
Diffstat (limited to 'lib/events')
-rw-r--r--lib/events/keyverificationevent.cpp193
-rw-r--r--lib/events/keyverificationevent.h167
2 files changed, 360 insertions, 0 deletions
diff --git a/lib/events/keyverificationevent.cpp b/lib/events/keyverificationevent.cpp
new file mode 100644
index 00000000..938b3bde
--- /dev/null
+++ b/lib/events/keyverificationevent.cpp
@@ -0,0 +1,193 @@
+// SPDX-FileCopyrightText: 2021 Carl Schwan <carlschwan@kde.org>
+// SPDX-License-Identifier: LGPL-2.1-or-later
+
+#include "keyverificationevent.h"
+
+using namespace Quotient;
+
+KeyVerificationRequestEvent::KeyVerificationRequestEvent(const QJsonObject &obj)
+ : Event(typeId(), obj)
+{}
+
+QString KeyVerificationRequestEvent::fromDevice() const
+{
+ return contentJson()["from_device"_ls].toString();
+}
+
+QString KeyVerificationRequestEvent::transactionId() const
+{
+ return contentJson()["transaction_id"_ls].toString();
+}
+
+QStringList KeyVerificationRequestEvent::methods() const
+{
+ QStringList methods;
+ for (const auto &method : contentJson()["methods"].toArray()) {
+ methods.append(method.toString());
+ }
+ return methods;
+}
+
+uint64_t KeyVerificationRequestEvent::timestamp() const
+{
+ return contentJson()["timestamp"_ls].toDouble();
+}
+
+KeyVerificationStartEvent::KeyVerificationStartEvent(const QJsonObject &obj)
+ : Event(typeId(), obj)
+{}
+
+QString KeyVerificationStartEvent::fromDevice() const
+{
+ return contentJson()["from_device"_ls].toString();
+}
+
+QString KeyVerificationStartEvent::transactionId() const
+{
+ return contentJson()["transaction_id"_ls].toString();
+}
+
+QString KeyVerificationStartEvent::method() const
+{
+ return contentJson()["method"_ls].toString();
+}
+
+Omittable<QString> KeyVerificationStartEvent::nextMethod() const
+{
+ auto next = contentJson()["method"_ls];
+ if (next.isUndefined()) {
+ return std::nullopt;
+ }
+ return next.toString();
+}
+
+QStringList KeyVerificationStartEvent::keyAgreementProtocols() const
+{
+ Q_ASSERT(method() == QStringLiteral("m.sas.v1"));
+ QStringList protocols;
+ for (const auto &proto : contentJson()["key_agreement_protocols"_ls].toArray()) {
+ protocols.append(proto.toString());
+ }
+ return protocols;
+}
+
+QStringList KeyVerificationStartEvent::hashes() const
+{
+ Q_ASSERT(method() == QStringLiteral("m.sas.v1"));
+ QStringList hashes;
+ for (const auto &hashItem : contentJson()["hashes"_ls].toArray()) {
+ hashes.append(hashItem.toString());
+ }
+ return hashes;
+}
+
+QStringList KeyVerificationStartEvent::messageAuthenticationCodes() const
+{
+ Q_ASSERT(method() == QStringLiteral("m.sas.v1"));
+
+ QStringList codes;
+ for (const auto &code : contentJson()["message_authentication_codes"_ls].toArray()) {
+ codes.append(code.toString());
+ }
+ return codes;
+}
+
+QString KeyVerificationStartEvent::shortAuthenticationString() const
+{
+ return contentJson()["short_authentification_string"_ls].toString();
+}
+
+KeyVerificationAcceptEvent::KeyVerificationAcceptEvent(const QJsonObject &obj)
+ : Event(typeId(), obj)
+{}
+
+QString KeyVerificationAcceptEvent::transactionId() const
+{
+ return contentJson()["transaction_id"_ls].toString();
+}
+
+QString KeyVerificationAcceptEvent::method() const
+{
+ return contentJson()["method"_ls].toString();
+}
+
+QString KeyVerificationAcceptEvent::keyAgreementProtocol() const
+{
+ return contentJson()["key_agreement_protocol"_ls].toString();
+}
+
+QString KeyVerificationAcceptEvent::hashData() const
+{
+ return contentJson()["hash"_ls].toString();
+}
+
+QStringList KeyVerificationAcceptEvent::shortAuthenticationString() const
+{
+ QStringList strings;
+ for (const auto &authenticationString : contentJson()["short_authentification_string"].toArray()) {
+ strings.append(authenticationString.toString());
+ }
+ return strings;
+}
+
+QString KeyVerificationAcceptEvent::commitement() const
+{
+ return contentJson()["commitement"].toString();
+}
+
+KeyVerificationCancelEvent::KeyVerificationCancelEvent(const QJsonObject &obj)
+ : Event(typeId(), obj)
+{}
+
+QString KeyVerificationCancelEvent::transactionId() const
+{
+ return contentJson()["transaction_id"_ls].toString();
+}
+
+QString KeyVerificationCancelEvent::reason() const
+{
+ return contentJson()["reason"_ls].toString();
+}
+
+QString KeyVerificationCancelEvent::code() const
+{
+ return contentJson()["code"_ls].toString();
+}
+
+KeyVerificationKeyEvent::KeyVerificationKeyEvent(const QJsonObject &obj)
+ : Event(typeId(), obj)
+{}
+
+QString KeyVerificationKeyEvent::transactionId() const
+{
+ return contentJson()["transaction_id"_ls].toString();
+}
+
+QString KeyVerificationKeyEvent::key() const
+{
+ return contentJson()["key"_ls].toString();
+}
+
+KeyVerificationMacEvent::KeyVerificationMacEvent(const QJsonObject &obj)
+ : Event(typeId(), obj)
+{}
+
+QString KeyVerificationMacEvent::transactionId() const
+{
+ return contentJson()["transaction_id"].toString();
+}
+
+QString KeyVerificationMacEvent::keys() const
+{
+ return contentJson()["keys"].toString();
+}
+
+QHash<QString, QString> KeyVerificationMacEvent::mac() const
+{
+ QHash<QString, QString> macs;
+ const auto macObj = contentJson()["mac"_ls].toObject();
+ for (auto mac = macObj.constBegin(); mac != macObj.constEnd(); mac++) {
+ macs.insert(mac.key(), mac.value().toString());
+ }
+ return macs;
+}
diff --git a/lib/events/keyverificationevent.h b/lib/events/keyverificationevent.h
new file mode 100644
index 00000000..13e7dcdd
--- /dev/null
+++ b/lib/events/keyverificationevent.h
@@ -0,0 +1,167 @@
+// SPDX-FileCopyrightText: 2021 Carl Schwan <carlschwan@kde.org>
+// SPDX-License-Identifier: LGPL-2.1-or-later
+
+#include "event.h"
+
+namespace Quotient {
+
+/// Requests a key verification with another user's devices.
+/// Typically sent as a to-device event.
+class KeyVerificationRequestEvent : public Event {
+ Q_GADGET
+public:
+ DEFINE_EVENT_TYPEID("m.key.verification.request", KeyVerificationRequestEvent)
+
+ explicit KeyVerificationRequestEvent(const QJsonObject& obj);
+
+ /// The device ID which is initiating the request.
+ QString fromDevice() const;
+
+ /// An opaque identifier for the verification request. Must
+ /// be unique with respect to the devices involved.
+ QString transactionId() const;
+
+ /// The verification methods supported by the sender.
+ QStringList methods() const;
+
+ /// The POSIX timestamp in milliseconds for when the request was
+ /// made. If the request is in the future by more than 5 minutes or
+ /// more than 10 minutes in the past, the message should be ignored
+ /// by the receiver.
+ uint64_t timestamp() const;
+};
+REGISTER_EVENT_TYPE(KeyVerificationRequestEvent)
+
+/// Begins a key verification process.
+class KeyVerificationStartEvent : public Event {
+ Q_GADGET
+public:
+ DEFINE_EVENT_TYPEID("m.key.verification.start", KeyVerificationStartEvent)
+
+ explicit KeyVerificationStartEvent(const QJsonObject &obj);
+
+ /// The device ID which is initiating the process.
+ QString fromDevice() const;
+
+ /// An opaque identifier for the verification request. Must
+ /// be unique with respect to the devices involved.
+ QString transactionId() const;
+
+ /// The verification method to use.
+ QString method() const;
+
+ /// Optional method to use to verify the other user's key with.
+ Omittable<QString> nextMethod() const;
+
+ // SAS.V1 methods
+
+ /// The key agreement protocols the sending device understands.
+ /// \note Only exist if method is m.sas.v1
+ QStringList keyAgreementProtocols() const;
+
+ /// The hash methods the sending device understands.
+ /// \note Only exist if method is m.sas.v1
+ QStringList hashes() const;
+
+ /// The message authentication codes that the sending device understands.
+ /// \note Only exist if method is m.sas.v1
+ QStringList messageAuthenticationCodes() const;
+
+ /// The SAS methods the sending device (and the sending device's
+ /// user) understands.
+ /// \note Only exist if method is m.sas.v1
+ QString shortAuthenticationString() const;
+};
+REGISTER_EVENT_TYPE(KeyVerificationStartEvent)
+
+/// Accepts a previously sent m.key.verification.start message.
+/// Typically sent as a to-device event.
+class KeyVerificationAcceptEvent : public Event {
+ Q_GADGET
+public:
+ DEFINE_EVENT_TYPEID("m.key.verification.accept", KeyVerificationAcceptEvent)
+
+ explicit KeyVerificationAcceptEvent(const QJsonObject& obj);
+
+ /// An opaque identifier for the verification process.
+ QString transactionId() const;
+
+ /// The verification method to use. Must be 'm.sas.v1'.
+ QString method() const;
+
+ /// The key agreement protocol the device is choosing to use, out of
+ /// the options in the m.key.verification.start message.
+ QString keyAgreementProtocol() const;
+
+ /// The hash method the device is choosing to use, out of the
+ /// options in the m.key.verification.start message.
+ QString hashData() const;
+
+ /// The message authentication code the device is choosing to use, out
+ /// of the options in the m.key.verification.start message.
+ QString messageAuthenticationCode() const;
+
+ /// The SAS methods both devices involved in the verification process understand.
+ QStringList shortAuthenticationString() const;
+
+ /// The hash (encoded as unpadded base64) of the concatenation of the
+ /// device's ephemeral public key (encoded as unpadded base64) and the
+ /// canonical JSON representation of the m.key.verification.start message.
+ QString commitement() const;
+};
+REGISTER_EVENT_TYPE(KeyVerificationAcceptEvent)
+
+class KeyVerificationCancelEvent : public Event {
+ Q_GADGET
+public:
+ DEFINE_EVENT_TYPEID("m.key.verification.cancel", KeyVerificationCancelEvent)
+
+ explicit KeyVerificationCancelEvent(const QJsonObject &obj);
+
+ /// An opaque identifier for the verification process.
+ QString transactionId() const;
+
+ /// A human readable description of the code. The client should only
+ /// rely on this string if it does not understand the code.
+ QString reason() const;
+
+ /// The error code for why the process/request was cancelled by the user.
+ QString code() const;
+};
+REGISTER_EVENT_TYPE(KeyVerificationCancelEvent)
+
+/// Sends the ephemeral public key for a device to the partner device.
+/// Typically sent as a to-device event.
+class KeyVerificationKeyEvent : public Event {
+ Q_GADGET
+public:
+ DEFINE_EVENT_TYPEID("m.key.verification.key", KeyVerificationKeyEvent)
+
+ explicit KeyVerificationKeyEvent(const QJsonObject &obj);
+
+ /// An opaque identifier for the verification process.
+ QString transactionId() const;
+
+ /// The device's ephemeral public key, encoded as unpadded base64.
+ QString key() const;
+};
+REGISTER_EVENT_TYPE(KeyVerificationKeyEvent)
+
+/// Sends the MAC of a device's key to the partner device.
+class KeyVerificationMacEvent : public Event {
+ Q_GADGET
+public:
+ DEFINE_EVENT_TYPEID("m.key.verification.mac", KeyVerificationMacEvent)
+
+ explicit KeyVerificationMacEvent(const QJsonObject &obj);
+
+ /// An opaque identifier for the verification process.
+ QString transactionId() const;
+
+ /// The device's ephemeral public key, encoded as unpadded base64.
+ QString keys() const;
+
+ QHash<QString, QString> mac() const;
+};
+REGISTER_EVENT_TYPE(KeyVerificationMacEvent)
+} // namespace Quotient