/* * SPDX-License-Identifier: GPL-3.0-or-later * SPDX-FileCopyrightText: 2020 Johan Ouwerkerk */ #ifndef OATH_H #define OATH_H #include #include #include #include #include #include namespace oath { class Encoder { public: Encoder(uint tokenLength, bool addChecksum = false); virtual ~Encoder(); virtual QString encode(quint32) const; uint tokenLength(void) const; bool checksum(void) const; static quint32 reduceMod10(quint32 value, uint tokenLength); private: Q_DISABLE_COPY_MOVE(Encoder) private: static constexpr const quint32 powerTable[10] = {1, 10, 100, 1'000, 10'000, 100'000, 1'000'000, 10'000'000, 100'000'000, 1'000'000'000}; const uint m_tokenLength; const bool m_addChecksum; }; class Algorithm { public: static bool validate(const Encoder *encoder); static bool validate(QCryptographicHash::Algorithm algorithm, const std::optional offset); static std::optional create(QCryptographicHash::Algorithm algorithm, const std::optional offset, const QSharedPointer &encoder, bool requireSaneKeyLength = false); static std::optional totp(QCryptographicHash::Algorithm algorithm, uint tokenLength, bool requireSaneKeyLength = false); static std::optional hotp(const std::optional offset, uint tokenLength, bool checksum, bool requireSaneKeyLength = false); std::optional compute(quint64 counter, char *secretBuffer, int length) const; private: Algorithm(const QSharedPointer &encoder, const std::function &truncation, QCryptographicHash::Algorithm algorithm, bool requireSaneKeyLength); private: const QSharedPointer m_encoder; const std::function m_truncation; bool m_enforceKeyLength; const QCryptographicHash::Algorithm m_algorithm; }; uint luhnChecksum(quint32 value, uint digits); std::optional count(const QDateTime &epoch, uint timeStep, const std::function &clock = &QDateTime::currentMSecsSinceEpoch); std::optional fromCounter(quint64 count, const QDateTime &epoch, uint timeStep); } #endif