POW (aka. hashcash) stuff.
This commit is contained in:
parent
00b7e3f920
commit
bcdc555c4a
@ -145,7 +145,7 @@ namespace Assets
|
|||||||
{
|
{
|
||||||
if (asset->lods[i].surfaces)
|
if (asset->lods[i].surfaces)
|
||||||
{
|
{
|
||||||
// Requiring this asset is not possible, as it has to be loaded after the model
|
// Requiring this asset is not possible, as it has to be loaded as part of the model
|
||||||
//dest->lods[i].surfaces = builder->RequireAsset(Game::XAssetType::ASSET_TYPE_XMODELSURFS, asset->lods[i].surfaces->name).surfaces;
|
//dest->lods[i].surfaces = builder->RequireAsset(Game::XAssetType::ASSET_TYPE_XMODELSURFS, asset->lods[i].surfaces->name).surfaces;
|
||||||
|
|
||||||
IXModelSurfs().Save({ asset->lods[i].surfaces }, builder);
|
IXModelSurfs().Save({ asset->lods[i].surfaces }, builder);
|
||||||
|
@ -4,6 +4,9 @@ namespace Components
|
|||||||
{
|
{
|
||||||
Auth::AuthInfo Auth::ClientAuthInfo[18];
|
Auth::AuthInfo Auth::ClientAuthInfo[18];
|
||||||
|
|
||||||
|
Utils::Cryptography::Token Auth::GuidToken;
|
||||||
|
Utils::Cryptography::ECDSA::Key Auth::GuidKey;
|
||||||
|
|
||||||
void Auth::Frame()
|
void Auth::Frame()
|
||||||
{
|
{
|
||||||
for (int i = 0; i < *Game::svs_numclients; i++)
|
for (int i = 0; i < *Game::svs_numclients; i++)
|
||||||
@ -79,8 +82,98 @@ namespace Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned int Auth::GetKeyHash()
|
||||||
|
{
|
||||||
|
Auth::LoadKey();
|
||||||
|
std::string key = Auth::GuidKey.GetPublicKey();
|
||||||
|
return (Utils::OneAtATime(key.data(), key.size()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Auth::StoreKey()
|
||||||
|
{
|
||||||
|
Proto::Auth::Certificate cert;
|
||||||
|
cert.set_token(Auth::GuidToken.ToString());
|
||||||
|
cert.set_privatekey(Auth::GuidKey.Export(PK_PRIVATE));
|
||||||
|
|
||||||
|
Utils::WriteFile("players/guid.dat", cert.SerializeAsString());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Auth::LoadKey(bool force)
|
||||||
|
{
|
||||||
|
if (!force && Auth::GuidKey.IsValid()) return;
|
||||||
|
|
||||||
|
Proto::Auth::Certificate cert;
|
||||||
|
if (cert.ParseFromString(::Utils::ReadFile("players/guid.dat")))
|
||||||
|
{
|
||||||
|
Auth::GuidKey.Import(cert.privatekey(), PK_PRIVATE);
|
||||||
|
Auth::GuidToken = cert.token();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Auth::GuidKey.Free();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Auth::GuidKey.IsValid())
|
||||||
|
{
|
||||||
|
Auth::GuidToken.Clear();
|
||||||
|
Auth::GuidKey = Utils::Cryptography::ECDSA::GenerateKey(512);
|
||||||
|
Auth::StoreKey();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t Auth::GetSecurityLevel()
|
||||||
|
{
|
||||||
|
return Auth::GetZeroBits(Auth::GuidToken, Auth::GuidKey.GetPublicKey());
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t Auth::GetZeroBits(Utils::Cryptography::Token token, std::string publicKey)
|
||||||
|
{
|
||||||
|
std::string message = publicKey + token.ToString();
|
||||||
|
std::string hash = Utils::Cryptography::SHA512::Compute(message, false);
|
||||||
|
|
||||||
|
uint32_t bits = 0;
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < hash.size(); ++i)
|
||||||
|
{
|
||||||
|
if (hash[i] == '\0')
|
||||||
|
{
|
||||||
|
bits += 8;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t value = static_cast<uint8_t>(hash[i]);
|
||||||
|
for (int j = 7; j >= 0; --j)
|
||||||
|
{
|
||||||
|
if ((value >> j) & 1)
|
||||||
|
{
|
||||||
|
return bits;
|
||||||
|
}
|
||||||
|
|
||||||
|
bits++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return bits;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Auth::IncrementToken(Utils::Cryptography::Token& token, std::string publicKey, uint32_t zeroBits)
|
||||||
|
{
|
||||||
|
if (zeroBits > 512) return; // Not possible, due to SHA512
|
||||||
|
|
||||||
|
Utils::Cryptography::Token tempToken(token);
|
||||||
|
|
||||||
|
while (Auth::GetZeroBits(tempToken, publicKey) < zeroBits)
|
||||||
|
{
|
||||||
|
++tempToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
token = tempToken;
|
||||||
|
}
|
||||||
|
|
||||||
Auth::Auth()
|
Auth::Auth()
|
||||||
{
|
{
|
||||||
|
Auth::LoadKey(true);
|
||||||
|
|
||||||
// Only clients receive the auth request
|
// Only clients receive the auth request
|
||||||
if (!Dedicated::IsDedicated())
|
if (!Dedicated::IsDedicated())
|
||||||
{
|
{
|
||||||
@ -93,11 +186,12 @@ namespace Components
|
|||||||
|
|
||||||
// Ensure our certificate is loaded
|
// Ensure our certificate is loaded
|
||||||
Steam::SteamUser()->GetSteamID();
|
Steam::SteamUser()->GetSteamID();
|
||||||
if (!Steam::User::GuidKey.IsValid()) return;
|
if (!Auth::GuidKey.IsValid()) return;
|
||||||
|
|
||||||
Proto::Auth::Response response;
|
Proto::Auth::Response response;
|
||||||
response.set_publickey(Steam::User::GuidKey.GetPublicKey());
|
response.set_token(Auth::GuidToken.ToString());
|
||||||
response.set_signature(Utils::Cryptography::ECDSA::SignMessage(Steam::User::GuidKey, data));
|
response.set_publickey(Auth::GuidKey.GetPublicKey());
|
||||||
|
response.set_signature(Utils::Cryptography::ECDSA::SignMessage(Auth::GuidKey, data));
|
||||||
|
|
||||||
Network::SendCommand(address, "xuidAuthResp", response.SerializeAsString());
|
Network::SendCommand(address, "xuidAuthResp", response.SerializeAsString());
|
||||||
});
|
});
|
||||||
@ -118,7 +212,7 @@ namespace Components
|
|||||||
unsigned int id = static_cast<unsigned int>(~0x110000100000000 & client->steamid);
|
unsigned int id = static_cast<unsigned int>(~0x110000100000000 & client->steamid);
|
||||||
|
|
||||||
// Check if response is valid
|
// Check if response is valid
|
||||||
if (!response.ParseFromString(data) || response.signature().empty() || response.publickey().empty())
|
if (!response.ParseFromString(data) || response.signature().empty() || response.publickey().empty() || response.token().empty())
|
||||||
{
|
{
|
||||||
info->state = Auth::STATE_INVALID;
|
info->state = Auth::STATE_INVALID;
|
||||||
Game::SV_KickClientError(client, "XUID authentication response was invalid!");
|
Game::SV_KickClientError(client, "XUID authentication response was invalid!");
|
||||||
@ -138,8 +232,19 @@ namespace Components
|
|||||||
|
|
||||||
if (Utils::Cryptography::ECDSA::VerifyMessage(info->publicKey, info->challenge, response.signature()))
|
if (Utils::Cryptography::ECDSA::VerifyMessage(info->publicKey, info->challenge, response.signature()))
|
||||||
{
|
{
|
||||||
info->state = Auth::STATE_VALID;
|
uint32_t ourLevel = static_cast<uint32_t>(Dvar::Var("sv_securityLevel").Get<int>());
|
||||||
Logger::Print("Verified XUID %llX from %s\n", client->steamid, address.GetString());
|
uint32_t userLevel = Auth::GetZeroBits(response.token(), response.publickey());
|
||||||
|
|
||||||
|
if (userLevel >= ourLevel)
|
||||||
|
{
|
||||||
|
info->state = Auth::STATE_VALID;
|
||||||
|
Logger::Print("Verified XUID %llX from %s\n", client->steamid, address.GetString());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
info->state = Auth::STATE_INVALID;
|
||||||
|
Game::SV_KickClientError(client, Utils::VA("Your security level (%d) does not match the server's security level (%d)", userLevel, ourLevel));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -157,17 +262,48 @@ namespace Components
|
|||||||
Dedicated::OnFrame(Auth::Frame);
|
Dedicated::OnFrame(Auth::Frame);
|
||||||
Renderer::OnFrame(Auth::Frame);
|
Renderer::OnFrame(Auth::Frame);
|
||||||
|
|
||||||
|
// Register dvar
|
||||||
|
Dvar::Register<int>("sv_securityLevel", 20, 0, 512, Game::dvar_flag::DVAR_FLAG_SERVERINFO, "Security level for GUID certificates (POW)");
|
||||||
|
|
||||||
// Install registration hook
|
// Install registration hook
|
||||||
Utils::Hook(0x478A12, Auth::RegisterClientStub, HOOK_JUMP).Install()->Quick();
|
Utils::Hook(0x478A12, Auth::RegisterClientStub, HOOK_JUMP).Install()->Quick();
|
||||||
|
|
||||||
|
// Guid command
|
||||||
|
Command::Add("guid", [] (Command::Params params)
|
||||||
|
{
|
||||||
|
Logger::Print("Your guid: %llX\n", Steam::SteamUser()->GetSteamID().Bits);
|
||||||
|
});
|
||||||
|
|
||||||
|
Command::Add("securityLevel", [] (Command::Params params)
|
||||||
|
{
|
||||||
|
if (params.Length() < 2)
|
||||||
|
{
|
||||||
|
Logger::Print("Your current security level is %d\n", Auth::GetZeroBits(Auth::GuidToken, Auth::GuidKey.GetPublicKey()));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uint32_t level = static_cast<uint32_t>(atoi(params[1]));
|
||||||
|
Logger::Print("Incrementing security level from %d to %d...\n", Auth::GetSecurityLevel(), level);
|
||||||
|
Auth::IncrementToken(Auth::GuidToken, Auth::GuidKey.GetPublicKey(), level);
|
||||||
|
Logger::Print("Your new security level is %d\n", Auth::GetSecurityLevel());
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Auth::~Auth()
|
Auth::~Auth()
|
||||||
{
|
{
|
||||||
|
Auth::StoreKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Auth::UnitTest()
|
bool Auth::UnitTest()
|
||||||
{
|
{
|
||||||
|
// Utils::Cryptography::Token t;
|
||||||
|
// auto _key = Utils::Cryptography::ECDSA::GenerateKey(512);
|
||||||
|
// Auth::IncrementToken(t, _key.GetPublicKey(), 22);
|
||||||
|
//
|
||||||
|
// Utils::WriteFile("pubKey.dat", _key.GetPublicKey());
|
||||||
|
// Utils::WriteFile("token.dat", t.ToString());
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Utils::Cryptography::Token t;
|
Utils::Cryptography::Token t;
|
||||||
for (int i = 0; i < 1'000'000; ++i, ++t)
|
for (int i = 0; i < 1'000'000; ++i, ++t)
|
||||||
@ -175,6 +311,40 @@ namespace Components
|
|||||||
printf("%s\n", Utils::DumpHex(t.ToString()).data());
|
printf("%s\n", Utils::DumpHex(t.ToString()).data());
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
// auto testSecurityLevel = [](size_t level, std::string key)
|
||||||
|
// {
|
||||||
|
// auto startTime = std::chrono::high_resolution_clock::now();
|
||||||
|
// Utils::Cryptography::Token t;
|
||||||
|
// Auth::IncrementToken(t, key, level);
|
||||||
|
// return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - startTime).count();
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// for (int j = 10; j < 30; ++j)
|
||||||
|
// {
|
||||||
|
// printf("\nTesting security level %i:\n", j);
|
||||||
|
//
|
||||||
|
// std::vector<long long> times;
|
||||||
|
//
|
||||||
|
// for (int i = 0; i < 10; ++i)
|
||||||
|
// {
|
||||||
|
// auto key = Utils::Cryptography::ECDSA::GenerateKey(512);
|
||||||
|
//
|
||||||
|
// auto time = testSecurityLevel(j, key.GetPublicKey());
|
||||||
|
// times.push_back(time);
|
||||||
|
// printf("\t%i: %llims\n", i, time);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// long long average = 0;
|
||||||
|
//
|
||||||
|
// for (auto time : times)
|
||||||
|
// {
|
||||||
|
// average += time;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// average /= times.size();
|
||||||
|
//
|
||||||
|
// printf("\n Average: %llims\n", average);
|
||||||
|
// }
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,14 @@ namespace Components
|
|||||||
const char* GetName() { return "Auth"; };
|
const char* GetName() { return "Auth"; };
|
||||||
bool UnitTest();
|
bool UnitTest();
|
||||||
|
|
||||||
|
static void StoreKey();
|
||||||
|
static void LoadKey(bool force = false);
|
||||||
|
static unsigned int GetKeyHash();
|
||||||
|
|
||||||
|
static uint32_t GetSecurityLevel();
|
||||||
|
static uint32_t GetZeroBits(Utils::Cryptography::Token token, std::string publicKey);
|
||||||
|
static void IncrementToken(Utils::Cryptography::Token& token, std::string publicKey, uint32_t zeroBits);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
enum AuthState
|
enum AuthState
|
||||||
@ -28,6 +36,9 @@ namespace Components
|
|||||||
|
|
||||||
static AuthInfo ClientAuthInfo[18];
|
static AuthInfo ClientAuthInfo[18];
|
||||||
|
|
||||||
|
static Utils::Cryptography::Token GuidToken;
|
||||||
|
static Utils::Cryptography::ECDSA::Key GuidKey;
|
||||||
|
|
||||||
static void Frame();
|
static void Frame();
|
||||||
|
|
||||||
static void RegisterClient(int clientNum);
|
static void RegisterClient(int clientNum);
|
||||||
|
@ -284,6 +284,7 @@ namespace Components
|
|||||||
info.Set("mapname", Dvar::Var("mapname").Get<const char*>());
|
info.Set("mapname", Dvar::Var("mapname").Get<const char*>());
|
||||||
info.Set("isPrivate", (Dvar::Var("g_password").Get<std::string>().size() ? "1" : "0"));
|
info.Set("isPrivate", (Dvar::Var("g_password").Get<std::string>().size() ? "1" : "0"));
|
||||||
info.Set("hc", (Dvar::Var("g_hardcore").Get<bool>() ? "1" : "0"));
|
info.Set("hc", (Dvar::Var("g_hardcore").Get<bool>() ? "1" : "0"));
|
||||||
|
info.Set("securityLevel", Utils::VA("%i", Dvar::Var("sv_securityLevel").Get<int>()));
|
||||||
|
|
||||||
// Ensure mapname is set
|
// Ensure mapname is set
|
||||||
if (info.Get("mapname").empty())
|
if (info.Get("mapname").empty())
|
||||||
@ -325,11 +326,16 @@ namespace Components
|
|||||||
Party::Container.Valid = false;
|
Party::Container.Valid = false;
|
||||||
|
|
||||||
int matchType = atoi(info.Get("matchtype").data());
|
int matchType = atoi(info.Get("matchtype").data());
|
||||||
|
uint32_t securityLevel = static_cast<uint32_t>(atoi(info.Get("securityLevel").data()));
|
||||||
|
|
||||||
if (info.Get("challenge") != Party::Container.Challenge)
|
if (info.Get("challenge") != Party::Container.Challenge)
|
||||||
{
|
{
|
||||||
Party::ConnectError("Invalid join response: Challenge mismatch.");
|
Party::ConnectError("Invalid join response: Challenge mismatch.");
|
||||||
}
|
}
|
||||||
|
else if (securityLevel > Auth::GetSecurityLevel())
|
||||||
|
{
|
||||||
|
Party::ConnectError(Utils::VA("Your security level (%d) is lower than the server's (%d)", Auth::GetSecurityLevel(), securityLevel));
|
||||||
|
}
|
||||||
else if (!matchType)
|
else if (!matchType)
|
||||||
{
|
{
|
||||||
Party::ConnectError("Server is not hosting a match.");
|
Party::ConnectError("Server is not hosting a match.");
|
||||||
|
@ -6,6 +6,7 @@ message Response
|
|||||||
{
|
{
|
||||||
bytes signature = 1;
|
bytes signature = 1;
|
||||||
bytes publickey = 2;
|
bytes publickey = 2;
|
||||||
|
bytes token = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
message Certificate
|
message Certificate
|
||||||
|
@ -108,4 +108,4 @@
|
|||||||
#define Assert_Size(x, size) static_assert(sizeof(x) == size, STRINGIZE(x) " structure has an invalid size.")
|
#define Assert_Size(x, size) static_assert(sizeof(x) == size, STRINGIZE(x) " structure has an invalid size.")
|
||||||
|
|
||||||
// Enable unit-test flag for release builds
|
// Enable unit-test flag for release builds
|
||||||
//#define FORCE_UNIT_TESTS
|
#define FORCE_UNIT_TESTS
|
||||||
|
@ -2,9 +2,6 @@
|
|||||||
|
|
||||||
namespace Steam
|
namespace Steam
|
||||||
{
|
{
|
||||||
::Utils::Cryptography::Token User::GuidToken;
|
|
||||||
::Utils::Cryptography::ECDSA::Key User::GuidKey;
|
|
||||||
|
|
||||||
int User::GetHSteamUser()
|
int User::GetHSteamUser()
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -27,32 +24,9 @@ namespace Steam
|
|||||||
{
|
{
|
||||||
subId = ~0xDED1CA7E;
|
subId = ~0xDED1CA7E;
|
||||||
}
|
}
|
||||||
else if (Components::Singleton::IsFirstInstance()) // Hardware guid
|
else if (Components::Singleton::IsFirstInstance()) // ECDSA guid
|
||||||
{
|
{
|
||||||
if (!User::GuidKey.IsValid())
|
subId = Components::Auth::GetKeyHash();
|
||||||
{
|
|
||||||
Proto::Auth::Certificate cert;
|
|
||||||
|
|
||||||
if (cert.ParseFromString(::Utils::ReadFile("players/guid.dat")))
|
|
||||||
{
|
|
||||||
User::GuidKey.Import(cert.privatekey(), PK_PRIVATE);
|
|
||||||
User::GuidToken = cert.token();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!User::GuidKey.IsValid())
|
|
||||||
{
|
|
||||||
User::GuidToken.Clear();
|
|
||||||
User::GuidKey = ::Utils::Cryptography::ECDSA::GenerateKey(512);
|
|
||||||
|
|
||||||
cert.set_token(User::GuidToken.ToString());
|
|
||||||
cert.set_privatekey(User::GuidKey.Export(PK_PRIVATE));
|
|
||||||
|
|
||||||
::Utils::WriteFile("players/guid.dat", cert.SerializeAsString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string publicKey = User::GuidKey.GetPublicKey();
|
|
||||||
subId = ::Utils::OneAtATime(publicKey.data(), publicKey.size());
|
|
||||||
}
|
}
|
||||||
else // Random guid
|
else // Random guid
|
||||||
{
|
{
|
||||||
|
@ -20,8 +20,5 @@ namespace Steam
|
|||||||
virtual void EndAuthSession(SteamID steamID);
|
virtual void EndAuthSession(SteamID steamID);
|
||||||
virtual void CancelAuthTicket(unsigned int hAuthTicket);
|
virtual void CancelAuthTicket(unsigned int hAuthTicket);
|
||||||
virtual unsigned int UserHasLicenseForApp(SteamID steamID, unsigned int appID);
|
virtual unsigned int UserHasLicenseForApp(SteamID steamID, unsigned int appID);
|
||||||
|
|
||||||
static ::Utils::Cryptography::Token GuidToken;
|
|
||||||
static ::Utils::Cryptography::ECDSA::Key GuidKey;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ namespace Utils
|
|||||||
{
|
{
|
||||||
namespace Cryptography
|
namespace Cryptography
|
||||||
{
|
{
|
||||||
|
|
||||||
#pragma region Rand
|
#pragma region Rand
|
||||||
|
|
||||||
prng_state Rand::State;
|
prng_state Rand::State;
|
||||||
@ -96,7 +97,7 @@ namespace Utils
|
|||||||
register_hash(&sha1_desc);
|
register_hash(&sha1_desc);
|
||||||
|
|
||||||
ltc_mp = ltm_desc;
|
ltc_mp = ltm_desc;
|
||||||
|
|
||||||
rsa_sign_hash(reinterpret_cast<const uint8_t*>(message.data()), message.size(), buffer, &length, NULL, find_prng("sprng"), find_hash("sha1"), 0, key.GetKeyPtr());
|
rsa_sign_hash(reinterpret_cast<const uint8_t*>(message.data()), message.size(), buffer, &length, NULL, find_prng("sprng"), find_hash("sha1"), 0, key.GetKeyPtr());
|
||||||
|
|
||||||
return std::string(reinterpret_cast<char*>(buffer), length);
|
return std::string(reinterpret_cast<char*>(buffer), length);
|
||||||
@ -113,8 +114,46 @@ namespace Utils
|
|||||||
int result = 0;
|
int result = 0;
|
||||||
return (rsa_verify_hash(reinterpret_cast<const uint8_t*>(signature.data()), signature.size(), reinterpret_cast<const uint8_t*>(message.data()), message.size(), find_hash("sha1"), 0, &result, key.GetKeyPtr()) == CRYPT_OK && result != 0);
|
return (rsa_verify_hash(reinterpret_cast<const uint8_t*>(signature.data()), signature.size(), reinterpret_cast<const uint8_t*>(message.data()), message.size(), find_hash("sha1"), 0, &result, key.GetKeyPtr()) == CRYPT_OK && result != 0);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
|
#pragma region SHA256
|
||||||
|
|
||||||
|
std::string SHA256::Compute(std::string data, bool hex)
|
||||||
|
{
|
||||||
|
uint8_t buffer[32] = { 0 };
|
||||||
|
|
||||||
|
hash_state state;
|
||||||
|
sha256_init(&state);
|
||||||
|
sha256_process(&state, reinterpret_cast<const uint8_t*>(data.data()), data.size());
|
||||||
|
sha256_done(&state, buffer);
|
||||||
|
|
||||||
|
std::string hash(reinterpret_cast<char*>(buffer), sizeof(buffer));
|
||||||
|
if (!hex) return hash;
|
||||||
|
|
||||||
|
return Utils::DumpHex(hash, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
#pragma region SHA512
|
||||||
|
|
||||||
|
std::string SHA512::Compute(std::string data, bool hex)
|
||||||
|
{
|
||||||
|
uint8_t buffer[64] = { 0 };
|
||||||
|
|
||||||
|
hash_state state;
|
||||||
|
sha512_init(&state);
|
||||||
|
sha512_process(&state, reinterpret_cast<const uint8_t*>(data.data()), data.size());
|
||||||
|
sha512_done(&state, buffer);
|
||||||
|
|
||||||
|
std::string hash(reinterpret_cast<char*>(buffer), sizeof(buffer));
|
||||||
|
if (!hex) return hash;
|
||||||
|
|
||||||
|
return Utils::DumpHex(hash, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -221,5 +221,17 @@ namespace Utils
|
|||||||
static std::string SignMessage(Key key, std::string message);
|
static std::string SignMessage(Key key, std::string message);
|
||||||
static bool VerifyMessage(Key key, std::string message, std::string signature);
|
static bool VerifyMessage(Key key, std::string message, std::string signature);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class SHA256
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static std::string Compute(std::string data, bool hex = false);
|
||||||
|
};
|
||||||
|
|
||||||
|
class SHA512
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static std::string Compute(std::string data, bool hex = false);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,7 @@ namespace Utils
|
|||||||
return (strstr(haystack.data(), needle.data()) == (haystack.data() + haystack.size() - needle.size()));
|
return (strstr(haystack.data(), needle.data()) == (haystack.data() + haystack.size() - needle.size()));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string DumpHex(std::string data)
|
std::string DumpHex(std::string data, std::string separator)
|
||||||
{
|
{
|
||||||
std::string result;
|
std::string result;
|
||||||
|
|
||||||
@ -38,7 +38,7 @@ namespace Utils
|
|||||||
{
|
{
|
||||||
if (i > 0)
|
if (i > 0)
|
||||||
{
|
{
|
||||||
result.append(" ");
|
result.append(separator);
|
||||||
}
|
}
|
||||||
|
|
||||||
result.append(Utils::VA("%02X", data[i] & 0xFF));
|
result.append(Utils::VA("%02X", data[i] & 0xFF));
|
||||||
|
@ -20,7 +20,7 @@ namespace Utils
|
|||||||
void WriteFile(std::string file, std::string data);
|
void WriteFile(std::string file, std::string data);
|
||||||
std::string ReadFile(std::string file);
|
std::string ReadFile(std::string file);
|
||||||
|
|
||||||
std::string DumpHex(std::string data);
|
std::string DumpHex(std::string data, std::string separator = " ");
|
||||||
|
|
||||||
bool MemIsSet(void* mem, char chr, size_t length);
|
bool MemIsSet(void* mem, char chr, size_t length);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user