keysmith/src/oath/oath.h

61 lines
2.4 KiB
C++

/*
* SPDX-License-Identifier: GPL-3.0-or-later
* SPDX-FileCopyrightText: 2020 Johan Ouwerkerk <jm.ouwerkerk@gmail.com>
*/
#ifndef OATH_H
#define OATH_H
#include <QByteArray>
#include <QCryptographicHash>
#include <QDateTime>
#include <QSharedPointer>
#include <functional>
#include <optional>
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<uint> offset);
static std::optional<Algorithm> create(QCryptographicHash::Algorithm algorithm, const std::optional<uint> offset, const QSharedPointer<const Encoder> &encoder, bool requireSaneKeyLength = false);
static std::optional<Algorithm> totp(QCryptographicHash::Algorithm algorithm, uint tokenLength, bool requireSaneKeyLength = false);
static std::optional<Algorithm> hotp(const std::optional<uint> offset, uint tokenLength, bool checksum, bool requireSaneKeyLength = false);
std::optional<QString> compute(quint64 counter, char * secretBuffer, int length) const;
private:
Algorithm(const QSharedPointer<const Encoder> &encoder, const std::function<quint32(const QByteArray &)> &truncation, QCryptographicHash::Algorithm algorithm, bool requireSaneKeyLength);
private:
const QSharedPointer<const Encoder> m_encoder;
const std::function<quint32(const QByteArray &)> m_truncation;
bool m_enforceKeyLength;
const QCryptographicHash::Algorithm m_algorithm;
};
uint luhnChecksum(quint32 value, uint digits);
std::optional<quint64> count(const QDateTime &epoch, uint timeStep, const std::function<qint64(void)> &clock = &QDateTime::currentMSecsSinceEpoch);
std::optional<QDateTime> fromCounter(quint64 count, const QDateTime &epoch, uint timeStep);
}
#endif