From 0b5e72a2c6502f22a752b72b4df5fa25746fdd25 Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Thu, 26 May 2022 08:51:22 +0200 Subject: Refactor EncryptedFile and EC::FileInfo::file Besides having a misleading name (and it goes back to the spec), EncryptedFile under `file` key preempts the `url` (or `thumbnail_url`) string value so only one of the two should exist. This is a case for using std::variant<> - despite its clumsy syntax, it can actually simplify and streamline code when all the necessary bits are in place (such as conversion to JSON and getting the common piece - the URL - out of it). This commit replaces `FileInfo::url` and `FileInfo::file` with a common field `source` of type `FileSourceInfo` that is an alias for a variant type covering both underlying types; and `url()` is reintroduced as a function instead, to allow simplified access to whichever URL is available inside the variant. Oh, and EncryptedFile is EncryptedFileMetadata now, to clarify that it does not represent the file payload itself but rather the data necessary to obtain that payload. --- lib/events/filesourceinfo.h | 89 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 lib/events/filesourceinfo.h (limited to 'lib/events/filesourceinfo.h') diff --git a/lib/events/filesourceinfo.h b/lib/events/filesourceinfo.h new file mode 100644 index 00000000..885601be --- /dev/null +++ b/lib/events/filesourceinfo.h @@ -0,0 +1,89 @@ +// SPDX-FileCopyrightText: 2021 Carl Schwan +// +// SPDX-License-Identifier: LGPL-2.1-or-later + +#pragma once + +#include "converters.h" + +#include + +namespace Quotient { +/** + * JSON Web Key object as specified in + * https://spec.matrix.org/unstable/client-server-api/#extensions-to-mroommessage-msgtypes + * The only currently relevant member is `k`, the rest needs to be set to the defaults specified in the spec. + */ +struct JWK +{ + Q_GADGET + Q_PROPERTY(QString kty MEMBER kty CONSTANT) + Q_PROPERTY(QStringList keyOps MEMBER keyOps CONSTANT) + Q_PROPERTY(QString alg MEMBER alg CONSTANT) + Q_PROPERTY(QString k MEMBER k CONSTANT) + Q_PROPERTY(bool ext MEMBER ext CONSTANT) + +public: + QString kty; + QStringList keyOps; + QString alg; + QString k; + bool ext; +}; + +struct QUOTIENT_API EncryptedFileMetadata { + Q_GADGET + Q_PROPERTY(QUrl url MEMBER url CONSTANT) + Q_PROPERTY(JWK key MEMBER key CONSTANT) + Q_PROPERTY(QString iv MEMBER iv CONSTANT) + Q_PROPERTY(QHash hashes MEMBER hashes CONSTANT) + Q_PROPERTY(QString v MEMBER v CONSTANT) + +public: + QUrl url; + JWK key; + QString iv; + QHash hashes; + QString v; + + static std::pair encryptFile( + const QByteArray& plainText); + QByteArray decryptFile(const QByteArray& ciphertext) const; +}; + +template <> +struct QUOTIENT_API JsonObjectConverter { + static void dumpTo(QJsonObject& jo, const EncryptedFileMetadata& pod); + static void fillFrom(const QJsonObject& jo, EncryptedFileMetadata& pod); +}; + +template <> +struct QUOTIENT_API JsonObjectConverter { + static void dumpTo(QJsonObject& jo, const JWK& pod); + static void fillFrom(const QJsonObject& jo, JWK& pod); +}; + +using FileSourceInfo = std::variant; + +QUOTIENT_API QUrl getUrlFromSourceInfo(const FileSourceInfo& fsi); + +QUOTIENT_API void setUrlInSourceInfo(FileSourceInfo& fsi, const QUrl& newUrl); + +// The way FileSourceInfo is stored in JSON requires an extra parameter so +// the original template is not applicable +template <> +void fillJson(QJsonObject&, const FileSourceInfo&) = delete; + +//! \brief Export FileSourceInfo to a JSON object +//! +//! Depending on what is stored inside FileSourceInfo, this function will insert +//! - a key-to-string pair where key is taken from jsonKeys[0] and the string +//! is the URL, if FileSourceInfo stores a QUrl; +//! - a key-to-object mapping where key is taken from jsonKeys[1] and the object +//! is the result of converting EncryptedFileMetadata to JSON, +//! if FileSourceInfo stores EncryptedFileMetadata +QUOTIENT_API void fillJson(QJsonObject& jo, + const std::array& jsonKeys, + const FileSourceInfo& fsi); + +} // namespace Quotient -- cgit v1.2.3 From c2d87291dbf8bd240e3e96138ec52aa5da22416b Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Thu, 26 May 2022 12:50:30 +0200 Subject: Move encryptFile/decryptFile out of EncryptedFileMetadata These are not operations on EncryptedFileMetadata but rather on a combination of EncryptedFileMetadata and ciphertext. If C++ had multimethods these could be bound to such a combination. --- lib/events/filesourceinfo.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'lib/events/filesourceinfo.h') diff --git a/lib/events/filesourceinfo.h b/lib/events/filesourceinfo.h index 885601be..8f7e3cbe 100644 --- a/lib/events/filesourceinfo.h +++ b/lib/events/filesourceinfo.h @@ -45,12 +45,13 @@ public: QString iv; QHash hashes; QString v; - - static std::pair encryptFile( - const QByteArray& plainText); - QByteArray decryptFile(const QByteArray& ciphertext) const; }; +QUOTIENT_API std::pair encryptFile( + const QByteArray& plainText); +QUOTIENT_API QByteArray decryptFile(const QByteArray& ciphertext, + const EncryptedFileMetadata& metadata); + template <> struct QUOTIENT_API JsonObjectConverter { static void dumpTo(QJsonObject& jo, const EncryptedFileMetadata& pod); -- cgit v1.2.3