aboutsummaryrefslogtreecommitdiff
path: root/lib/encryptionmanager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/encryptionmanager.cpp')
-rw-r--r--lib/encryptionmanager.cpp236
1 files changed, 119 insertions, 117 deletions
diff --git a/lib/encryptionmanager.cpp b/lib/encryptionmanager.cpp
index 3533d791..46d937b8 100644
--- a/lib/encryptionmanager.cpp
+++ b/lib/encryptionmanager.cpp
@@ -1,112 +1,117 @@
#include "encryptionmanager.h"
-#include <functional>
-#include <memory>
-#include <QtCore/QStringBuilder>
-#include <QtCore/QHash>
-#include <account.h> // QtOlm
-
-#include "csapi/keys.h"
#include "connection.h"
#include "e2ee.h"
+#include "csapi/keys.h"
+
+#include <QtCore/QHash>
+#include <QtCore/QStringBuilder>
+
+#include <account.h> // QtOlm
+#include <functional>
+#include <memory>
+
using namespace QMatrixClient;
using namespace QtOlm;
using std::move;
class EncryptionManager::Private
{
- public:
- explicit Private(const QByteArray& encryptionAccountPickle, float signedKeysProportion, float oneTimeKeyThreshold)
- : signedKeysProportion(move(signedKeysProportion)),
- oneTimeKeyThreshold(move(oneTimeKeyThreshold))
- {
- Q_ASSERT((0 <= signedKeysProportion) && (signedKeysProportion <= 1));
- Q_ASSERT((0 <= oneTimeKeyThreshold) && (oneTimeKeyThreshold <= 1));
- if (encryptionAccountPickle.isEmpty())
- {
- olmAccount.reset(new Account());
- } else {
- olmAccount.reset(new Account(encryptionAccountPickle)); // TODO: passphrase even with qtkeychain?
- }
- /*
- * Note about targetKeysNumber:
- *
- * From: https://github.com/Zil0/matrix-python-sdk/
- * File: matrix_client/crypto/olm_device.py
- *
- * Try to maintain half the number of one-time keys libolm can hold uploaded
- * on the HS. This is because some keys will be claimed by peers but not
- * used instantly, and we want them to stay in libolm, until the limit is reached
- * and it starts discarding keys, starting by the oldest.
- */
- targetKeysNumber = olmAccount->maxOneTimeKeys(); // 2 // see note below
- targetOneTimeKeyCounts =
- {
- {SignedCurve25519Key, qRound(signedKeysProportion * targetKeysNumber)},
- {Curve25519Key, qRound((1-signedKeysProportion) * targetKeysNumber)}
- };
+public:
+ explicit Private(const QByteArray& encryptionAccountPickle,
+ float signedKeysProportion, float oneTimeKeyThreshold)
+ : signedKeysProportion(move(signedKeysProportion))
+ , oneTimeKeyThreshold(move(oneTimeKeyThreshold))
+ {
+ Q_ASSERT((0 <= signedKeysProportion) && (signedKeysProportion <= 1));
+ Q_ASSERT((0 <= oneTimeKeyThreshold) && (oneTimeKeyThreshold <= 1));
+ if (encryptionAccountPickle.isEmpty()) {
+ olmAccount.reset(new Account());
+ } else {
+ olmAccount.reset(
+ new Account(encryptionAccountPickle)); // TODO: passphrase even
+ // with qtkeychain?
}
- ~Private() = default;
+ /*
+ * Note about targetKeysNumber:
+ *
+ * From: https://github.com/Zil0/matrix-python-sdk/
+ * File: matrix_client/crypto/olm_device.py
+ *
+ * Try to maintain half the number of one-time keys libolm can hold
+ * uploaded on the HS. This is because some keys will be claimed by
+ * peers but not used instantly, and we want them to stay in libolm,
+ * until the limit is reached and it starts discarding keys, starting by
+ * the oldest.
+ */
+ targetKeysNumber = olmAccount->maxOneTimeKeys(); // 2 // see note below
+ targetOneTimeKeyCounts = {
+ { SignedCurve25519Key,
+ qRound(signedKeysProportion * targetKeysNumber) },
+ { Curve25519Key,
+ qRound((1 - signedKeysProportion) * targetKeysNumber) }
+ };
+ }
+ ~Private() = default;
- UploadKeysJob* uploadIdentityKeysJob = nullptr;
- UploadKeysJob* uploadOneTimeKeysJob = nullptr;
+ UploadKeysJob* uploadIdentityKeysJob = nullptr;
+ UploadKeysJob* uploadOneTimeKeysJob = nullptr;
- QScopedPointer<Account> olmAccount;
+ QScopedPointer<Account> olmAccount;
- float signedKeysProportion;
- float oneTimeKeyThreshold;
- int targetKeysNumber;
+ float signedKeysProportion;
+ float oneTimeKeyThreshold;
+ int targetKeysNumber;
- void updateKeysToUpload();
- bool oneTimeKeyShouldUpload();
+ void updateKeysToUpload();
+ bool oneTimeKeyShouldUpload();
- QHash<QString, int> oneTimeKeyCounts;
- void setOneTimeKeyCounts(const QHash<QString, int> oneTimeKeyCountsNewValue)
- {
- oneTimeKeyCounts = oneTimeKeyCountsNewValue;
- updateKeysToUpload();
- }
- QHash<QString, int> oneTimeKeysToUploadCounts;
- QHash<QString, int> targetOneTimeKeyCounts;
+ QHash<QString, int> oneTimeKeyCounts;
+ void setOneTimeKeyCounts(const QHash<QString, int> oneTimeKeyCountsNewValue)
+ {
+ oneTimeKeyCounts = oneTimeKeyCountsNewValue;
+ updateKeysToUpload();
+ }
+ QHash<QString, int> oneTimeKeysToUploadCounts;
+ QHash<QString, int> targetOneTimeKeyCounts;
};
-EncryptionManager::EncryptionManager(const QByteArray &encryptionAccountPickle, float signedKeysProportion, float oneTimeKeyThreshold,
- QObject* parent)
- : QObject(parent),
- d(std::make_unique<Private>(std::move(encryptionAccountPickle), std::move(signedKeysProportion), std::move(oneTimeKeyThreshold)))
-{
-
-}
+EncryptionManager::EncryptionManager(const QByteArray& encryptionAccountPickle,
+ float signedKeysProportion,
+ float oneTimeKeyThreshold, QObject* parent)
+ : QObject(parent)
+ , d(std::make_unique<Private>(std::move(encryptionAccountPickle),
+ std::move(signedKeysProportion),
+ std::move(oneTimeKeyThreshold)))
+{}
EncryptionManager::~EncryptionManager() = default;
void EncryptionManager::uploadIdentityKeys(Connection* connection)
{
// https://matrix.org/docs/spec/client_server/latest#post-matrix-client-r0-keys-upload
- DeviceKeys deviceKeys
- {
+ DeviceKeys deviceKeys {
/*
- * The ID of the user the device belongs to. Must match the user ID used when logging in.
- * The ID of the device these keys belong to. Must match the device ID used when logging in.
- * The encryption algorithms supported by this device.
+ * The ID of the user the device belongs to. Must match the user ID used
+ * when logging in. The ID of the device these keys belong to. Must
+ * match the device ID used when logging in. The encryption algorithms
+ * supported by this device.
*/
- connection->userId(), connection->deviceId(), SupportedAlgorithms,
+ connection->userId(),
+ connection->deviceId(),
+ SupportedAlgorithms,
/*
- * Public identity keys. The names of the properties should be in the format <algorithm>:<device_id>.
- * The keys themselves should be encoded as specified by the key algorithm.
+ * Public identity keys. The names of the properties should be in the
+ * format <algorithm>:<device_id>. The keys themselves should be encoded
+ * as specified by the key algorithm.
*/
- {
- {
- Curve25519Key + QStringLiteral(":") + connection->deviceId(),
- d->olmAccount->curve25519IdentityKey()
- },
- {
- Ed25519Key + QStringLiteral(":") + connection->deviceId(),
- d->olmAccount->ed25519IdentityKey()
- }
- },
- /* signatures should be provided after the unsigned deviceKeys generation */
+ { { Curve25519Key + QStringLiteral(":") + connection->deviceId(),
+ d->olmAccount->curve25519IdentityKey() },
+ { Ed25519Key + QStringLiteral(":") + connection->deviceId(),
+ d->olmAccount->ed25519IdentityKey() } },
+ /* signatures should be provided after the unsigned deviceKeys
+ generation */
{}
};
@@ -118,20 +123,14 @@ void EncryptionManager::uploadIdentityKeys(Connection* connection)
deviceKeysJsonObject.remove(QStringLiteral("signatures"));
/*
* Signatures for the device key object.
- * A map from user ID, to a map from <algorithm>:<device_id> to the signature.
- * The signature is calculated using the process called Signing JSON.
+ * A map from user ID, to a map from <algorithm>:<device_id> to the
+ * signature. The signature is calculated using the process called Signing
+ * JSON.
*/
- deviceKeys.signatures =
- {
- {
- connection->userId(),
- {
- {
- Ed25519Key + QStringLiteral(":") + connection->deviceId(),
- d->olmAccount->sign(deviceKeysJsonObject)
- }
- }
- }
+ deviceKeys.signatures = {
+ { connection->userId(),
+ { { Ed25519Key + QStringLiteral(":") + connection->deviceId(),
+ d->olmAccount->sign(deviceKeysJsonObject) } } }
};
connect(d->uploadIdentityKeysJob, &BaseJob::success, this, [this] {
@@ -141,37 +140,37 @@ void EncryptionManager::uploadIdentityKeys(Connection* connection)
d->uploadIdentityKeysJob = connection->callApi<UploadKeysJob>(deviceKeys);
}
-void EncryptionManager::uploadOneTimeKeys(Connection* connection, bool forceUpdate)
+void EncryptionManager::uploadOneTimeKeys(Connection* connection,
+ bool forceUpdate)
{
- if (forceUpdate || d->oneTimeKeyCounts.isEmpty())
- {
+ if (forceUpdate || d->oneTimeKeyCounts.isEmpty()) {
auto job = connection->callApi<UploadKeysJob>();
- connect(job, &BaseJob::success, this, [job,this] {
+ connect(job, &BaseJob::success, this, [job, this] {
d->setOneTimeKeyCounts(job->oneTimeKeyCounts());
});
-
}
- int signedKeysToUploadCount = d->oneTimeKeysToUploadCounts.value(SignedCurve25519Key, 0);
- int unsignedKeysToUploadCount = d->oneTimeKeysToUploadCounts.value(Curve25519Key, 0);
+ int signedKeysToUploadCount =
+ d->oneTimeKeysToUploadCounts.value(SignedCurve25519Key, 0);
+ int unsignedKeysToUploadCount =
+ d->oneTimeKeysToUploadCounts.value(Curve25519Key, 0);
- d->olmAccount->generateOneTimeKeys(signedKeysToUploadCount + unsignedKeysToUploadCount);
+ d->olmAccount->generateOneTimeKeys(signedKeysToUploadCount
+ + unsignedKeysToUploadCount);
QHash<QString, QVariant> oneTimeKeys = {};
- const auto& olmAccountCurve25519OneTimeKeys = d->olmAccount->curve25519OneTimeKeys();
+ const auto& olmAccountCurve25519OneTimeKeys =
+ d->olmAccount->curve25519OneTimeKeys();
int oneTimeKeysCounter = 0;
- for (auto it = olmAccountCurve25519OneTimeKeys.cbegin(); it != olmAccountCurve25519OneTimeKeys.cend(); ++it)
- {
+ for (auto it = olmAccountCurve25519OneTimeKeys.cbegin();
+ it != olmAccountCurve25519OneTimeKeys.cend(); ++it) {
QString keyId = it.key();
QString keyType;
QVariant key;
- if (oneTimeKeysCounter < signedKeysToUploadCount)
- {
- QJsonObject message
- {
- {QStringLiteral("key"), it.value().toString()}
- };
+ if (oneTimeKeysCounter < signedKeysToUploadCount) {
+ QJsonObject message { { QStringLiteral("key"),
+ it.value().toString() } };
key = d->olmAccount->sign(message);
keyType = SignedCurve25519Key;
@@ -183,10 +182,12 @@ void EncryptionManager::uploadOneTimeKeys(Connection* connection, bool forceUpda
oneTimeKeys.insert(QString("%1:%2").arg(keyType).arg(keyId), key);
}
- d->uploadOneTimeKeysJob = connection->callApi<UploadKeysJob>(none, oneTimeKeys);
+ d->uploadOneTimeKeysJob = connection->callApi<UploadKeysJob>(none,
+ oneTimeKeys);
d->olmAccount->markKeysAsPublished();
qDebug() << QString("Uploaded new one-time keys: %1 signed, %2 unsigned.")
- .arg(signedKeysToUploadCount).arg(unsignedKeysToUploadCount);
+ .arg(signedKeysToUploadCount)
+ .arg(unsignedKeysToUploadCount);
}
QByteArray EncryptionManager::olmAccountPickle()
@@ -201,8 +202,8 @@ QtOlm::Account* EncryptionManager::account() const
void EncryptionManager::Private::updateKeysToUpload()
{
- for (auto it = targetOneTimeKeyCounts.cbegin(); it != targetOneTimeKeyCounts.cend(); ++it)
- {
+ for (auto it = targetOneTimeKeyCounts.cbegin();
+ it != targetOneTimeKeyCounts.cend(); ++it) {
int numKeys = oneTimeKeyCounts.value(it.key(), 0);
int numToCreate = qMax(it.value() - numKeys, 0);
oneTimeKeysToUploadCounts.insert(it.key(), numToCreate);
@@ -213,9 +214,10 @@ bool EncryptionManager::Private::oneTimeKeyShouldUpload()
{
if (oneTimeKeyCounts.empty())
return true;
- for (auto it = targetOneTimeKeyCounts.cbegin(); it != targetOneTimeKeyCounts.cend(); ++it)
- {
- if (oneTimeKeyCounts.value(it.key(), 0) < it.value() * oneTimeKeyThreshold)
+ for (auto it = targetOneTimeKeyCounts.cbegin();
+ it != targetOneTimeKeyCounts.cend(); ++it) {
+ if (oneTimeKeyCounts.value(it.key(), 0)
+ < it.value() * oneTimeKeyThreshold)
return true;
}
return false;