Hash system fixes

This commit is contained in:
fed 2023-12-13 20:20:51 +01:00
parent ce12f0d9f5
commit 2db853c4c1
No known key found for this signature in database
GPG Key ID: 1D2C630F04722996
4 changed files with 62 additions and 4 deletions

View File

@ -8,6 +8,8 @@
#include "game/ui_scripting/execution.hpp" #include "game/ui_scripting/execution.hpp"
#include "utils/hash.hpp"
#include <utils/concurrency.hpp> #include <utils/concurrency.hpp>
#include <utils/http.hpp> #include <utils/http.hpp>
#include <utils/io.hpp> #include <utils/io.hpp>
@ -165,7 +167,7 @@ namespace download
const auto url = utils::string::va("%s/%s", base.data(), file.name.data()); const auto url = utils::string::va("%s/%s", base.data(), file.name.data());
console::debug("Downloading %s from %s: %s\n", file.name.data(), base.data(), url); console::debug("Downloading %s from %s: %s\n", file.name.data(), base.data(), url);
const auto data = utils::http::get_data(url, {}, {}, &progress_callback); auto data = utils::http::get_data(url, {}, {}, &progress_callback);
if (!data.has_value()) if (!data.has_value())
{ {
menu_error("Download failed: An unknown error occurred, please try again."); menu_error("Download failed: An unknown error occurred, please try again.");
@ -177,7 +179,7 @@ namespace download
return; return;
} }
const auto& result = data.value(); auto& result = data.value();
if (result.code != CURLE_OK) if (result.code != CURLE_OK)
{ {
menu_error(utils::string::va("Download failed: %s (%i)\n", menu_error(utils::string::va("Download failed: %s (%i)\n",
@ -192,7 +194,7 @@ namespace download
return; return;
} }
const auto hash = utils::cryptography::sha1::compute(result.buffer, true); const auto hash = utils::hash::get_buffer_hash(result.buffer, file.name);
if (hash != file.hash) if (hash != file.hash)
{ {
menu_error(utils::string::va("Download failed: file hash doesn't match the server's (%s: %s != %s)\n", menu_error(utils::string::va("Download failed: file hash doesn't match the server's (%s: %s != %s)\n",

View File

@ -211,7 +211,11 @@ namespace party
} }
const auto hash = utils::hash::get_file_hash(file); const auto hash = utils::hash::get_file_hash(file);
if (!hash.empty())
{
hash_cache.insert(std::make_pair(file, hash)); hash_cache.insert(std::make_pair(file, hash));
}
return hash; return hash;
} }
@ -271,6 +275,7 @@ namespace party
} }
const auto hash = get_file_hash(filename); const auto hash = get_file_hash(filename);
console::debug("hash != source_hash => %s != %s\n", source_hash.data(), hash.data());
if (hash != source_hash) if (hash != source_hash)
{ {
files.emplace_back(filename, source_hash); files.emplace_back(filename, source_hash);
@ -327,6 +332,7 @@ namespace party
if (!has_to_download) if (!has_to_download)
{ {
const auto hash = get_file_hash(file_path); const auto hash = get_file_hash(file_path);
console::debug("has_to_download = %s != %s\n", source_hash.data(), hash.data());
has_to_download = source_hash != hash; has_to_download = source_hash != hash;
} }

View File

@ -3,6 +3,7 @@
#include "game/game.hpp" #include "game/game.hpp"
#include "hash.hpp" #include "hash.hpp"
#include "component/console.hpp"
#include <zlib.h> #include <zlib.h>
#include <utils/cryptography.hpp> #include <utils/cryptography.hpp>
@ -30,6 +31,8 @@ namespace utils::hash
game::DB_AuthHash empty_hash{}; game::DB_AuthHash empty_hash{};
if (!std::memcmp(header.hash.bytes, empty_hash.bytes, hash_size)) if (!std::memcmp(header.hash.bytes, empty_hash.bytes, hash_size))
{ {
console::warn("Computing pakfile hash because its missing, this may take some time...\n");
hash_state state; hash_state state;
sha256_init(&state); sha256_init(&state);
@ -82,6 +85,40 @@ namespace utils::hash
hash.append(reinterpret_cast<char*>(&crc_value), sizeof(crc_value)); hash.append(reinterpret_cast<char*>(&crc_value), sizeof(crc_value));
return utils::string::dump_hex(hash, ""); return utils::string::dump_hex(hash, "");
} }
std::string get_pakfile_buffer_hash(std::string& buffer)
{
if (buffer.size() < sizeof(game::XPakHeader))
{
return {};
}
constexpr auto hash_size = sizeof(game::DB_AuthHash);
const auto header = reinterpret_cast<game::XPakHeader*>(buffer.data());
game::DB_AuthHash empty_hash{};
if (!std::memcmp(header->hash.bytes, empty_hash.bytes, hash_size))
{
console::warn("Computing pakfile hash because its missing, this may take some time...\n");
const auto hash_start = reinterpret_cast<std::uint8_t*>(buffer.data() + sizeof(game::XPakHeader));
const auto len = buffer.size() - sizeof(game::XPakHeader);
const auto hash = utils::cryptography::sha256::compute(hash_start, len, false);
std::memcpy(header->hash.bytes, hash.data(), sizeof(header->hash));
}
std::string hash = {header->hash.bytes, header->hash.bytes + hash_size};
return utils::string::dump_hex(hash, "");
}
std::string get_generic_buffer_hash(const std::string& buffer)
{
auto crc_value = crc32(0L, Z_NULL, 0);
crc_value = crc32(crc_value, reinterpret_cast<const std::uint8_t*>(buffer.data()),
static_cast<std::uint32_t>(buffer.size()));
std::string hash;
hash.append(reinterpret_cast<char*>(&crc_value), sizeof(crc_value));
return utils::string::dump_hex(hash, "");
}
} }
std::string get_file_hash(const std::string& file) std::string get_file_hash(const std::string& file)
@ -105,4 +142,16 @@ namespace utils::hash
return get_file_hash_generic(file_stream, file_size); return get_file_hash_generic(file_stream, file_size);
} }
} }
std::string get_buffer_hash(std::string& buffer, const std::string& filename)
{
if (filename.ends_with(".pak"))
{
return get_pakfile_buffer_hash(buffer);
}
else
{
return get_generic_buffer_hash(buffer);
}
}
} }

View File

@ -3,4 +3,5 @@
namespace utils::hash namespace utils::hash
{ {
std::string get_file_hash(const std::string& file); std::string get_file_hash(const std::string& file);
std::string get_buffer_hash(std::string& buffer, const std::string& filename);
} }