File indexing completed on 2024-05-12 13:54:24
0001 /* 0002 * SPDX-License-Identifier: GPL-3.0-or-later 0003 * SPDX-FileCopyrightText: 2020 Johan Ouwerkerk <jm.ouwerkerk@gmail.com> 0004 */ 0005 #ifndef OATH_H 0006 #define OATH_H 0007 0008 #include <QByteArray> 0009 #include <QCryptographicHash> 0010 #include <QDateTime> 0011 #include <QSharedPointer> 0012 0013 #include <functional> 0014 #include <optional> 0015 0016 namespace oath 0017 { 0018 class Encoder 0019 { 0020 public: 0021 Encoder(uint tokenLength, bool addChecksum = false); 0022 virtual ~Encoder(); 0023 virtual QString encode(quint32) const; 0024 uint tokenLength(void) const; 0025 bool checksum(void) const; 0026 static quint32 reduceMod10(quint32 value, uint tokenLength); 0027 private: 0028 Q_DISABLE_COPY_MOVE(Encoder) 0029 private: 0030 static constexpr const quint32 powerTable[10] = { 0031 1, 10, 100, 1'000, 10'000, 100'000, 1'000'000, 10'000'000, 100'000'000, 1'000'000'000 0032 }; 0033 const uint m_tokenLength; 0034 const bool m_addChecksum; 0035 }; 0036 0037 class Algorithm 0038 { 0039 public: 0040 static bool validate(const Encoder *encoder); 0041 static bool validate(QCryptographicHash::Algorithm algorithm, const std::optional<uint> offset); 0042 static std::optional<Algorithm> create(QCryptographicHash::Algorithm algorithm, const std::optional<uint> offset, const QSharedPointer<const Encoder> &encoder, bool requireSaneKeyLength = false); 0043 static std::optional<Algorithm> totp(QCryptographicHash::Algorithm algorithm, uint tokenLength, bool requireSaneKeyLength = false); 0044 static std::optional<Algorithm> hotp(const std::optional<uint> offset, uint tokenLength, bool checksum, bool requireSaneKeyLength = false); 0045 std::optional<QString> compute(quint64 counter, char * secretBuffer, int length) const; 0046 private: 0047 Algorithm(const QSharedPointer<const Encoder> &encoder, const std::function<quint32(const QByteArray &)> &truncation, QCryptographicHash::Algorithm algorithm, bool requireSaneKeyLength); 0048 private: 0049 const QSharedPointer<const Encoder> m_encoder; 0050 const std::function<quint32(const QByteArray &)> m_truncation; 0051 bool m_enforceKeyLength; 0052 const QCryptographicHash::Algorithm m_algorithm; 0053 }; 0054 0055 uint luhnChecksum(quint32 value, uint digits); 0056 std::optional<quint64> count(const QDateTime &epoch, uint timeStep, const std::function<qint64(void)> &clock = &QDateTime::currentMSecsSinceEpoch); 0057 std::optional<QDateTime> fromCounter(quint64 count, const QDateTime &epoch, uint timeStep); 0058 } 0059 0060 #endif