/* * SPDX-License-Identifier: GPL-3.0-or-later * SPDX-FileCopyrightText: 2020 Johan Ouwerkerk */ #include "oath/oath.h" #include #include class TotpAlgorithmTest: public QObject { Q_OBJECT private Q_SLOTS: void rfcTestVector(void); void rfcTestVector_data(void); }; void define_test_case(const QString &testCase, const QString &datetime, const QByteArray &secret, QCryptographicHash::Algorithm algorithm, const char *expected) { const QDateTime dt = QDateTime::fromString(datetime, Qt::ISODate); QTest::newRow(qPrintable(testCase.arg(datetime).arg(QLatin1String(expected)))) << dt << ((int) algorithm) << secret << QString(QLatin1String(expected)); } void define_sha1_test_case(const char * datetime, const char *expected) { define_test_case(QLatin1String("%1 (SHA1) ... %2"), QLatin1String(datetime), QByteArray("12345678901234567890"), QCryptographicHash::Sha1, expected); } void define_sha256_test_case(const char * datetime, const char *expected) { define_test_case(QLatin1String("%1 (SHA256) ... %2"), QLatin1String(datetime), QByteArray("12345678901234567890123456789012"), QCryptographicHash::Sha256, expected); } void define_sha512_test_case(const char * datetime, const char *expected) { define_test_case(QLatin1String("%1 (SHA512) ... %2"), QLatin1String(datetime), QByteArray("1234567890123456789012345678901234567890123456789012345678901234"), QCryptographicHash::Sha512, expected); } /* * (Static) test vector params obtained from RFC-6238 * https://tools.ietf.org/html/rfc6238#page-9 */ static const uint tokenLength = 8U; static const QDateTime epoch = QDateTime::fromMSecsSinceEpoch(0); static const uint timeStep = 30U; void TotpAlgorithmTest::rfcTestVector(void) { QFETCH(QDateTime, now); QFETCH(int, hash); QFETCH(QByteArray, secret); std::optional counter = oath::count(epoch, timeStep, [now](void) -> qint64 { return now.toMSecsSinceEpoch(); }); QVERIFY2(counter, "should be able to count timesteps using the settings of the RFC test vector"); std::optional uut = oath::Algorithm::usingDynamicTruncation((QCryptographicHash::Algorithm) hash, tokenLength); QVERIFY2(uut, "should be able to construct the algorithm using settings of the RFC test vector"); QByteArray copy(secret); std::optional result = uut->compute(*counter, copy.data(), copy.size()); QVERIFY2(result, "token should be computed successfully"); QTEST(*result, "rfc-test-vector"); } void TotpAlgorithmTest::rfcTestVector_data(void) { QTest::addColumn("now"); QTest::addColumn("hash"); QTest::addColumn("secret"); QTest::addColumn("rfc-test-vector"); define_sha1_test_case("1970-01-01T00:00:59Z", "94287082"); define_sha256_test_case("1970-01-01T00:00:59Z", "46119246"); define_sha512_test_case("1970-01-01T00:00:59Z", "90693936"); define_sha1_test_case("2005-03-18T01:58:29Z", "07081804"); define_sha256_test_case("2005-03-18T01:58:29Z", "68084774"); define_sha512_test_case("2005-03-18T01:58:29Z", "25091201"); define_sha1_test_case("2005-03-18T01:58:31Z", "14050471"); define_sha256_test_case("2005-03-18T01:58:31Z", "67062674"); define_sha512_test_case("2005-03-18T01:58:31Z", "99943326"); define_sha1_test_case("2009-02-13T23:31:30Z", "89005924"); define_sha256_test_case("2009-02-13T23:31:30Z", "91819424"); define_sha512_test_case("2009-02-13T23:31:30Z", "93441116"); define_sha1_test_case("2033-05-18T03:33:20Z", "69279037"); define_sha256_test_case("2033-05-18T03:33:20Z", "90698825"); define_sha512_test_case("2033-05-18T03:33:20Z", "38618901"); define_sha1_test_case("2603-10-11T11:33:20Z", "65353130"); define_sha256_test_case("2603-10-11T11:33:20Z", "77737706"); define_sha512_test_case("2603-10-11T11:33:20Z", "47863826"); } QTEST_APPLESS_MAIN(TotpAlgorithmTest) #include "totp-algorithm.moc"