diff options
author | Carl Schwan <carl@carlschwan.eu> | 2021-01-30 01:26:30 +0100 |
---|---|---|
committer | Tobias Fella <fella@posteo.de> | 2021-12-01 21:34:52 +0100 |
commit | 4593856411a2a8e4b82333abd5684b253daab47c (patch) | |
tree | bb03be717418c47d2bcc3c2d2aea3920b9a42bc3 | |
parent | f9f7d130e5768d0f69edc8900d37f540b61fa974 (diff) | |
download | libquotient-4593856411a2a8e4b82333abd5684b253daab47c.tar.gz libquotient-4593856411a2a8e4b82333abd5684b253daab47c.zip |
Add more test and use macro to remove duplicated code
-rw-r--r-- | autotests/testolmaccount.cpp | 343 | ||||
-rw-r--r-- | autotests/testolmaccount.h | 7 | ||||
-rw-r--r-- | lib/crypto/qolmaccount.cpp | 5 |
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; |