Skip to content

Commit

Permalink
udp2p: setup utils (WIP..)
Browse files Browse the repository at this point in the history
  • Loading branch information
rtgiskard committed Sep 28, 2024
1 parent e8cbc2f commit 16870d5
Show file tree
Hide file tree
Showing 8 changed files with 270 additions and 0 deletions.
3 changes: 3 additions & 0 deletions src/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ deps = [
dependency('argparse', version: '>=3.0'),
]

subdir('udp2p/')
deps += udp2p_deps

exe = executable('mtrx',
sources: src,
dependencies: deps,
Expand Down
75 changes: 75 additions & 0 deletions src/udp2p/manager.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#include <spdlog/spdlog.h>
#include <string>

#include "manager.h"

namespace mtrx {
namespace udp2p {

auto logger = spdlog::default_logger()->clone("udp2p");

bool AuthManager::updateUser(const std::string & id, const std::string & hash) {
if (userdb_.contains(id))
logger->info("update user: {}", id);
else
logger->info("add user: {}", id);

userdb_[id] = hash;
return true;
}

bool AuthManager::rmUser(const std::string & id) {
auto it = userdb_.find(id);
if (it == userdb_.end()) {
logger->error("no such user: {}", id);
return false;
}

userdb_.erase(it);
return true;
}

bool AuthManager::authUser(const std::string & id, const std::string & hash) {
auto it = userdb_.find(id);
if (it == userdb_.end()) {
logger->error("no such user: {}", id);
return false;
}
return it->second == hash;
}

bool EndpointManager::updateEndpoint(const std::string & id, const EndPoint & endpoint) {
if (onlineMap_.contains(id))
logger->info("update endpoint: {}", id);
else
logger->info("add endpoint: {}", id);

onlineMap_[id] = endpoint;
return true;
}

bool EndpointManager::rmEndpoint(const std::string & id) {
auto it = onlineMap_.find(id);
if (it == onlineMap_.end()) {
logger->error("no such endpoint: {}", id);
return false;
}

onlineMap_.erase(it);
return true;
};

const EndPoint & EndpointManager::getEndpointByID(const std::string & id) {

auto it = onlineMap_.find(id);
if (it == onlineMap_.end()) {
logger->warn("no such endpoint: {}", id);
static const EndPoint endpoint_zero{};
return endpoint_zero;
}

return onlineMap_[id];
}

} // namespace udp2p
} // namespace mtrx
46 changes: 46 additions & 0 deletions src/udp2p/manager.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#ifndef INCLUDE_UDP2P_MANAGER_H
#define INCLUDE_UDP2P_MANAGER_H

#include <map>
#include <string>

#include <asio.hpp>

namespace mtrx {
namespace udp2p {

struct EndPoint {
asio::ip::address_v4 ip4;
int port;
};

class AuthManager {
public:
AuthManager(){};
~AuthManager(){};

bool authUser(const std::string & id, const std::string & hash);
bool updateUser(const std::string & id, const std::string & hash);
bool rmUser(const std::string & id);

private:
std::map<std::string, std::string> userdb_;
};

class EndpointManager {
public:
EndpointManager(){};
~EndpointManager(){};

bool updateEndpoint(const std::string & id, const EndPoint & endpoint);
bool rmEndpoint(const std::string & id);
const EndPoint & getEndpointByID(const std::string & id);

private:
std::map<std::string, EndPoint> onlineMap_;
};

}; // namespace udp2p
}; // namespace mtrx

#endif
4 changes: 4 additions & 0 deletions src/udp2p/meson.build
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
udp2p_deps = [
dependency('asio'),
dependency('libargon2'),
]
53 changes: 53 additions & 0 deletions src/udp2p/utils.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#include <algorithm>
#include <cstdint>
#include <functional>
#include <random>
#include <string>
#include <argon2.h>

#include "utils.h"

namespace mtrx {
namespace udp2p {
namespace utils {

bool KeyUtils::genRandBytes(uint8_t * buf, const uint32_t size) {
// TODO: seed? better impl?
std::independent_bits_engine<std::default_random_engine, CHAR_BIT, uint8_t> rbe;
std::generate(buf, buf + size, std::ref(rbe));
return true;
}

argon2_context KeyUtils::getHashContext(uint8_t * hash, const uint32_t hash_size,
const std::string & key) {
return argon2_context{
hash, hash_size, /* output hash digest */
const_cast<uint8_t *>(reinterpret_cast<const uint8_t *>(key.c_str())),
static_cast<uint32_t>(key.size()), // key
const_cast<uint8_t *>(reinterpret_cast<const uint8_t *>(salt.c_str())),
static_cast<uint32_t>(salt.size()), // salt
nullptr, 0, /* optional secret data */
nullptr, 0, /* optional associated data */
t_cost, m_cost, paralle, paralle, hash_ver, /* algorithm version */
nullptr, nullptr, /* custom memory allocation / deallocation functions */
/* by default only internal memory is cleared (pwd is not wiped) */
ARGON2_DEFAULT_FLAGS};
}

bool KeyUtils::hashFromKey(uint8_t * hash, const uint32_t hash_size,
const std::string & key) {
auto ctx = getHashContext(hash, hash_size, key);
auto rc = argon2_ctx(&ctx, hash_type);
return (rc == ARGON2_OK);
}

bool KeyUtils::verifyHash(const uint8_t * hash, const uint32_t hash_size,
const std::string & key) {
auto ctx = getHashContext(const_cast<uint8_t *>(hash), hash_size, key);
auto rc = argon2_verify_ctx(&ctx, reinterpret_cast<const char *>(hash), hash_type);
return (rc == ARGON2_OK);
}

}; // namespace utils
}; // namespace udp2p
}; // namespace mtrx
44 changes: 44 additions & 0 deletions src/udp2p/utils.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#ifndef INCLUDE_UDP2P_UTILS_H
#define INCLUDE_UDP2P_UTILS_H

#include <cstdint>
#include <string>

#include <argon2.h>

namespace mtrx {
namespace udp2p {
namespace utils {

// default hash length in byte
constexpr uint8_t HASH_SIZE = 32;
constexpr uint8_t SALT_SIZE = 16;

class KeyUtils {
public:
static bool genRandBytes(uint8_t * buf, const uint32_t size);
static bool hashFromKey(uint8_t * hash, const uint32_t hash_size,
const std::string & key);
static bool verifyHash(const uint8_t * hash, const uint32_t hash_size,
const std::string & key);

private:
static argon2_context getHashContext(uint8_t * hash, const uint32_t hash_size,
const std::string & key);

// TODO: preshared salt, random salt?
constexpr static std::string salt = "somesalt";

constexpr static uint8_t t_cost = 4; // n-pass computation
constexpr static uint32_t m_cost = 1 << 10; // n-MB memory usage
constexpr static uint8_t paralle = 2; // number of threads and lanes

constexpr static argon2_type hash_type = Argon2_id;
constexpr static argon2_version hash_ver = ARGON2_VERSION_13;
};

}; // namespace utils
}; // namespace udp2p
}; // namespace mtrx

#endif
1 change: 1 addition & 0 deletions test/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ src_test = cmd.stdout().strip().split('\n')

src_test += [
'../src/log.cc',
'../src/udp2p/utils.cc',
]

deps_test = deps + [ dependency('doctest') ]
Expand Down
44 changes: 44 additions & 0 deletions test/test_udp2p_utils.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#define DOCTEST_CONFIG_IMPLEMENTATION_IN_DLL
#include "doctest.h"

#include <array>
#include <cstdint>
#include <string>

#include <spdlog/spdlog.h>
#include <spdlog/fmt/bin_to_hex.h>

#include "../src/udp2p/utils.h"

auto logger = spdlog::default_logger();
auto utils = mtrx::udp2p::utils::KeyUtils();

TEST_CASE("gen rand bytes") {
std::array<uint8_t, 20> hash;
utils.genRandBytes(hash.data(), hash.size());
logger->info("1st salt bytes[{}]: {}", hash.size(),
spdlog::to_hex(hash.begin(), hash.end()));

utils.genRandBytes(hash.data(), hash.size());
logger->info("2nd salt bytes[{}]: {}", hash.size(),
spdlog::to_hex(hash.begin(), hash.end()));
}

TEST_CASE("key hash") {
std::string key = "hello";

std::array<uint8_t, mtrx::udp2p::utils::HASH_SIZE> hash;

logger->info("unhash bytes[{}]: {}", hash.size(),
spdlog::to_hex(hash.begin(), hash.end()));
logger->info(utils.verifyHash(hash.data(), hash.size(), key));

logger->info("hash verified bytes[{}]: {}", hash.size(),
spdlog::to_hex(hash.begin(), hash.end()));

utils.hashFromKey(hash.data(), hash.size(), key);

logger->info("hashed bytes[{}]: {}", hash.size(),
spdlog::to_hex(hash.begin(), hash.end()));
CHECK(utils.verifyHash(hash.data(), hash.size(), key));
}

0 comments on commit 16870d5

Please sign in to comment.