aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarl Schwan <carl@carlschwan.eu>2021-01-30 01:26:30 +0100
committerTobias Fella <fella@posteo.de>2021-12-01 21:34:52 +0100
commit4593856411a2a8e4b82333abd5684b253daab47c (patch)
treebb03be717418c47d2bcc3c2d2aea3920b9a42bc3
parentf9f7d130e5768d0f69edc8900d37f540b61fa974 (diff)
downloadlibquotient-4593856411a2a8e4b82333abd5684b253daab47c.tar.gz
libquotient-4593856411a2a8e4b82333abd5684b253daab47c.zip
Add more test and use macro to remove duplicated code
-rw-r--r--autotests/testolmaccount.cpp343
-rw-r--r--autotests/testolmaccount.h7
-rw-r--r--lib/crypto/qolmaccount.cpp5
3 files changed, 175 insertions, 180 deletions
diff --git a/autotests/testolmaccount.cpp b/autotests/testolmaccount.cpp
index ce51b9ec..5cb88a99 100644
--- a/autotests/testolmaccount.cpp
+++ b/autotests/testolmaccount.cpp
@@ -163,207 +163,130 @@ void TestOlmAccount::encryptedFile()
QCOMPARE(file.key.kty, "oct");
}
+#define CREATE_CONNECTION(VAR, USERNAME, SECRET, DEVICE_NAME) \
+ auto VAR = std::make_shared<Connection>(); \
+ (VAR) ->resolveServer("@alice:localhost:" + QString::number(443)); \
+ connect( (VAR) .get(), &Connection::loginFlowsChanged, this, [this, VAR ] () { \
+ (VAR) ->loginWithPassword( (USERNAME) , SECRET , DEVICE_NAME , ""); \
+ }); \
+ connect( (VAR) .get(), &Connection::networkError, [=](QString error, const QString &, int, int) { \
+ QFAIL("Network error: make sure synapse is running"); \
+ }); \
+ connect( (VAR) .get(), &Connection::loginError, [=](QString error, const QString &) { \
+ QFAIL("Login failed"); \
+ }); \
+ QSignalSpy spy ## VAR ((VAR).get(), &Connection::loginFlowsChanged); \
+ QSignalSpy spy2 ## VAR ((VAR).get(), &Connection::connected); \
+ QVERIFY(spy ## VAR .wait(10000)); \
+ QVERIFY(spy2 ## VAR .wait(10000));
+
void TestOlmAccount::uploadIdentityKey()
{
- auto conn = new Connection();
- conn->resolveServer("@alice:localhost:" + QString::number(443));
- connect(conn, &Connection::loginFlowsChanged, this, [this, conn]() {
- conn->loginWithPassword("alice", "secret", "AlicePhone", "");
- connect(conn, &Connection::connected, this, [this, conn] {
- auto olmAccount = conn->olmAccount();
- auto idKeys = olmAccount->identityKeys();
-
- QVERIFY(idKeys.curve25519.size() > 10);
- QVERIFY(idKeys.curve25519.size() > 10);
-
-
- OneTimeKeys unused;
- auto request = olmAccount->createUploadKeyRequest(unused);
- connect(request, &BaseJob::result, this, [request, conn](BaseJob *job) {
- auto job2 = static_cast<UploadKeysJob *>(job);
- QCOMPARE(job2->oneTimeKeyCounts().size(), 0);
- });
- connect(request, &BaseJob::failure, this, [] {
- QFAIL("upload failed");
- });
- conn->run(request);
- QSignalSpy spy3(request, &BaseJob::result);
- QVERIFY(spy3.wait(10000));
- });
- connect(conn, &Connection::networkError, [=](QString error, const QString &, int, int) {
- QFAIL("Network error: make sure synapse is running");
- });
- connect(conn, &Connection::loginError, [=](QString error, const QString &) {
- QFAIL("Login failed");
- });
- });
+ CREATE_CONNECTION(conn, "alice", "secret", "AlicePhone")
+
+ auto olmAccount = conn->olmAccount();
+ auto idKeys = olmAccount->identityKeys();
- connect(conn, &Connection::resolveError, this, [=](QString error) {
- QFAIL("Network error: make sure synapse is running");
+ QVERIFY(idKeys.curve25519.size() > 10);
+ QVERIFY(idKeys.curve25519.size() > 10);
+
+ OneTimeKeys unused;
+ auto request = olmAccount->createUploadKeyRequest(unused);
+ connect(request, &BaseJob::result, this, [request, conn](BaseJob *job) {
+ auto job2 = static_cast<UploadKeysJob *>(job);
+ QCOMPARE(job2->oneTimeKeyCounts().size(), 0);
});
- connect(conn, &Connection::loginError, this, [=] {
- QFAIL("Network error: make sure synapse is running");
+ connect(request, &BaseJob::failure, this, [] {
+ QFAIL("upload failed");
});
-
- QSignalSpy spy(conn, &Connection::loginFlowsChanged);
- QSignalSpy spy2(conn, &Connection::connected);
- QVERIFY(spy.wait(10000));
- QVERIFY(spy2.wait(10000));
- delete conn;
+ conn->run(request);
+ QSignalSpy spy3(request, &BaseJob::result);
+ QVERIFY(spy3.wait(10000));
}
void TestOlmAccount::uploadOneTimeKeys()
{
- auto conn = new Connection();
- conn->resolveServer("@alice:localhost:" + QString::number(443));
- connect(conn, &Connection::loginFlowsChanged, this, [this, conn]() {
- conn->loginWithPassword("alice", "secret", "AlicePhone", "");
- connect(conn, &Connection::connected, this, [this, conn] {
- auto olmAccount = conn->olmAccount();
-
- auto nKeys = olmAccount->generateOneTimeKeys(5);
- QCOMPARE(nKeys, 5);
-
- auto oneTimeKeys = olmAccount->oneTimeKeys();
-
- QHash<QString, QVariant> oneTimeKeysHash;
- const auto curve = oneTimeKeys.curve25519();
- for (const auto &[keyId, key] : asKeyValueRange(curve)) {
- oneTimeKeysHash["curve25519:"+keyId] = key;
- }
- auto request = new UploadKeysJob(none, oneTimeKeysHash);
- connect(request, &BaseJob::result, this, [request, conn](BaseJob *job) {
- auto job2 = static_cast<UploadKeysJob *>(job);
- QCOMPARE(job2->oneTimeKeyCounts().size(), 1);
- QCOMPARE(job2->oneTimeKeyCounts()["curve25519"], 5);
- });
- connect(request, &BaseJob::failure, this, [] {
- QFAIL("upload failed");
- });
- conn->run(request);
- QSignalSpy spy3(request, &BaseJob::result);
- QVERIFY(spy3.wait(10000));
- });
- });
+ CREATE_CONNECTION(conn, "alice", "secret", "AlicePhone")
+ auto olmAccount = conn->olmAccount();
- QSignalSpy spy(conn, &Connection::loginFlowsChanged);
- QSignalSpy spy2(conn, &Connection::connected);
- QVERIFY(spy.wait(10000));
- QVERIFY(spy2.wait(10000));
- delete conn;
+ auto nKeys = olmAccount->generateOneTimeKeys(5);
+ QCOMPARE(nKeys, 5);
+
+ auto oneTimeKeys = olmAccount->oneTimeKeys();
+
+ QHash<QString, QVariant> oneTimeKeysHash;
+ const auto curve = oneTimeKeys.curve25519();
+ for (const auto &[keyId, key] : asKeyValueRange(curve)) {
+ oneTimeKeysHash["curve25519:"+keyId] = key;
+ }
+ auto request = new UploadKeysJob(none, oneTimeKeysHash);
+ connect(request, &BaseJob::result, this, [request, conn](BaseJob *job) {
+ auto job2 = static_cast<UploadKeysJob *>(job);
+ QCOMPARE(job2->oneTimeKeyCounts().size(), 1);
+ QCOMPARE(job2->oneTimeKeyCounts()["curve25519"], 5);
+ });
+ connect(request, &BaseJob::failure, this, [] {
+ QFAIL("upload failed");
+ });
+ conn->run(request);
+ QSignalSpy spy3(request, &BaseJob::result);
+ QVERIFY(spy3.wait(10000));
}
void TestOlmAccount::uploadSignedOneTimeKeys()
{
- auto conn = new Connection();
- conn->resolveServer("@alice:localhost:" + QString::number(443));
- connect(conn, &Connection::loginFlowsChanged, this, [this, conn]() {
- conn->loginWithPassword("alice", "secret", "AlicePhone", "");
- connect(conn, &Connection::connected, this, [this, conn] {
- auto olmAccount = conn->olmAccount();
- auto nKeys = olmAccount->generateOneTimeKeys(5);
- QCOMPARE(nKeys, 5);
-
- auto oneTimeKeys = olmAccount->oneTimeKeys();
- QHash<QString, QVariant> oneTimeKeysHash;
- const auto signedKey = olmAccount->signOneTimeKeys(oneTimeKeys);
- for (const auto &[keyId, key] : asKeyValueRange(signedKey)) {
- QVariant var;
- var.setValue(key);
- oneTimeKeysHash[keyId] = var;
- }
- auto request = new UploadKeysJob(none, oneTimeKeysHash);
- connect(request, &BaseJob::result, this, [request, nKeys, conn](BaseJob *job) {
- auto job2 = static_cast<UploadKeysJob *>(job);
- QCOMPARE(job2->oneTimeKeyCounts().size(), 1);
- QCOMPARE(job2->oneTimeKeyCounts()["signed_curve25519"], nKeys);
- });
- connect(request, &BaseJob::failure, this, [] {
- QFAIL("upload failed");
- });
- conn->run(request);
- QSignalSpy spy3(request, &BaseJob::result);
- QVERIFY(spy3.wait(10000));
- });
+ CREATE_CONNECTION(conn, "alice", "secret", "AlicePhone")
+ auto olmAccount = conn->olmAccount();
+ auto nKeys = olmAccount->generateOneTimeKeys(5);
+ QCOMPARE(nKeys, 5);
+
+ auto oneTimeKeys = olmAccount->oneTimeKeys();
+ QHash<QString, QVariant> oneTimeKeysHash;
+ const auto signedKey = olmAccount->signOneTimeKeys(oneTimeKeys);
+ for (const auto &[keyId, key] : asKeyValueRange(signedKey)) {
+ QVariant var;
+ var.setValue(key);
+ oneTimeKeysHash[keyId] = var;
+ }
+ auto request = new UploadKeysJob(none, oneTimeKeysHash);
+ connect(request, &BaseJob::result, this, [request, nKeys, conn](BaseJob *job) {
+ auto job2 = static_cast<UploadKeysJob *>(job);
+ QCOMPARE(job2->oneTimeKeyCounts().size(), 1);
+ QCOMPARE(job2->oneTimeKeyCounts()["signed_curve25519"], nKeys);
});
-
- QSignalSpy spy(conn, &Connection::loginFlowsChanged);
- QSignalSpy spy2(conn, &Connection::connected);
- QVERIFY(spy.wait(10000));
- QVERIFY(spy2.wait(10000));
- delete conn;
+ connect(request, &BaseJob::failure, this, [] {
+ QFAIL("upload failed");
+ });
+ conn->run(request);
+ QSignalSpy spy3(request, &BaseJob::result);
+ QVERIFY(spy3.wait(10000));
}
void TestOlmAccount::uploadKeys()
{
- auto conn = new Connection();
- conn->resolveServer("@alice:localhost:" + QString::number(443));
- connect(conn, &Connection::loginFlowsChanged, this, [this, conn]() {
- conn->loginWithPassword("alice", "secret", "AlicePhone", "");
- connect(conn, &Connection::connected, this, [this, conn] {
- auto olmAccount = conn->olmAccount();
- auto idks = olmAccount->identityKeys();
- olmAccount->generateOneTimeKeys(1);
- auto otks = olmAccount->oneTimeKeys();
- auto request = olmAccount->createUploadKeyRequest(otks);
- connect(request, &BaseJob::result, this, [request, conn](BaseJob *job) {
- auto job2 = static_cast<UploadKeysJob *>(job);
- QCOMPARE(job2->oneTimeKeyCounts().size(), 1);
- QCOMPARE(job2->oneTimeKeyCounts()["signed_curve25519"], 1);
- });
- connect(request, &BaseJob::failure, this, [] {
- QFAIL("upload failed");
- });
- conn->run(request);
- QSignalSpy spy3(request, &BaseJob::result);
- QVERIFY(spy3.wait(10000));
- });
+ CREATE_CONNECTION(conn, "alice", "secret", "AlicePhone")
+ auto olmAccount = conn->olmAccount();
+ auto idks = olmAccount->identityKeys();
+ olmAccount->generateOneTimeKeys(1);
+ auto otks = olmAccount->oneTimeKeys();
+ auto request = olmAccount->createUploadKeyRequest(otks);
+ connect(request, &BaseJob::result, this, [request, conn](BaseJob *job) {
+ auto job2 = static_cast<UploadKeysJob *>(job);
+ QCOMPARE(job2->oneTimeKeyCounts().size(), 1);
+ QCOMPARE(job2->oneTimeKeyCounts()["signed_curve25519"], 1);
});
-
- QSignalSpy spy(conn, &Connection::loginFlowsChanged);
- QSignalSpy spy2(conn, &Connection::connected);
- QVERIFY(spy.wait(10000));
- QVERIFY(spy2.wait(10000));
- delete conn;
-}
-
-inline void sleep()
-{
- std::this_thread::sleep_for(std::chrono::milliseconds(100));
+ connect(request, &BaseJob::failure, this, [] {
+ QFAIL("upload failed");
+ });
+ conn->run(request);
+ QSignalSpy spy3(request, &BaseJob::result);
+ QVERIFY(spy3.wait(10000));
}
-
void TestOlmAccount::claimKeys()
{
- auto alice = new Connection();
- alice->resolveServer("@alice:localhost:" + QString::number(443));
- connect(alice, &Connection::loginFlowsChanged, this, [this, alice]() {
- alice->loginWithPassword("alice", "secret", "AlicePhone", "");
- connect(alice, &Connection::connected, this, [this, alice] {
- qDebug() << "alice->accessToken()" << alice->accessToken();
- QVERIFY(!alice->accessToken().isEmpty());
- });
- });
-
- QSignalSpy spy(alice, &Connection::loginFlowsChanged);
- QSignalSpy spy2(alice, &Connection::connected);
- QVERIFY(spy.wait(10000));
- QVERIFY(spy2.wait(10000));
-
- auto bob = new Connection();
- bob->resolveServer("@bob:localhost:" + QString::number(443));
- connect(bob, &Connection::loginFlowsChanged, this, [this, bob]() {
- bob->loginWithPassword("bob", "secret", "BobPhone", "");
- connect(bob, &Connection::connected, this, [this, bob] {
- qDebug() << "bob->accessToken()" << bob->accessToken();
- QVERIFY(!bob->accessToken().isEmpty());
- });
- });
-
- QSignalSpy spy3(bob, &Connection::loginFlowsChanged);
- QSignalSpy spy4(bob, &Connection::connected);
- QVERIFY(spy3.wait(10000));
- QVERIFY(spy4.wait(10000));
+ CREATE_CONNECTION(alice, "alice", "secret", "AlicePhone")
+ CREATE_CONNECTION(bob, "alice", "secret", "AlicePhone")
// Bob uploads his keys.
auto *bobOlm = bob->olmAccount();
@@ -422,8 +345,70 @@ void TestOlmAccount::claimKeys()
//auto contents = oneTimeKey.begin().value();
});
});
- delete bob;
- delete alice;
}
+void TestOlmAccount::claimMultipleKeys()
+{
+ // Login with alice multiple times
+ CREATE_CONNECTION(alice, "alice", "secret", "AlicePhone")
+ CREATE_CONNECTION(alice1, "alice", "secret", "AlicePhone")
+ CREATE_CONNECTION(alice2, "alice", "secret", "AlicePhone")
+
+ auto olm = alice->olmAccount();
+ olm->generateOneTimeKeys(10);
+ auto res = olm->createUploadKeyRequest(olm->oneTimeKeys());
+ alice->run(res);
+ connect(res, &BaseJob::result, this, [res] {
+ QCOMPARE(res->oneTimeKeyCounts().size(), 1);
+ QCOMPARE(res->oneTimeKeyCounts()["signed_curve25519"], 10);
+ });
+ QSignalSpy spy(res, &BaseJob::result);
+
+ auto olm1 = alice1->olmAccount();
+ olm1->generateOneTimeKeys(10);
+ auto res1 = olm1->createUploadKeyRequest(olm1->oneTimeKeys());
+ alice1->run(res1);
+ connect(res1, &BaseJob::result, this, [res1] {
+ QCOMPARE(res1->oneTimeKeyCounts().size(), 1);
+ QCOMPARE(res1->oneTimeKeyCounts()["signed_curve25519"], 10);
+ });
+ QSignalSpy spy1(res1, &BaseJob::result);
+
+ auto olm2 = alice2->olmAccount();
+ olm2->generateOneTimeKeys(10);
+ auto res2 = olm2->createUploadKeyRequest(olm2->oneTimeKeys());
+ alice2->run(res2);
+ connect(res2, &BaseJob::result, this, [res2] {
+ QCOMPARE(res2->oneTimeKeyCounts().size(), 1);
+ QCOMPARE(res2->oneTimeKeyCounts()["signed_curve25519"], 10);
+ });
+ QSignalSpy spy2(res2, &BaseJob::result);
+
+ QVERIFY(spy.wait(10000));
+ QVERIFY(spy1.wait(10000));
+ QVERIFY(spy2.wait(10000));
+
+ // Bob will claim all keys from alice
+ CREATE_CONNECTION(bob, "bob", "secret", "BobPhone")
+
+ QStringList devices_;
+ devices_ << alice->deviceId()
+ << alice1->deviceId()
+ << alice2->deviceId();
+
+ QHash<QString, QHash<QString, QString>> oneTimeKeys;
+ for (const auto &d : devices_) {
+ oneTimeKeys[alice->userId()] = QHash<QString, QString>();
+ oneTimeKeys[alice->userId()][d] = SignedCurve25519Key;
+ }
+ auto job = bob->callApi<ClaimKeysJob>(oneTimeKeys);
+ connect(job, &BaseJob::result, this, [bob, job] {
+ const auto userId = bob->userId();
+ const auto deviceId = bob->deviceId();
+
+ // The device exists.
+ QCOMPARE(job->oneTimeKeys().size(), 1);
+ QCOMPARE(job->oneTimeKeys()[userId].size(), 3);
+ });
+}
QTEST_MAIN(TestOlmAccount)
diff --git a/autotests/testolmaccount.h b/autotests/testolmaccount.h
index 8b2d2e09..b6b9cae4 100644
--- a/autotests/testolmaccount.h
+++ b/autotests/testolmaccount.h
@@ -3,11 +3,17 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
#include <QtTest/QtTest>
+#include <QString>
+
+namespace Quotient {
+ class Connection;
+}
class TestOlmAccount : public QObject
{
Q_OBJECT
+
private Q_SLOTS:
void pickleUnpickedTest();
void identityKeysValid();
@@ -21,4 +27,5 @@ private Q_SLOTS:
void uploadSignedOneTimeKeys();
void uploadKeys();
void claimKeys();
+ void claimMultipleKeys();
};
diff --git a/lib/crypto/qolmaccount.cpp b/lib/crypto/qolmaccount.cpp
index 24fd87f2..750d7318 100644
--- a/lib/crypto/qolmaccount.cpp
+++ b/lib/crypto/qolmaccount.cpp
@@ -272,6 +272,7 @@ bool Quotient::verifyIdentitySignature(const DeviceKeys &deviceKeys,
const auto signingKey = deviceKeys.keys[signKeyId];
const auto signature = deviceKeys.signatures[userId][signKeyId];
+
if (signature.isEmpty()) {
return false;
}
@@ -292,7 +293,9 @@ bool Quotient::ed25519VerifySignature(QString signingKey,
QJsonDocument doc;
doc.setObject(obj);
- auto canonicalJson = doc.toJson();
+ auto canonicalJson = doc.toJson(QJsonDocument::Compact);
+
+ qDebug() << canonicalJson;
QByteArray signingKeyBuf = signingKey.toUtf8();
QOlmUtility utility;