aboutsummaryrefslogtreecommitdiff
path: root/lib/csapi/keys.h
diff options
context:
space:
mode:
Diffstat (limited to 'lib/csapi/keys.h')
-rw-r--r--lib/csapi/keys.h473
1 files changed, 275 insertions, 198 deletions
diff --git a/lib/csapi/keys.h b/lib/csapi/keys.h
index e59b1dae..b28de305 100644
--- a/lib/csapi/keys.h
+++ b/lib/csapi/keys.h
@@ -4,216 +4,293 @@
#pragma once
+#include "csapi/definitions/cross_signing_key.h"
+#include "csapi/definitions/device_keys.h"
+
+#include "e2ee/e2ee.h"
+
#include "jobs/basejob.h"
-#include "csapi/definitions/device_keys.h"
-#include <QtCore/QHash>
-#include "converters.h"
-#include <QtCore/QVariant>
-#include <QtCore/QJsonObject>
+namespace Quotient {
-namespace QMatrixClient
-{
- // Operations
+/*! \brief Upload end-to-end encryption keys.
+ *
+ * Publishes end-to-end encryption keys for the device.
+ */
+class QUOTIENT_API UploadKeysJob : public BaseJob {
+public:
+ /*! \brief Upload end-to-end encryption keys.
+ *
+ * \param deviceKeys
+ * Identity keys for the device. May be absent if no new
+ * identity keys are required.
+ *
+ * \param oneTimeKeys
+ * One-time public keys for "pre-key" messages. The names of
+ * the properties should be in the format
+ * `<algorithm>:<key_id>`. The format of the key is determined
+ * by the [key algorithm](/client-server-api/#key-algorithms).
+ *
+ * May be absent if no new one-time keys are required.
+ *
+ * \param fallbackKeys
+ * The public key which should be used if the device's one-time keys
+ * are exhausted. The fallback key is not deleted once used, but should
+ * be replaced when additional one-time keys are being uploaded. The
+ * server will notify the client of the fallback key being used through
+ * `/sync`.
+ *
+ * There can only be at most one key per algorithm uploaded, and the
+ * server will only persist one key per algorithm.
+ *
+ * When uploading a signed key, an additional `fallback: true` key should
+ * be included to denote that the key is a fallback key.
+ *
+ * May be absent if a new fallback key is not required.
+ */
+ explicit UploadKeysJob(const Omittable<DeviceKeys>& deviceKeys = none,
+ const OneTimeKeys& oneTimeKeys = {},
+ const OneTimeKeys& fallbackKeys = {});
- /// Upload end-to-end encryption keys.
- ///
- /// Publishes end-to-end encryption keys for the device.
- class UploadKeysJob : public BaseJob
+ // Result properties
+
+ /// For each key algorithm, the number of unclaimed one-time keys
+ /// of that type currently held on the server for this device.
+ /// If an algorithm is not listed, the count for that algorithm
+ /// is to be assumed zero.
+ QHash<QString, int> oneTimeKeyCounts() const
{
- public:
- /*! Upload end-to-end encryption keys.
- * \param deviceKeys
- * Identity keys for the device. May be absent if no new
- * identity keys are required.
- * \param oneTimeKeys
- * One-time public keys for "pre-key" messages. The names of
- * the properties should be in the format
- * ``<algorithm>:<key_id>``. The format of the key is determined
- * by the key algorithm.
- *
- * May be absent if no new one-time keys are required.
- */
- explicit UploadKeysJob(const Omittable<DeviceKeys>& deviceKeys = none, const QHash<QString, QVariant>& oneTimeKeys = {});
- ~UploadKeysJob() override;
-
- // Result properties
-
- /// For each key algorithm, the number of unclaimed one-time keys
- /// of that type currently held on the server for this device.
- const QHash<QString, int>& oneTimeKeyCounts() const;
-
- protected:
- Status parseJson(const QJsonDocument& data) override;
-
- private:
- class Private;
- QScopedPointer<Private> d;
+ return loadFromJson<QHash<QString, int>>("one_time_key_counts"_ls);
+ }
+};
+
+/*! \brief Download device identity keys.
+ *
+ * Returns the current devices and identity keys for the given users.
+ */
+class QUOTIENT_API QueryKeysJob : public BaseJob {
+public:
+ // Inner data structures
+
+ /// Additional data added to the device key information
+ /// by intermediate servers, and not covered by the
+ /// signatures.
+ struct UnsignedDeviceInfo {
+ /// The display name which the user set on the device.
+ QString deviceDisplayName;
};
- /// Download device identity keys.
- ///
/// Returns the current devices and identity keys for the given users.
- class QueryKeysJob : public BaseJob
- {
- public:
- // Inner data structures
-
- /// Additional data added to the device key information
- /// by intermediate servers, and not covered by the
- /// signatures.
- struct UnsignedDeviceInfo
- {
- /// The display name which the user set on the device.
- QString deviceDisplayName;
- };
-
- /// Returns the current devices and identity keys for the given users.
- struct DeviceInformation : DeviceKeys
- {
- /// Additional data added to the device key information
- /// by intermediate servers, and not covered by the
- /// signatures.
- Omittable<UnsignedDeviceInfo> unsignedData;
- };
-
- // Construction/destruction
-
- /*! Download device identity keys.
- * \param deviceKeys
- * The keys to be downloaded. A map from user ID, to a list of
- * device IDs, or to an empty list to indicate all devices for the
- * corresponding user.
- * \param timeout
- * The time (in milliseconds) to wait when downloading keys from
- * remote servers. 10 seconds is the recommended default.
- * \param token
- * If the client is fetching keys as a result of a device update received
- * in a sync request, this should be the 'since' token of that sync request,
- * or any later sync token. This allows the server to ensure its response
- * contains the keys advertised by the notification in that sync.
- */
- explicit QueryKeysJob(const QHash<QString, QStringList>& deviceKeys, Omittable<int> timeout = none, const QString& token = {});
- ~QueryKeysJob() override;
-
- // Result properties
-
- /// If any remote homeservers could not be reached, they are
- /// recorded here. The names of the properties are the names of
- /// the unreachable servers.
- ///
- /// If the homeserver could be reached, but the user or device
- /// was unknown, no failure is recorded. Instead, the corresponding
- /// user or device is missing from the ``device_keys`` result.
- const QHash<QString, QJsonObject>& failures() const;
- /// Information on the queried devices. A map from user ID, to a
- /// map from device ID to device information. For each device,
- /// the information returned will be the same as uploaded via
- /// ``/keys/upload``, with the addition of an ``unsigned``
- /// property.
- const QHash<QString, QHash<QString, DeviceInformation>>& deviceKeys() const;
-
- protected:
- Status parseJson(const QJsonDocument& data) override;
-
- private:
- class Private;
- QScopedPointer<Private> d;
+ struct DeviceInformation : DeviceKeys {
+ /// Additional data added to the device key information
+ /// by intermediate servers, and not covered by the
+ /// signatures.
+ Omittable<UnsignedDeviceInfo> unsignedData;
};
- /// Claim one-time encryption keys.
+ // Construction/destruction
+
+ /*! \brief Download device identity keys.
+ *
+ * \param deviceKeys
+ * The keys to be downloaded. A map from user ID, to a list of
+ * device IDs, or to an empty list to indicate all devices for the
+ * corresponding user.
+ *
+ * \param timeout
+ * The time (in milliseconds) to wait when downloading keys from
+ * remote servers. 10 seconds is the recommended default.
+ *
+ * \param token
+ * If the client is fetching keys as a result of a device update received
+ * in a sync request, this should be the 'since' token of that sync
+ * request, or any later sync token. This allows the server to ensure its
+ * response contains the keys advertised by the notification in that sync.
+ */
+ explicit QueryKeysJob(const QHash<QString, QStringList>& deviceKeys,
+ Omittable<int> timeout = none,
+ const QString& token = {});
+
+ // Result properties
+
+ /// If any remote homeservers could not be reached, they are
+ /// recorded here. The names of the properties are the names of
+ /// the unreachable servers.
///
- /// Claims one-time keys for use in pre-key messages.
- class ClaimKeysJob : public BaseJob
+ /// If the homeserver could be reached, but the user or device
+ /// was unknown, no failure is recorded. Instead, the corresponding
+ /// user or device is missing from the `device_keys` result.
+ QHash<QString, QJsonObject> failures() const
{
- public:
- /*! Claim one-time encryption keys.
- * \param oneTimeKeys
- * The keys to be claimed. A map from user ID, to a map from
- * device ID to algorithm name.
- * \param timeout
- * The time (in milliseconds) to wait when downloading keys from
- * remote servers. 10 seconds is the recommended default.
- */
- explicit ClaimKeysJob(const QHash<QString, QHash<QString, QString>>& oneTimeKeys, Omittable<int> timeout = none);
- ~ClaimKeysJob() override;
-
- // Result properties
-
- /// If any remote homeservers could not be reached, they are
- /// recorded here. The names of the properties are the names of
- /// the unreachable servers.
- ///
- /// If the homeserver could be reached, but the user or device
- /// was unknown, no failure is recorded. Instead, the corresponding
- /// user or device is missing from the ``one_time_keys`` result.
- const QHash<QString, QJsonObject>& failures() const;
- /// One-time keys for the queried devices. A map from user ID, to a
- /// map from devices to a map from ``<algorithm>:<key_id>`` to the key object.
- const QHash<QString, QHash<QString, QVariant>>& oneTimeKeys() const;
-
- protected:
- Status parseJson(const QJsonDocument& data) override;
-
- private:
- class Private;
- QScopedPointer<Private> d;
- };
+ return loadFromJson<QHash<QString, QJsonObject>>("failures"_ls);
+ }
+
+ /// Information on the queried devices. A map from user ID, to a
+ /// map from device ID to device information. For each device,
+ /// the information returned will be the same as uploaded via
+ /// `/keys/upload`, with the addition of an `unsigned`
+ /// property.
+ QHash<QString, QHash<QString, DeviceInformation>> deviceKeys() const
+ {
+ return loadFromJson<QHash<QString, QHash<QString, DeviceInformation>>>(
+ "device_keys"_ls);
+ }
+
+ /// Information on the master cross-signing keys of the queried users.
+ /// A map from user ID, to master key information. For each key, the
+ /// information returned will be the same as uploaded via
+ /// `/keys/device_signing/upload`, along with the signatures
+ /// uploaded via `/keys/signatures/upload` that the requesting user
+ /// is allowed to see.
+ QHash<QString, CrossSigningKey> masterKeys() const
+ {
+ return loadFromJson<QHash<QString, CrossSigningKey>>("master_keys"_ls);
+ }
+
+ /// Information on the self-signing keys of the queried users. A map
+ /// from user ID, to self-signing key information. For each key, the
+ /// information returned will be the same as uploaded via
+ /// `/keys/device_signing/upload`.
+ QHash<QString, CrossSigningKey> selfSigningKeys() const
+ {
+ return loadFromJson<QHash<QString, CrossSigningKey>>(
+ "self_signing_keys"_ls);
+ }
- /// Query users with recent device key updates.
+ /// Information on the user-signing key of the user making the
+ /// request, if they queried their own device information. A map
+ /// from user ID, to user-signing key information. The
+ /// information returned will be the same as uploaded via
+ /// `/keys/device_signing/upload`.
+ QHash<QString, CrossSigningKey> userSigningKeys() const
+ {
+ return loadFromJson<QHash<QString, CrossSigningKey>>(
+ "user_signing_keys"_ls);
+ }
+};
+
+template <>
+struct JsonObjectConverter<QueryKeysJob::UnsignedDeviceInfo> {
+ static void fillFrom(const QJsonObject& jo,
+ QueryKeysJob::UnsignedDeviceInfo& result)
+ {
+ fromJson(jo.value("device_display_name"_ls), result.deviceDisplayName);
+ }
+};
+
+template <>
+struct JsonObjectConverter<QueryKeysJob::DeviceInformation> {
+ static void fillFrom(const QJsonObject& jo,
+ QueryKeysJob::DeviceInformation& result)
+ {
+ fillFromJson<DeviceKeys>(jo, result);
+ fromJson(jo.value("unsigned"_ls), result.unsignedData);
+ }
+};
+
+/*! \brief Claim one-time encryption keys.
+ *
+ * Claims one-time keys for use in pre-key messages.
+ */
+class QUOTIENT_API ClaimKeysJob : public BaseJob {
+public:
+ /*! \brief Claim one-time encryption keys.
+ *
+ * \param oneTimeKeys
+ * The keys to be claimed. A map from user ID, to a map from
+ * device ID to algorithm name.
+ *
+ * \param timeout
+ * The time (in milliseconds) to wait when downloading keys from
+ * remote servers. 10 seconds is the recommended default.
+ */
+ explicit ClaimKeysJob(
+ const QHash<QString, QHash<QString, QString>>& oneTimeKeys,
+ Omittable<int> timeout = none);
+
+ // Result properties
+
+ /// If any remote homeservers could not be reached, they are
+ /// recorded here. The names of the properties are the names of
+ /// the unreachable servers.
///
- /// Gets a list of users who have updated their device identity keys since a
- /// previous sync token.
- ///
- /// The server should include in the results any users who:
- ///
- /// * currently share a room with the calling user (ie, both users have
- /// membership state ``join``); *and*
- /// * added new device identity keys or removed an existing device with
- /// identity keys, between ``from`` and ``to``.
- class GetKeysChangesJob : public BaseJob
+ /// If the homeserver could be reached, but the user or device
+ /// was unknown, no failure is recorded. Instead, the corresponding
+ /// user or device is missing from the `one_time_keys` result.
+ QHash<QString, QJsonObject> failures() const
{
- public:
- /*! Query users with recent device key updates.
- * \param from
- * The desired start point of the list. Should be the ``next_batch`` field
- * from a response to an earlier call to |/sync|. Users who have not
- * uploaded new device identity keys since this point, nor deleted
- * existing devices with identity keys since then, will be excluded
- * from the results.
- * \param to
- * The desired end point of the list. Should be the ``next_batch``
- * field from a recent call to |/sync| - typically the most recent
- * such call. This may be used by the server as a hint to check its
- * caches are up to date.
- */
- explicit GetKeysChangesJob(const QString& from, const QString& to);
-
- /*! Construct a URL without creating a full-fledged job object
- *
- * This function can be used when a URL for
- * GetKeysChangesJob is necessary but the job
- * itself isn't.
- */
- static QUrl makeRequestUrl(QUrl baseUrl, const QString& from, const QString& to);
-
- ~GetKeysChangesJob() override;
-
- // Result properties
-
- /// The Matrix User IDs of all users who updated their device
- /// identity keys.
- const QStringList& changed() const;
- /// The Matrix User IDs of all users who may have left all
- /// the end-to-end encrypted rooms they previously shared
- /// with the user.
- const QStringList& left() const;
-
- protected:
- Status parseJson(const QJsonDocument& data) override;
-
- private:
- class Private;
- QScopedPointer<Private> d;
- };
-} // namespace QMatrixClient
+ return loadFromJson<QHash<QString, QJsonObject>>("failures"_ls);
+ }
+
+ /// One-time keys for the queried devices. A map from user ID, to a
+ /// map from devices to a map from `<algorithm>:<key_id>` to the key object.
+ ///
+ /// See the [key algorithms](/client-server-api/#key-algorithms) section for
+ /// information on the Key Object format.
+ ///
+ /// If necessary, the claimed key might be a fallback key. Fallback
+ /// keys are re-used by the server until replaced by the device.
+ QHash<QString, QHash<QString, OneTimeKeys>> oneTimeKeys() const
+ {
+ return loadFromJson<QHash<QString, QHash<QString, OneTimeKeys>>>(
+ "one_time_keys"_ls);
+ }
+};
+
+/*! \brief Query users with recent device key updates.
+ *
+ * Gets a list of users who have updated their device identity keys since a
+ * previous sync token.
+ *
+ * The server should include in the results any users who:
+ *
+ * * currently share a room with the calling user (ie, both users have
+ * membership state `join`); *and*
+ * * added new device identity keys or removed an existing device with
+ * identity keys, between `from` and `to`.
+ */
+class QUOTIENT_API GetKeysChangesJob : public BaseJob {
+public:
+ /*! \brief Query users with recent device key updates.
+ *
+ * \param from
+ * The desired start point of the list. Should be the `next_batch` field
+ * from a response to an earlier call to
+ * [`/sync`](/client-server-api/#get_matrixclientv3sync). Users who have not
+ * uploaded new device identity keys since this point, nor deleted
+ * existing devices with identity keys since then, will be excluded
+ * from the results.
+ *
+ * \param to
+ * The desired end point of the list. Should be the `next_batch`
+ * field from a recent call to
+ * [`/sync`](/client-server-api/#get_matrixclientv3sync) - typically the
+ * most recent such call. This may be used by the server as a hint to check
+ * its caches are up to date.
+ */
+ explicit GetKeysChangesJob(const QString& from, const QString& to);
+
+ /*! \brief Construct a URL without creating a full-fledged job object
+ *
+ * This function can be used when a URL for GetKeysChangesJob
+ * is necessary but the job itself isn't.
+ */
+ static QUrl makeRequestUrl(QUrl baseUrl, const QString& from,
+ const QString& to);
+
+ // Result properties
+
+ /// The Matrix User IDs of all users who updated their device
+ /// identity keys.
+ QStringList changed() const
+ {
+ return loadFromJson<QStringList>("changed"_ls);
+ }
+
+ /// The Matrix User IDs of all users who may have left all
+ /// the end-to-end encrypted rooms they previously shared
+ /// with the user.
+ QStringList left() const { return loadFromJson<QStringList>("left"_ls); }
+};
+
+} // namespace Quotient