diff --git a/loader/hash/hash.cpp b/loader/hash/hash.cpp index 2b60276e..5757b778 100644 --- a/loader/hash/hash.cpp +++ b/loader/hash/hash.cpp @@ -52,6 +52,8 @@ std::string calculateSHA256Text(std::filesystem::path const& path) { return picosha2::bytes_to_hex_string(hash.begin(), hash.end()); } -std::string calculateHash(std::filesystem::path const& path) { - return calculateSHA3_256(path); +std::string calculateHash(std::span data) { + std::vector hash(picosha2::k_digest_size); + picosha2::hash256(data.begin(), data.end(), hash); + return picosha2::bytes_to_hex_string(hash.begin(), hash.end()); } \ No newline at end of file diff --git a/loader/hash/hash.hpp b/loader/hash/hash.hpp index 06d7adec..5b517c48 100644 --- a/loader/hash/hash.hpp +++ b/loader/hash/hash.hpp @@ -2,6 +2,7 @@ #include #include +#include std::string calculateSHA3_256(std::filesystem::path const& path); @@ -9,4 +10,8 @@ std::string calculateSHA256(std::filesystem::path const& path); std::string calculateSHA256Text(std::filesystem::path const& path); -std::string calculateHash(std::filesystem::path const& path); +/** + * Calculates the SHA256 hash of the given data, + * used for verifying mods. + */ +std::string calculateHash(std::span data); diff --git a/loader/src/server/DownloadManager.cpp b/loader/src/server/DownloadManager.cpp index 5d89316d..ee16fe2d 100644 --- a/loader/src/server/DownloadManager.cpp +++ b/loader/src/server/DownloadManager.cpp @@ -3,6 +3,7 @@ #include #include #include +#include using namespace server; @@ -103,8 +104,16 @@ public: m_downloadListener.bind([this, hash = version.hash](web::WebTask::Event* event) { if (auto value = event->getValue()) { if (value->ok()) { + if (auto actualHash = ::calculateHash(value->data()); actualHash != hash) { + log::error("Failed to download {}, hash mismatch ({} != {})", m_id, actualHash, hash); + m_status = DownloadStatusError { + .details = "Hash mismatch, downloaded file did not match what was expected", + }; + ModDownloadEvent(m_id).post(); + return; + } + bool removingInstalledWasError = false; - bool disablingReplacedWasError = false; std::string id = m_replacesMod.has_value() ? m_replacesMod.value() : m_id; if (auto mod = Loader::get()->getInstalledMod(id)) { std::error_code ec;