/* * SPDX-License-Identifier: GPL-3.0-or-later * SPDX-FileCopyrightText: 2020 Johan Ouwerkerk */ #include "account/actions_p.h" #include "../../test-utils/spy.h" #include "../test-utils/secret.h" #include #include class ComputeTotpTest : public QObject { Q_OBJECT private Q_SLOTS: void initTestCase(void); void testDefaults(void); void testDefaults_data(void); private: accounts::AccountSecret m_secret; }; // RFC test vector uses the key: 12345678901234567890 static QByteArray rfcSecret("12345678901234567890"); // the RFC test vector consists of 6-character tokens static uint tokenLength = 6; // the default TOTP timestep is 30s static uint timeStep = 30; // the default TOTP epoch is the Unix epoch static QDateTime epoch = QDateTime::fromMSecsSinceEpoch(0); void ComputeTotpTest::initTestCase(void) { QVERIFY2(test::useDummyPassword(&m_secret), "should be able to set up the master key"); } void ComputeTotpTest::testDefaults(void) { QFETCH(qint64, counter); std::function clock([counter](void) -> qint64 { return counter * timeStep * 1000; }); std::optional tokenSecret = test::encrypt(&m_secret, rfcSecret); QVERIFY2(tokenSecret, "should be able to encrypt the token secret"); accounts::ComputeTotp uut(&m_secret, *tokenSecret, tokenLength, epoch, timeStep, accounts::Account::Hash::Sha1, clock); QSignalSpy tokenGenerated(&uut, &accounts::ComputeTotp::otp); QSignalSpy jobFinished(&uut, &accounts::ComputeTotp::finished); uut.run(); QVERIFY2(test::signal_eventually_emitted_once(tokenGenerated), "token should be generated by now"); QVERIFY2(test::signal_eventually_emitted_once(jobFinished), "job should be finished by now"); QTEST(tokenGenerated.at(0).at(0).toString(), "rfc-test-vector"); QCOMPARE(tokenGenerated.at(0).at(2).toDateTime(), QDateTime::fromMSecsSinceEpoch(timeStep * 1000 * (counter + 1))); // from QCOMPARE(tokenGenerated.at(0).at(3).toDateTime(), QDateTime::fromMSecsSinceEpoch(timeStep * 1000 * (counter + 2))); // until } static void define_test_case(int k, const char *expected) { QByteArray output(expected, tokenLength); QTest::newRow(qPrintable(QStringLiteral("RFC 4226 test vector, # time steps = %1").arg(k))) << (qint64)k << QString::fromLocal8Bit(output); } void ComputeTotpTest::testDefaults_data(void) { static const char *corpus[10]{"755224", "287082", "359152", "969429", "338314", "254676", "287922", "162583", "399871", "520489"}; QTest::addColumn("counter"); QTest::addColumn("rfc-test-vector"); for (int k = 0; k < 10; ++k) { define_test_case(k, corpus[k]); } } QTEST_MAIN(ComputeTotpTest) #include "compute-totp.moc"