@@ -5,10 +5,11 @@
|
||||
#include <fmt/format.h>
|
||||
#include <glaze/glaze.hpp>
|
||||
|
||||
constexpr const uint64_t CHALLENGE_VERSION = 1;
|
||||
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_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);
|
||||
@@ -28,6 +29,10 @@ CChallenge::CChallenge(const std::string& jsonResponse) {
|
||||
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;
|
||||
|
||||
@@ -54,9 +59,13 @@ std::string CChallenge::signature() const {
|
||||
}
|
||||
|
||||
bool CChallenge::valid() const {
|
||||
return m_valid;
|
||||
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);
|
||||
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());
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <chrono>
|
||||
|
||||
class CChallenge {
|
||||
public:
|
||||
@@ -10,17 +11,20 @@ class CChallenge {
|
||||
std::string fingerprint() const;
|
||||
std::string challenge() const;
|
||||
std::string signature() const;
|
||||
std::string timestampAsString() const;
|
||||
bool valid() const;
|
||||
|
||||
private:
|
||||
std::string getSigString();
|
||||
std::string getSigString();
|
||||
|
||||
std::string m_sig, m_fingerprint, m_challenge;
|
||||
bool m_valid = false;
|
||||
int m_difficulty = 4;
|
||||
std::string m_sig, m_fingerprint, m_challenge;
|
||||
bool m_valid = false;
|
||||
int m_difficulty = 4;
|
||||
|
||||
std::chrono::system_clock::time_point m_issued;
|
||||
|
||||
struct SChallengeJSON {
|
||||
std::string fingerprint, challenge, sig;
|
||||
std::string fingerprint, challenge, sig, timestamp;
|
||||
int difficulty = 4, solution = 0;
|
||||
};
|
||||
};
|
||||
@@ -98,7 +98,7 @@ std::string CCrypto::sha256(const std::string& in) {
|
||||
}
|
||||
|
||||
bool CCrypto::genKey() {
|
||||
EVP_PKEY_CTX* ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_ED25519, nullptr);
|
||||
EVP_PKEY_CTX* ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_ED25519, nullptr);
|
||||
|
||||
if (!ctx)
|
||||
return false;
|
||||
@@ -178,7 +178,7 @@ bool CCrypto::verifySignature(const std::string& in, const std::string& sig) {
|
||||
|
||||
auto sigAsArr = toByteArr(sig);
|
||||
|
||||
int ret = EVP_DigestVerify(ctx, sigAsArr.data(), sigAsArr.size(), (const unsigned char*)in.c_str(), in.size());
|
||||
int ret = EVP_DigestVerify(ctx, sigAsArr.data(), sigAsArr.size(), (const unsigned char*)in.c_str(), in.size());
|
||||
|
||||
if (ret == 1) {
|
||||
// match
|
||||
|
||||
@@ -296,6 +296,7 @@ void CServerHandler::serveStop(const Pistache::Http::Request& req, Pistache::Htt
|
||||
page.add("challengeNonce", CTinylatesProp(NONCE));
|
||||
page.add("challengeSignature", CTinylatesProp(CHALLENGE.signature()));
|
||||
page.add("challengeFingerprint", CTinylatesProp(CHALLENGE.fingerprint()));
|
||||
page.add("challengeTimestamp", CTinylatesProp(CHALLENGE.timestampAsString()));
|
||||
page.add("checkpointVersion", CTinylatesProp(CHECKPOINT_VERSION));
|
||||
response.send(Pistache::Http::Code::Ok, page.render().value_or("error"));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user