#include "loginDb.hpp" #include "databasepool.h" #include #include #include #include #include extern "C" { #include "monocypher.h" } using namespace sqlite_orm; namespace login { constexpr uint32_t SALT_SIZE = 16; constexpr uint32_t PASSWORD_HASH_SIZE = 32; static std::vector getPasswordHash(const std::vector& salt, const std::string password){ std::vector password_hash; password_hash.resize(PASSWORD_HASH_SIZE); crypto_argon2_config config = { .algorithm = CRYPTO_ARGON2_I, /* Argon2i */ .nb_blocks = 100000, /* 100 megabytes */ .nb_passes = 3, /* 3 iterations */ .nb_lanes = 1 /* Single-threaded */ }; crypto_argon2_inputs inputs = { .pass = (uint8_t*)(password.data()), /* User password */ .salt = (uint8_t*)salt.data(), /* Salt for the password */ .pass_size = static_cast(password.size()), /* Password length */ .salt_size = 16 }; crypto_argon2_extras extras = {0}; /* Extra parameters unused */ void *work_area = malloc((size_t)config.nb_blocks * 1024); crypto_argon2((uint8_t*)password_hash.data(), PASSWORD_HASH_SIZE, work_area, config, inputs, extras); free(work_area); return password_hash; } static void createPasswordHash(User& user, const std::string password){ user.salt.resize(SALT_SIZE); user.password_hash.resize(PASSWORD_HASH_SIZE); arc4random_buf(user.salt.data(), SALT_SIZE); user.password_hash = getPasswordHash(user.salt, password); } static bool verifyUser(const User& user, std::string const& password) { const auto hash = getPasswordHash(user.salt, password); return crypto_verify32((uint8_t*)hash.data(), (uint8_t*)user.password_hash.data()) == 0; } int createUser(const std::string& username, const std::string& password){ if (username.empty() || password.empty()) return -1; int64_t id; auto db = dbpool.acquire(); for (auto &u : db->get_all()) { if (u.username == username){ std::cout << "WTF" << std::endl; }; } auto user = db->get_optional( where(c(&login::User::username) == username) ); if (user.has_value()) { id = user.value().id; } else { User usr = newUser(username); createPasswordHash(usr, password); id = db->insert(usr); } dbpool.release(db); return id; } std::optional getUser(const std::string& username){ auto db = dbpool.acquire(); auto user = db->get_all( where(c(&login::User::username) == username) ); dbpool.release(db); if(user.size() > 0){ return user[0]; } return {}; } std::optional getVerifiedUser(const std::string& username, const std::string& password){ auto user = getUser(username); if (!user.has_value()) return {}; if (verifyUser(*user, password)){ return user; } return {}; } }