#pragma once namespace Utils { namespace Cryptography { void Initialize(); std::string GetEntropy(); class Token { public: Token() { this->tokenString.clear(); } Token(const Token& obj) : tokenString(obj.tokenString) { } Token(const std::string& token) : tokenString(token.begin(), token.end()) { } Token(const std::basic_string& token) : tokenString(token.begin(), token.end()) { } Token& operator++ () { if (this->tokenString.empty()) { this->tokenString.append(reinterpret_cast(const_cast("\0")), 1); } else { for (int i = static_cast(this->tokenString.size() - 1); i >= 0; --i) { if (this->tokenString[i] == 0xFF) { this->tokenString[i] = 0; if (!i) { this->tokenString = std::basic_string{ reinterpret_cast(const_cast("\0")), 1 } + this->tokenString; break; } } else { ++this->tokenString[i]; break; } } } return *this; } Token operator++ (int) { Token result = *this; this->operator++(); return result; } bool operator==(const Token& token) const { return (this->toString() == token.toString()); } bool operator!=(const Token& token) const { return !(*this == token); } bool operator<(const Token& token) const { if (*this == token) { return false; } if (this->toString().size() < token.toString().size()) { return true; } if (this->toString().size() > token.toString().size()) { return false; } auto lStr = this->toString(); auto rStr = token.toString(); for (std::size_t i = 0; i < lStr.size(); ++i) { if (lStr[i] < rStr[i]) { return true; } } return false; } bool operator>(const Token& token) const { return (token < *this && *this != token); } bool operator<=(const Token& token) const { return !(*this > token); } bool operator>=(const Token& token) const { return !(*this < token); } [[nodiscard]] std::string toString() const { return std::string{ this->tokenString.begin(), this->tokenString.end() }; } [[nodiscard]] std::basic_string toUnsignedString() const { return this->tokenString; } void clear() { this->tokenString.clear(); } private: std::basic_string tokenString; }; class Rand { public: static std::string GenerateChallenge(); static std::uint32_t GenerateInt(); static void Initialize(); private: static prng_state State; }; class ECC { public: class Key { public: Key() : keyStorage(new ecc_key) { ZeroMemory(this->getKeyPtr(), sizeof(*this->getKeyPtr())); } Key(ecc_key* key) : Key() { if (key) std::memmove(this->getKeyPtr(), key, sizeof(*key)); } Key(ecc_key key) : Key(&key) {} ~Key() { if (this->keyStorage.use_count() <= 1) { this->free(); } } [[nodiscard]] bool isValid() { return (!Memory::IsSet(this->getKeyPtr(), 0, sizeof(*this->getKeyPtr()))); } [[nodiscard]] ecc_key* getKeyPtr() { return this->keyStorage.get(); } [[nodiscard]] std::string getPublicKey() { std::uint8_t buffer[512]{}; unsigned long length = sizeof(buffer); if (ecc_ansi_x963_export(this->getKeyPtr(), buffer, &length) == CRYPT_OK) { return std::string{ reinterpret_cast(buffer), length }; } return std::string{}; } void set(const std::string& pubKeyBuffer) { this->free(); if (ecc_ansi_x963_import(reinterpret_cast(pubKeyBuffer.data()), pubKeyBuffer.size(), this->getKeyPtr()) != CRYPT_OK) { ZeroMemory(this->getKeyPtr(), sizeof(*this->getKeyPtr())); } } void deserialize(const std::string& key) { this->free(); if (ecc_import(reinterpret_cast(key.data()), key.size(), this->getKeyPtr()) != CRYPT_OK) { ZeroMemory(this->getKeyPtr(), sizeof(*this->getKeyPtr())); } } [[nodiscard]] std::string serialize(int type = PK_PRIVATE) { std::uint8_t buffer[4096]{}; unsigned long length = sizeof(buffer); if (ecc_export(buffer, &length, type, this->getKeyPtr()) == CRYPT_OK) { return std::string{ reinterpret_cast(buffer), length }; } return std::string{}; } void free() { if (this->isValid()) { ecc_free(this->getKeyPtr()); } ZeroMemory(this->getKeyPtr(), sizeof(*this->getKeyPtr())); } bool operator==(Key& key) { return (this->isValid() && key.isValid() && this->serialize(PK_PUBLIC) == key.serialize(PK_PUBLIC)); } private: std::shared_ptr keyStorage; }; static Key GenerateKey(int bits); static std::string SignMessage(Key key, const std::string& message); static bool VerifyMessage(Key key, const std::string& message, const std::string& signature); }; class RSA { public: class Key { public: Key() : keyStorage(new rsa_key) { ZeroMemory(this->getKeyPtr(), sizeof(*this->getKeyPtr())); } Key(rsa_key* key) : Key() { if (key) std::memmove(this->getKeyPtr(), key, sizeof(*key)); } Key(rsa_key key) : Key(&key) {} ~Key() { if (this->keyStorage.use_count() <= 1) { this->free(); } } [[nodiscard]] bool isValid() { return (!Memory::IsSet(this->getKeyPtr(), 0, sizeof(*this->getKeyPtr()))); } [[nodiscard]] rsa_key* getKeyPtr() { return this->keyStorage.get(); } [[nodiscard]] std::string getPublicKey() { std::uint8_t buffer[4096]{}; unsigned long length = sizeof(buffer); if (rsa_export(buffer, &length, PK_PUBLIC, this->getKeyPtr()) == CRYPT_OK) { return std::string{ reinterpret_cast(buffer), length }; } return std::string{}; } void set(const std::string& keyBuffer) { this->free(); if (rsa_import(reinterpret_cast(keyBuffer.data()), keyBuffer.size(), this->getKeyPtr()) != CRYPT_OK) { ZeroMemory(this->getKeyPtr(), sizeof(*this->getKeyPtr())); } } [[nodiscard]] std::string serialize(int type = PK_PRIVATE) { std::uint8_t buffer[4096]{}; unsigned long length = sizeof(buffer); if (rsa_export(buffer, &length, type, this->getKeyPtr()) == CRYPT_OK) { return std::string{ reinterpret_cast(buffer), length }; } return std::string{}; } void free() { if (this->isValid()) { rsa_free(this->getKeyPtr()); } ZeroMemory(this->getKeyPtr(), sizeof(*this->getKeyPtr())); } private: std::shared_ptr keyStorage; }; static Key GenerateKey(int bits); static std::string SignMessage(Key key, const std::string& message); static bool VerifyMessage(Key key, const std::string& message, const std::string& signature); }; class Tiger { public: static std::string Compute(const std::string& data, bool hex = false); static std::string Compute(const std::uint8_t* data, std::size_t length, bool hex = false); }; class SHA1 { public: static std::string Compute(const std::string& data, bool hex = false); static std::string Compute(const std::uint8_t* data, std::size_t length, bool hex = false); }; class SHA256 { public: static std::string Compute(const std::string& data, bool hex = false); static std::string Compute(const std::uint8_t* data, std::size_t length, bool hex = false); }; class SHA512 { public: static std::string Compute(const std::string& data, bool hex = false); static std::string Compute(const std::uint8_t* data, std::size_t length, bool hex = false); }; class JenkinsOneAtATime { public: static std::size_t Compute(const std::string& data); static std::size_t Compute(const char* key, std::size_t len); }; } }