keysmith/autotests/oath/totp-algorithm.cpp

105 lines
3.9 KiB
C++

/*
* SPDX-License-Identifier: GPL-3.0-or-later
* SPDX-FileCopyrightText: 2020 Johan Ouwerkerk <jm.ouwerkerk@gmail.com>
*/
#include "oath/oath.h"
#include <QTest>
#include <QtDebug>
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<quint64> 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<oath::Algorithm> 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<QString> 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<QDateTime>("now");
QTest::addColumn<int>("hash");
QTest::addColumn<QByteArray>("secret");
QTest::addColumn<QString>("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"