From a6b8597f5a2197a9a2a3abdf1cbd96fe8cd09495 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?RADICS=20=C3=81ron?= Date: Tue, 26 Oct 2021 17:21:48 +0200 Subject: [PATCH] Fix CRC and hash calculations (#321) * Fix CRC calculation, add more CRC parameters Use the Boost CRC module to calculate the CRC values. Add options for final xor value, reflectIn and reflectOut. Fixes #320 * Cleanup Hash view combo box, add CRC8 * Use offset/size consistently * Cleanup: unify processing data by chunks * Change CRC algorithm back, drop boost dependency This is mostly the original algorithm, with a few fixes and small additions (support for reflect In / Out, final XOR value). * Use size_t for file read size consistently --- include/views/view_hashes.hpp | 18 +- plugins/builtin/source/lang/en_US.cpp | 5 +- .../libimhex/include/hex/helpers/crypto.hpp | 7 +- plugins/libimhex/source/helpers/crypto.cpp | 223 ++++++----- source/views/view_hashes.cpp | 354 +++++++++++------- 5 files changed, 365 insertions(+), 242 deletions(-) diff --git a/include/views/view_hashes.hpp b/include/views/view_hashes.hpp index 77c96135a..3defc32f7 100644 --- a/include/views/view_hashes.hpp +++ b/include/views/view_hashes.hpp @@ -2,6 +2,8 @@ #include +#include +#include #include namespace hex { @@ -17,12 +19,24 @@ namespace hex { void drawMenu() override; private: + enum class HashFunctions { Crc8, Crc16, Crc32, Md5, Sha1, Sha224, Sha256, Sha384, Sha512 }; + bool m_shouldInvalidate = true; int m_currHashFunction = 0; u64 m_hashRegion[2] = { 0 }; bool m_shouldMatchSelection = false; - static constexpr const char* HashFunctionNames[] = { "CRC16", "CRC32", "MD5", "SHA-1", "SHA-224", "SHA-256", "SHA-384", "SHA-512" }; + static constexpr std::array hashFunctionNames { + std::pair{HashFunctions::Crc8, "CRC8"}, + std::pair{HashFunctions::Crc16, "CRC16"}, + std::pair{HashFunctions::Crc32, "CRC32"}, + std::pair{HashFunctions::Md5, "MD5"}, + std::pair{HashFunctions::Sha1, "SHA-1"}, + std::pair{HashFunctions::Sha224, "SHA-224"}, + std::pair{HashFunctions::Sha256, "SHA-256"}, + std::pair{HashFunctions::Sha384, "SHA-384"}, + std::pair{HashFunctions::Sha512, "SHA-512"}, + }; }; -} \ No newline at end of file +} diff --git a/plugins/builtin/source/lang/en_US.cpp b/plugins/builtin/source/lang/en_US.cpp index ae2aa7d49..9986fffa4 100644 --- a/plugins/builtin/source/lang/en_US.cpp +++ b/plugins/builtin/source/lang/en_US.cpp @@ -146,6 +146,9 @@ namespace hex::plugin::builtin { { "hex.view.hashes.settings", "Settings" }, { "hex.view.hashes.function", "Hash function" }, { "hex.view.hashes.iv", "Initial value" }, + { "hex.view.hashes.xorout", "Final XOR value" }, + { "hex.common.reflectIn", "Reflect input" }, + { "hex.common.reflectOut", "Reflect output" }, { "hex.view.hashes.poly", "Polynomial" }, { "hex.view.hashes.result", "Result" }, @@ -666,4 +669,4 @@ namespace hex::plugin::builtin { }); } -} \ No newline at end of file +} diff --git a/plugins/libimhex/include/hex/helpers/crypto.hpp b/plugins/libimhex/include/hex/helpers/crypto.hpp index 7faa74688..79f2ac60c 100644 --- a/plugins/libimhex/include/hex/helpers/crypto.hpp +++ b/plugins/libimhex/include/hex/helpers/crypto.hpp @@ -14,8 +14,9 @@ namespace hex::crypt { void initialize(); void exit(); - u16 crc16(prv::Provider* &data, u64 offset, size_t size, u16 polynomial, u16 init); - u32 crc32(prv::Provider* &data, u64 offset, size_t size, u32 polynomial, u32 init); + u16 crc8(prv::Provider* &data, u64 offset, size_t size, u32 polynomial, u32 init, u32 xorout, bool reflectIn, bool reflectOut); + u16 crc16(prv::Provider* &data, u64 offset, size_t size, u32 polynomial, u32 init, u32 xorout, bool reflectIn, bool reflectOut); + u32 crc32(prv::Provider* &data, u64 offset, size_t size, u32 polynomial, u32 init, u32 xorout, bool reflectIn, bool reflectOut); std::array md5(prv::Provider* &data, u64 offset, size_t size); std::array sha1(prv::Provider* &data, u64 offset, size_t size); @@ -54,4 +55,4 @@ namespace hex::crypt { }; std::vector aesDecrypt(AESMode mode, KeyLength keyLength, const std::vector &key, std::array nonce, std::array iv, const std::vector &input); -} \ No newline at end of file +} diff --git a/plugins/libimhex/source/helpers/crypto.cpp b/plugins/libimhex/source/helpers/crypto.cpp index 072ebffba..62281fae9 100644 --- a/plugins/libimhex/source/helpers/crypto.cpp +++ b/plugins/libimhex/source/helpers/crypto.cpp @@ -15,6 +15,11 @@ #include #include +#include +#include +#include +#include +#include #if MBEDTLS_VERSION_MAJOR <= 2 @@ -37,77 +42,139 @@ #endif namespace hex::crypt { + using namespace std::placeholders; - u16 crc16(prv::Provider* &data, u64 offset, size_t size, u16 polynomial, u16 init) { - const auto table = [polynomial] { - std::array table; - - for (u16 i = 0; i < 256; i++) { - u16 crc = 0; - u16 c = i; - - for (u16 j = 0; j < 8; j++) { - if (((crc ^ c) & 0x0001U) != 0) - crc = (crc >> 1U) ^ polynomial; - else - crc >>= 1U; - - c >>= 1U; - } - - table[i] = crc; - } - - return table; - }(); - - u16 crc = init; - + template Func> + void processDataByChunks(prv::Provider* data, u64 offset, size_t size, Func func) + { std::array buffer = { 0 }; - - for (u64 bufferOffset = 0; offset < size; offset += buffer.size()) { - const u64 readSize = std::min(u64(buffer.size()), size - bufferOffset); + for (size_t bufferOffset = 0; bufferOffset < size; bufferOffset += buffer.size()) { + const auto readSize = std::min(buffer.size(), size - bufferOffset); data->read(offset + bufferOffset, buffer.data(), readSize); - - for (size_t i = 0; i < readSize; i++) { - crc = (crc >> 8) ^ table[(crc ^ u16(buffer[i])) & 0x00FF]; - } + func(buffer.data(), readSize); } - - return crc; } - u32 crc32(prv::Provider* &data, u64 offset, size_t size, u32 polynomial, u32 init) { - const auto table = [polynomial] { - std::array table = {0}; + template + T reflect(T in, std::size_t bits) + { + T out{}; - for (uint32_t i = 0; i < 256; i++) { - uint32_t c = i; - for (size_t j = 0; j < 8; j++) { - if (c & 1) - c = polynomial ^ (c >> 1); - else - c >>= 1; + for(std::size_t i = 0; i < bits; i++) + { + out <<= 1; + if (in & 0b1) + out |= 1; + in >>= 1; + } + return out; + } + + template + T reflect(T in) + { + if constexpr (sizeof(T) == 1) + { + T out{in}; + + out = ((out & 0xf0u) >> 4) | ((out & 0x0fu) << 4); + out = ((out & 0xccu) >> 2) | ((out & 0x33u) << 2); + out = ((out & 0xaau) >> 1) | ((out & 0x55u) << 1); + + return out; + } + else + { + return reflect(in, sizeof(T) *8 ); + } + } + + class Crc { + // use reflected algorithm, so we reflect only if refin / refout is FALSE + // mask values, 0b1 << 64 is UB, so use 0b10 << 63 + + public: + using calc_type = uint64_t; + + Crc(int bits, calc_type polynomial, calc_type init, calc_type xorout, bool refin, bool refout) : + m_bits(bits), + m_init(init & ((0b10ull << (bits-1)) - 1)), + m_xorout(xorout & ((0b10ull << (bits-1)) - 1)), + m_refin(refin), + m_refout(refout), + table([polynomial, bits](){ + auto reflectedpoly= reflect(polynomial & ((0b10ull << (bits-1)) - 1), bits); + std::array table = {0}; + + for (uint32_t i = 0; i < 256; i++) { + uint64_t c = i; + for (std::size_t j = 0; j < 8; j++) { + if (c & 0b1) + c = reflectedpoly ^ (c >> 1); + else + c >>= 1; + } + table[i] = c; } - table[i] = c; - } - return table; - }(); + return table; + }()) { + reset(); + }; - uint32_t c = init; - std::array buffer = { 0 }; + void reset() { + c = reflect(m_init, m_bits); + } - for (u64 bufferOffset = 0; offset < size; offset += buffer.size()) { - const u64 readSize = std::min(u64(buffer.size()), size - bufferOffset); - data->read(offset + bufferOffset, buffer.data(), readSize); + void processBytes(const unsigned char *data, std::size_t size) { + for (std::size_t i = 0; i < size; i++) { + unsigned char d; + if (m_refin) + d = data[i]; + else + d = reflect(data[i]); - for (size_t i = 0; i < readSize; i++) { - c = table[(c ^ buffer[i]) & 0xFF] ^ (c >> 8); + c = table[(c ^ d) & 0xFFL] ^ (c >> 8); } } - return ~c; + calc_type checksum() const { + if (m_refout) + return c ^ m_xorout; + else + return reflect(c, m_bits) ^ m_xorout; + } + + private: + const int m_bits; + const calc_type m_init; + const calc_type m_xorout; + const bool m_refin; + const bool m_refout; + const std::array table; + + calc_type c; + }; + + template + auto calcCrc(prv::Provider* data, u64 offset, std::size_t size, u32 polynomial, u32 init, u32 xorout, bool reflectIn, bool reflectOut) { + Crc crc(bits, polynomial, init, xorout, reflectIn, reflectOut); + + processDataByChunks(data, offset, size, std::bind(&Crc::processBytes, &crc, _1, _2)); + + return crc.checksum(); + } + + u16 crc8(prv::Provider* &data, u64 offset, size_t size, u32 polynomial, u32 init, u32 xorout, bool reflectIn, bool reflectOut) { + return calcCrc<8>(data, offset, size, polynomial, init, xorout, reflectIn, reflectOut); + } + + u16 crc16(prv::Provider* &data, u64 offset, size_t size, u32 polynomial, u32 init, u32 xorout, bool reflectIn, bool reflectOut) { + return calcCrc<16>(data, offset, size, polynomial, init, xorout, reflectIn, reflectOut); + } + + u32 crc32(prv::Provider* &data, u64 offset, size_t size, u32 polynomial, u32 init, u32 xorout, bool reflectIn, bool reflectOut) { + return calcCrc<32>(data, offset, size, polynomial, init, xorout, reflectIn, reflectOut); } @@ -119,12 +186,7 @@ namespace hex::crypt { mbedtls_md5_starts(&ctx); - std::array buffer = { 0 }; - for (u64 bufferOffset = 0; bufferOffset < size; bufferOffset += buffer.size()) { - const u64 readSize = std::min(u64(buffer.size()), size - bufferOffset); - data->read(offset + bufferOffset, buffer.data(), readSize); - mbedtls_md5_update(&ctx, buffer.data(), readSize); - } + processDataByChunks(data, offset, size, std::bind(mbedtls_md5_update, &ctx, _1, _2)); mbedtls_md5_finish(&ctx, result.data()); @@ -156,12 +218,7 @@ namespace hex::crypt { mbedtls_sha1_starts(&ctx); - std::array buffer = { 0 }; - for (u64 bufferOffset = 0; bufferOffset < size; bufferOffset += buffer.size()) { - const u64 readSize = std::min(u64(buffer.size()), size - bufferOffset); - data->read(offset + bufferOffset, buffer.data(), readSize); - mbedtls_sha1_update(&ctx, buffer.data(), readSize); - } + processDataByChunks(data, offset, size, std::bind(mbedtls_sha1_update, &ctx, _1, _2)); mbedtls_sha1_finish(&ctx, result.data()); @@ -193,12 +250,7 @@ namespace hex::crypt { mbedtls_sha256_starts(&ctx, true); - std::array buffer = { 0 }; - for (u64 bufferOffset = 0; bufferOffset < size; bufferOffset += buffer.size()) { - const u64 readSize = std::min(u64(buffer.size()), size - bufferOffset); - data->read(offset + bufferOffset, buffer.data(), readSize); - mbedtls_sha256_update(&ctx, buffer.data(), readSize); - } + processDataByChunks(data, offset, size, std::bind(mbedtls_sha256_update, &ctx, _1, _2)); mbedtls_sha256_finish(&ctx, result.data()); @@ -230,12 +282,7 @@ namespace hex::crypt { mbedtls_sha256_starts(&ctx, false); - std::array buffer = { 0 }; - for (u64 bufferOffset = 0; bufferOffset < size; bufferOffset += buffer.size()) { - const u64 readSize = std::min(u64(buffer.size()), size - bufferOffset); - data->read(offset + bufferOffset, buffer.data(), readSize); - mbedtls_sha256_update(&ctx, buffer.data(), readSize); - } + processDataByChunks(data, offset, size, std::bind(mbedtls_sha256_update, &ctx, _1, _2)); mbedtls_sha256_finish(&ctx, result.data()); @@ -267,12 +314,7 @@ namespace hex::crypt { mbedtls_sha512_starts(&ctx, true); - std::array buffer = { 0 }; - for (u64 bufferOffset = 0; bufferOffset < size; bufferOffset += buffer.size()) { - const u64 readSize = std::min(u64(buffer.size()), size - bufferOffset); - data->read(offset + bufferOffset, buffer.data(), readSize); - mbedtls_sha512_update(&ctx, buffer.data(), readSize); - } + processDataByChunks(data, offset, size, std::bind(mbedtls_sha512_update, &ctx, _1, _2)); mbedtls_sha512_finish(&ctx, result.data()); @@ -304,12 +346,7 @@ namespace hex::crypt { mbedtls_sha512_starts(&ctx, false); - std::array buffer = { 0 }; - for (u64 bufferOffset = 0; bufferOffset < size; bufferOffset += buffer.size()) { - const u64 readSize = std::min(u64(buffer.size()), size - bufferOffset); - data->read(offset + bufferOffset, buffer.data(), readSize); - mbedtls_sha512_update(&ctx, buffer.data(), readSize); - } + processDataByChunks(data, offset, size, std::bind(mbedtls_sha512_update, &ctx, _1, _2)); mbedtls_sha512_finish(&ctx, result.data()); @@ -445,4 +482,4 @@ namespace hex::crypt { return aes(type, MBEDTLS_DECRYPT, key, nonce, iv, input); } -} \ No newline at end of file +} diff --git a/source/views/view_hashes.cpp b/source/views/view_hashes.cpp index f92382ff3..f2558bc03 100644 --- a/source/views/view_hashes.cpp +++ b/source/views/view_hashes.cpp @@ -19,7 +19,7 @@ namespace hex { this->m_hashRegion[0] = this->m_hashRegion[1] = 0; } else { this->m_hashRegion[0] = region.address; - this->m_hashRegion[1] = region.address + region.size; + this->m_hashRegion[1] = region.size + 1; //WARNING: get size - 1 as region size } this->m_shouldInvalidate = true; } @@ -63,169 +63,237 @@ namespace hex { ImGui::TextUnformatted("hex.view.hashes.settings"_lang); ImGui::Separator(); - if (ImGui::Combo("hex.view.hashes.function"_lang, &this->m_currHashFunction, HashFunctionNames,sizeof(HashFunctionNames) / sizeof(const char *))) + if (ImGui::BeginCombo("hex.view.hashes.function"_lang, hashFunctionNames[this->m_currHashFunction].second, 0)) + { + for (int i = 0; i < hashFunctionNames.size(); i++) + { + bool is_selected = (this->m_currHashFunction == i); + if (ImGui::Selectable(hashFunctionNames[i].second, is_selected)) + this->m_currHashFunction = i; + if (is_selected) + ImGui::SetItemDefaultFocus(); // Set the initial focus when opening the combo (scrolling + for keyboard navigation support in the upcoming navigation branch) + } + ImGui::EndCombo(); this->m_shouldInvalidate = true; + } size_t dataSize = provider->getSize(); if (this->m_hashRegion[1] >= provider->getBaseAddress() + dataSize) this->m_hashRegion[1] = provider->getBaseAddress() + dataSize; - if (this->m_hashRegion[1] >= this->m_hashRegion[0]) { + switch (hashFunctionNames[this->m_currHashFunction].first) { + case HashFunctions::Crc8: + { + static int polynomial = 0x07, init = 0x0000, xorout = 0x0000; + static bool reflectIn = false, reflectOut = false; - switch (this->m_currHashFunction) { - case 0: // CRC16 - { - static int polynomial = 0x8005, init = 0x0000; + ImGui::InputInt("hex.view.hashes.iv"_lang, &init, 0, 0, ImGuiInputTextFlags_CharsHexadecimal); + if (ImGui::IsItemEdited()) this->m_shouldInvalidate = true; - ImGui::InputInt("hex.view.hashes.iv"_lang, &init, 0, 0, ImGuiInputTextFlags_CharsHexadecimal); - if (ImGui::IsItemEdited()) this->m_shouldInvalidate = true; + ImGui::InputInt("hex.view.hashes.xorout"_lang, &xorout, 0, 0, ImGuiInputTextFlags_CharsHexadecimal); + if (ImGui::IsItemEdited()) this->m_shouldInvalidate = true; - ImGui::InputInt("hex.view.hashes.poly"_lang, &polynomial, 0, 0, ImGuiInputTextFlags_CharsHexadecimal); - if (ImGui::IsItemEdited()) this->m_shouldInvalidate = true; + ImGui::Checkbox("hex.common.reflectIn"_lang, &reflectIn); + if (ImGui::IsItemEdited()) this->m_shouldInvalidate = true; - ImGui::NewLine(); + ImGui::Checkbox("hex.common.reflectOut"_lang, &reflectOut); + if (ImGui::IsItemEdited()) this->m_shouldInvalidate = true; - static u16 result = 0; + ImGui::InputInt("hex.view.hashes.poly"_lang, &polynomial, 0, 0, ImGuiInputTextFlags_CharsHexadecimal); + if (ImGui::IsItemEdited()) this->m_shouldInvalidate = true; - if (this->m_shouldInvalidate) - result = crypt::crc16(provider, this->m_hashRegion[0], this->m_hashRegion[1] - this->m_hashRegion[0] + 1, polynomial, init); + ImGui::NewLine(); - char buffer[sizeof(result) * 2 + 1]; - snprintf(buffer, sizeof(buffer), "%04X", result); + static u8 result = 0; - ImGui::TextUnformatted("hex.view.hashes.result"_lang); - ImGui::Separator(); - ImGui::InputText("##nolabel", buffer, ImGuiInputTextFlags_ReadOnly); - } - break; - case 1: // CRC32 - { - static int polynomial = 0x04C11DB7, init = 0xFFFFFFFF; + if (this->m_shouldInvalidate) + result = crypt::crc8(provider, this->m_hashRegion[0], this->m_hashRegion[1], + polynomial, init, xorout, reflectIn, reflectOut); - ImGui::InputInt("hex.view.hashes.iv"_lang, &init, 0, 0, ImGuiInputTextFlags_CharsHexadecimal); - if (ImGui::IsItemEdited()) this->m_shouldInvalidate = true; + char buffer[sizeof(result) * 2 + 1]; + snprintf(buffer, sizeof(buffer), "%02X", result); - ImGui::InputInt("hex.view.hashes.poly"_lang, &polynomial, 0, 0, ImGuiInputTextFlags_CharsHexadecimal); - if (ImGui::IsItemEdited()) this->m_shouldInvalidate = true; - - ImGui::NewLine(); - - static u32 result = 0; - - if (this->m_shouldInvalidate) - result = crypt::crc32(provider, this->m_hashRegion[0], this->m_hashRegion[1] - this->m_hashRegion[0] + 1, polynomial, init); - - char buffer[sizeof(result) * 2 + 1]; - snprintf(buffer, sizeof(buffer), "%08X", result); - - ImGui::TextUnformatted("hex.view.hashes.result"_lang); - ImGui::Separator(); - ImGui::InputText("##nolabel", buffer, ImGuiInputTextFlags_ReadOnly); - } - break; - case 2: // MD5 - { - static std::array result = { 0 }; - - if (this->m_shouldInvalidate) - result = crypt::md5(provider, this->m_hashRegion[0], this->m_hashRegion[1] - this->m_hashRegion[0] + 1); - - char buffer[sizeof(result) * 2 + 1]; - formatBigHexInt(result, buffer, sizeof(buffer)); - - ImGui::NewLine(); - ImGui::TextUnformatted("hex.view.hashes.result"_lang); - ImGui::Separator(); - ImGui::InputText("##nolabel", buffer, ImGuiInputTextFlags_ReadOnly); - } - break; - case 3: // SHA-1 - { - static std::array result = { 0 }; - - if (this->m_shouldInvalidate) - result = crypt::sha1(provider, this->m_hashRegion[0], this->m_hashRegion[1] - this->m_hashRegion[0] + 1); - - char buffer[sizeof(result) * 2 + 1]; - formatBigHexInt(result, buffer, sizeof(buffer)); - - ImGui::NewLine(); - ImGui::TextUnformatted("hex.view.hashes.result"_lang); - ImGui::Separator(); - ImGui::InputText("##nolabel", buffer, ImGuiInputTextFlags_ReadOnly); - } - break; - case 4: // SHA-224 - { - static std::array result = { 0 }; - - if (this->m_shouldInvalidate) - result = crypt::sha224(provider, this->m_hashRegion[0], this->m_hashRegion[1] - this->m_hashRegion[0] + 1); - - char buffer[sizeof(result) * 2 + 1]; - formatBigHexInt(result, buffer, sizeof(buffer)); - - ImGui::NewLine(); - ImGui::TextUnformatted("hex.view.hashes.result"_lang); - ImGui::Separator(); - ImGui::InputText("##nolabel", buffer, ImGuiInputTextFlags_ReadOnly); - } - break; - case 5: // SHA-256 - { - static std::array result; - - if (this->m_shouldInvalidate) - result = crypt::sha256(provider, this->m_hashRegion[0], this->m_hashRegion[1] - this->m_hashRegion[0] + 1); - - char buffer[sizeof(result) * 2 + 1]; - formatBigHexInt(result, buffer, sizeof(buffer)); - - ImGui::NewLine(); - ImGui::TextUnformatted("hex.view.hashes.result"_lang); - ImGui::Separator(); - ImGui::InputText("##nolabel", buffer, ImGuiInputTextFlags_ReadOnly); - } - break; - case 6: // SHA-384 - { - static std::array result; - - if (this->m_shouldInvalidate) - result = crypt::sha384(provider, this->m_hashRegion[0], this->m_hashRegion[1] - this->m_hashRegion[0] + 1); - - char buffer[sizeof(result) * 2 + 1]; - formatBigHexInt(result, buffer, sizeof(buffer)); - - ImGui::NewLine(); - ImGui::TextUnformatted("hex.view.hashes.result"_lang); - ImGui::Separator(); - ImGui::InputText("##nolabel", buffer, ImGuiInputTextFlags_ReadOnly); - } - break; - case 7: // SHA-512 - { - static std::array result; - - if (this->m_shouldInvalidate) - result = crypt::sha512(provider, this->m_hashRegion[0], this->m_hashRegion[1] - this->m_hashRegion[0] + 1); - - char buffer[sizeof(result) * 2 + 1]; - formatBigHexInt(result, buffer, sizeof(buffer)); - - ImGui::NewLine(); - ImGui::TextUnformatted("hex.view.hashes.result"_lang); - ImGui::Separator(); - ImGui::InputText("##nolabel", buffer, ImGuiInputTextFlags_ReadOnly); - } - break; + ImGui::TextUnformatted("hex.view.hashes.result"_lang); + ImGui::Separator(); + ImGui::InputText("##nolabel", buffer, ImGuiInputTextFlags_ReadOnly); } + break; + case HashFunctions::Crc16: + { + static int polynomial = 0x8005, init = 0x0000, xorout = 0x0000; + static bool reflectIn = false, reflectOut = false; + ImGui::InputInt("hex.view.hashes.iv"_lang, &init, 0, 0, ImGuiInputTextFlags_CharsHexadecimal); + if (ImGui::IsItemEdited()) this->m_shouldInvalidate = true; + + ImGui::InputInt("hex.view.hashes.xorout"_lang, &xorout, 0, 0, ImGuiInputTextFlags_CharsHexadecimal); + if (ImGui::IsItemEdited()) this->m_shouldInvalidate = true; + + ImGui::Checkbox("hex.common.reflectIn"_lang, &reflectIn); + if (ImGui::IsItemEdited()) this->m_shouldInvalidate = true; + + ImGui::Checkbox("hex.common.reflectOut"_lang, &reflectOut); + if (ImGui::IsItemEdited()) this->m_shouldInvalidate = true; + + ImGui::InputInt("hex.view.hashes.poly"_lang, &polynomial, 0, 0, ImGuiInputTextFlags_CharsHexadecimal); + if (ImGui::IsItemEdited()) this->m_shouldInvalidate = true; + + ImGui::NewLine(); + + static u16 result = 0; + + if (this->m_shouldInvalidate) + result = crypt::crc16(provider, this->m_hashRegion[0], this->m_hashRegion[1], + polynomial, init, xorout, reflectIn, reflectOut); + + char buffer[sizeof(result) * 2 + 1]; + snprintf(buffer, sizeof(buffer), "%04X", result); + + ImGui::TextUnformatted("hex.view.hashes.result"_lang); + ImGui::Separator(); + ImGui::InputText("##nolabel", buffer, ImGuiInputTextFlags_ReadOnly); + } + break; + case HashFunctions::Crc32: + { + static int polynomial = 0x04C11DB7, init = 0xFFFFFFFF, xorout = 0xFFFFFFFF; + static bool reflectIn = true, reflectOut = true; + + + + ImGui::InputInt("hex.view.hashes.iv"_lang, &init, 0, 0, ImGuiInputTextFlags_CharsHexadecimal); + if (ImGui::IsItemEdited()) this->m_shouldInvalidate = true; + + ImGui::InputInt("hex.view.hashes.xorout"_lang, &xorout, 0, 0, ImGuiInputTextFlags_CharsHexadecimal); + if (ImGui::IsItemEdited()) this->m_shouldInvalidate = true; + + ImGui::Checkbox("hex.common.reflectIn"_lang, &reflectIn); + if (ImGui::IsItemEdited()) this->m_shouldInvalidate = true; + + ImGui::Checkbox("hex.common.reflectOut"_lang, &reflectOut); + if (ImGui::IsItemEdited()) this->m_shouldInvalidate = true; + + ImGui::InputInt("hex.view.hashes.poly"_lang, &polynomial, 0, 0, ImGuiInputTextFlags_CharsHexadecimal); + if (ImGui::IsItemEdited()) this->m_shouldInvalidate = true; + + ImGui::NewLine(); + + static u32 result = 0; + + if (this->m_shouldInvalidate) + result = crypt::crc32(provider, this->m_hashRegion[0], this->m_hashRegion[1], + polynomial, init, xorout, reflectIn, reflectOut); + + char buffer[sizeof(result) * 2 + 1]; + snprintf(buffer, sizeof(buffer), "%08X", result); + + ImGui::TextUnformatted("hex.view.hashes.result"_lang); + ImGui::Separator(); + ImGui::InputText("##nolabel", buffer, ImGuiInputTextFlags_ReadOnly); + } + break; + case HashFunctions::Md5: + { + static std::array result = { 0 }; + + if (this->m_shouldInvalidate) + result = crypt::md5(provider, this->m_hashRegion[0], this->m_hashRegion[1]); + + char buffer[sizeof(result) * 2 + 1]; + formatBigHexInt(result, buffer, sizeof(buffer)); + + ImGui::NewLine(); + ImGui::TextUnformatted("hex.view.hashes.result"_lang); + ImGui::Separator(); + ImGui::InputText("##nolabel", buffer, ImGuiInputTextFlags_ReadOnly); + } + break; + case HashFunctions::Sha1: + { + static std::array result = { 0 }; + + if (this->m_shouldInvalidate) + result = crypt::sha1(provider, this->m_hashRegion[0], this->m_hashRegion[1]); + + char buffer[sizeof(result) * 2 + 1]; + formatBigHexInt(result, buffer, sizeof(buffer)); + + ImGui::NewLine(); + ImGui::TextUnformatted("hex.view.hashes.result"_lang); + ImGui::Separator(); + ImGui::InputText("##nolabel", buffer, ImGuiInputTextFlags_ReadOnly); + } + break; + case HashFunctions::Sha224: + { + static std::array result = { 0 }; + + if (this->m_shouldInvalidate) + result = crypt::sha224(provider, this->m_hashRegion[0], this->m_hashRegion[1]); + + char buffer[sizeof(result) * 2 + 1]; + formatBigHexInt(result, buffer, sizeof(buffer)); + + ImGui::NewLine(); + ImGui::TextUnformatted("hex.view.hashes.result"_lang); + ImGui::Separator(); + ImGui::InputText("##nolabel", buffer, ImGuiInputTextFlags_ReadOnly); + } + break; + case HashFunctions::Sha256: + { + static std::array result; + + if (this->m_shouldInvalidate) + result = crypt::sha256(provider, this->m_hashRegion[0], this->m_hashRegion[1]); + + char buffer[sizeof(result) * 2 + 1]; + formatBigHexInt(result, buffer, sizeof(buffer)); + + ImGui::NewLine(); + ImGui::TextUnformatted("hex.view.hashes.result"_lang); + ImGui::Separator(); + ImGui::InputText("##nolabel", buffer, ImGuiInputTextFlags_ReadOnly); + } + break; + case HashFunctions::Sha384: + { + static std::array result; + + if (this->m_shouldInvalidate) + result = crypt::sha384(provider, this->m_hashRegion[0], this->m_hashRegion[1]); + + char buffer[sizeof(result) * 2 + 1]; + formatBigHexInt(result, buffer, sizeof(buffer)); + + ImGui::NewLine(); + ImGui::TextUnformatted("hex.view.hashes.result"_lang); + ImGui::Separator(); + ImGui::InputText("##nolabel", buffer, ImGuiInputTextFlags_ReadOnly); + } + break; + case HashFunctions::Sha512: + { + static std::array result; + + if (this->m_shouldInvalidate) + result = crypt::sha512(provider, this->m_hashRegion[0], this->m_hashRegion[1]); + + char buffer[sizeof(result) * 2 + 1]; + formatBigHexInt(result, buffer, sizeof(buffer)); + + ImGui::NewLine(); + ImGui::TextUnformatted("hex.view.hashes.result"_lang); + ImGui::Separator(); + ImGui::InputText("##nolabel", buffer, ImGuiInputTextFlags_ReadOnly); + } + break; } - this->m_shouldInvalidate = false; } + + this->m_shouldInvalidate = false; } ImGui::EndChild(); } @@ -236,4 +304,4 @@ namespace hex { } -} \ No newline at end of file +}