Files
checkpoint/src/core/Challenge.cpp
2025-04-14 13:26:32 +01:00

72 lines
2.0 KiB
C++

#include "Challenge.hpp"
#include "Crypto.hpp"
#include <fmt/format.h>
#include <glaze/glaze.hpp>
constexpr const uint64_t CHALLENGE_VERSION = 2;
constexpr const uint64_t CHALLENGE_EXPIRE_TIME_S = 600; // 10 minutes
CChallenge::CChallenge(const std::string& fingerprint, const std::string& challenge, int difficulty) :
m_fingerprint(fingerprint), m_challenge(challenge), m_difficulty(difficulty), m_issued(std::chrono::system_clock::now()) {
std::string toSign = getSigString();
m_sig = g_pCrypto->sign(toSign);
m_valid = true;
}
CChallenge::CChallenge(const std::string& jsonResponse) {
auto json = glz::read_json<SChallengeJSON>(jsonResponse);
if (!json.has_value())
return;
SChallengeJSON s = json.value();
m_challenge = s.challenge;
m_fingerprint = s.fingerprint;
m_sig = s.sig;
try {
m_issued = std::chrono::system_clock::time_point(std::chrono::seconds(std::stoull(s.timestamp)));
} catch (std::exception& e) { return; }
if (!g_pCrypto->verifySignature(getSigString(), m_sig))
return;
const auto SHA = g_pCrypto->sha256(m_challenge + std::to_string(s.solution));
for (size_t i = 0; i < m_difficulty; ++i) {
if (SHA.at(i) != '0')
return;
}
m_valid = true;
}
std::string CChallenge::fingerprint() const {
return m_fingerprint;
}
std::string CChallenge::challenge() const {
return m_challenge;
}
std::string CChallenge::signature() const {
return m_sig;
}
bool CChallenge::valid() const {
return m_valid && std::chrono::duration_cast<std::chrono::seconds>(std::chrono::system_clock::now() - m_issued).count() < CHALLENGE_EXPIRE_TIME_S;
}
std::string CChallenge::getSigString() {
return fmt::format("{}-{},{},{}", CHALLENGE_VERSION, m_fingerprint, m_challenge, std::chrono::duration_cast<std::chrono::seconds>(m_issued.time_since_epoch()).count());
}
std::string CChallenge::timestampAsString() const {
return std::to_string(std::chrono::duration_cast<std::chrono::seconds>(m_issued.time_since_epoch()).count());
}