From 5ba3badcbfc138f47ea9773cedc7195217524932 Mon Sep 17 00:00:00 2001 From: WerWolv Date: Thu, 12 Nov 2020 12:00:50 +0100 Subject: [PATCH] Add more hash algorthms, switch to openssl / libcrypto --- CMakeLists.txt | 3 +- include/crypto.hpp | 24 ++++ include/utils.hpp | 3 - include/views/view_hashes.hpp | 2 +- source/crypto.cpp | 218 ++++++++++++++++++++++++++++++++++ source/utils.cpp | 141 ---------------------- source/views/view_hashes.cpp | 118 ++++++++++++++---- 7 files changed, 340 insertions(+), 169 deletions(-) create mode 100644 include/crypto.hpp create mode 100644 source/crypto.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 20c87f822..2a8d5cb0e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,6 +12,7 @@ add_executable(ImHex source/main.cpp source/window.cpp source/utils.cpp + source/crypto.cpp source/parser/lexer.cpp source/parser/parser.cpp @@ -36,6 +37,6 @@ add_executable(ImHex res.rc ) -target_link_libraries(ImHex libglfw3.a libgcc.a libstdc++.a libmagic.a libgnurx.a libtre.a libintl.a libiconv.a shlwapi.lib libwinpthread.a) +target_link_libraries(ImHex libglfw3.a libgcc.a libstdc++.a libmagic.a libgnurx.a libtre.a libintl.a libiconv.a shlwapi.lib libwinpthread.a libcrypto.a) diff --git a/include/crypto.hpp b/include/crypto.hpp new file mode 100644 index 000000000..4a6598882 --- /dev/null +++ b/include/crypto.hpp @@ -0,0 +1,24 @@ +#pragma once + +#include + +#include +#include +#include + +namespace hex { + + namespace prv { class Provider; } + + 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); + + std::array md4(prv::Provider* &data, u64 offset, size_t size); + std::array md5(prv::Provider* &data, u64 offset, size_t size); + std::array sha1(prv::Provider* &data, u64 offset, size_t size); + std::array sha224(prv::Provider* &data, u64 offset, size_t size); + std::array sha256(prv::Provider* &data, u64 offset, size_t size); + std::array sha384(prv::Provider* &data, u64 offset, size_t size); + std::array sha512(prv::Provider* &data, u64 offset, size_t size); + +} \ No newline at end of file diff --git a/include/utils.hpp b/include/utils.hpp index 8070bb70c..f7bd5e47a 100644 --- a/include/utils.hpp +++ b/include/utils.hpp @@ -10,7 +10,4 @@ namespace hex { std::optional openFileDialog(); - u16 crc16(u8 *data, size_t size, u16 polynomial, u16 init); - u32 crc32(u8 *data, size_t size, u32 polynomial, u32 init); - std::array md5(u8 *data, size_t size); } \ No newline at end of file diff --git a/include/views/view_hashes.hpp b/include/views/view_hashes.hpp index 6881edf7e..975fd65dc 100644 --- a/include/views/view_hashes.hpp +++ b/include/views/view_hashes.hpp @@ -23,7 +23,7 @@ namespace hex { bool m_shouldInvalidate = true; int m_currHashFunction = 0; int m_hashStart = 0, m_hashEnd = 0; - static constexpr const char* HashFunctionNames[] = { "CRC16", "CRC32", "MD5", "SHA-1", "SHA-256" }; + static constexpr const char* HashFunctionNames[] = { "CRC16", "CRC32", "MD4", "MD5", "SHA-1", "SHA-224", "SHA-256", "SHA-384", "SHA-512" }; }; } \ No newline at end of file diff --git a/source/crypto.cpp b/source/crypto.cpp new file mode 100644 index 000000000..077583520 --- /dev/null +++ b/source/crypto.cpp @@ -0,0 +1,218 @@ +#include "crypto.hpp" + +#include "providers/provider.hpp" + +#include +#include +#include + +#include +#include + +namespace hex { + + 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; + + std::array buffer = { 0 }; + + for (u64 bufferOffset = 0; offset < size; offset += buffer.size()) { + const u64 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]; + } + } + + return crc; + } + + u32 crc32(prv::Provider* &data, u64 offset, size_t size, u32 polynomial, u32 init) { + auto table = [polynomial] { + std::array table = {0}; + + 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; + } + table[i] = c; + } + + return table; + }(); + + uint32_t c = init; + std::array buffer = { 0 }; + + for (u64 bufferOffset = 0; offset < size; offset += buffer.size()) { + const u64 readSize = std::min(buffer.size(), size - bufferOffset); + data->read(offset + bufferOffset, buffer.data(), readSize); + + for (size_t i = 0; i < readSize; i++) { + c = table[(c ^ buffer[i]) & 0xFF] ^ (c >> 8); + } + } + + return ~c; + } + + std::array md4(prv::Provider* &data, u64 offset, size_t size) { + std::array result = { 0 }; + + MD4_CTX ctx; + + MD4_Init(&ctx); + + std::array buffer = { 0 }; + for (u64 bufferOffset = 0; bufferOffset < size; bufferOffset += buffer.size()) { + const u64 readSize = std::min(buffer.size(), size - bufferOffset); + data->read(offset + bufferOffset, buffer.data(), readSize); + MD4_Update(&ctx, buffer.data(), readSize); + } + + MD4_Final(reinterpret_cast(result.data()), &ctx); + + return result; + } + + std::array md5(prv::Provider* &data, u64 offset, size_t size) { + std::array result = { 0 }; + + MD5_CTX ctx; + + MD5_Init(&ctx); + + std::array buffer = { 0 }; + for (u64 bufferOffset = 0; bufferOffset < size; bufferOffset += buffer.size()) { + const u64 readSize = std::min(buffer.size(), size - bufferOffset); + data->read(offset + bufferOffset, buffer.data(), readSize); + MD5_Update(&ctx, buffer.data(), readSize); + } + + MD5_Final(reinterpret_cast(result.data()), &ctx); + + return result; + } + + std::array sha1(prv::Provider* &data, u64 offset, size_t size) { + std::array result = { 0 }; + + SHA_CTX ctx; + + SHA1_Init(&ctx); + std::array buffer = { 0 }; + for (u64 bufferOffset = 0; bufferOffset < size; bufferOffset += buffer.size()) { + const u64 readSize = std::min(buffer.size(), size - bufferOffset); + data->read(offset + bufferOffset, buffer.data(), readSize); + SHA1_Update(&ctx, buffer.data(), readSize); + } + + SHA1_Final(reinterpret_cast(result.data()), &ctx); + + return result; + } + + std::array sha224(prv::Provider* &data, u64 offset, size_t size) { + std::array result = { 0 }; + + SHA256_CTX ctx; + + SHA224_Init(&ctx); + + std::array buffer = { 0 }; + for (u64 bufferOffset = 0; bufferOffset < size; bufferOffset += buffer.size()) { + const u64 readSize = std::min(buffer.size(), size - bufferOffset); + data->read(offset + bufferOffset, buffer.data(), readSize); + SHA224_Update(&ctx, buffer.data(), readSize); + } + + SHA224_Final(reinterpret_cast(result.data()), &ctx); + + return result; + } + + std::array sha256(prv::Provider* &data, u64 offset, size_t size) { + std::array result = { 0 }; + + SHA256_CTX ctx; + + SHA256_Init(&ctx); + + std::array buffer = { 0 }; + for (u64 bufferOffset = 0; bufferOffset < size; bufferOffset += buffer.size()) { + const u64 readSize = std::min(buffer.size(), size - bufferOffset); + data->read(offset + bufferOffset, buffer.data(), readSize); + SHA256_Update(&ctx, buffer.data(), readSize); + } + + SHA256_Final(reinterpret_cast(result.data()), &ctx); + + return result; + } + + std::array sha384(prv::Provider* &data, u64 offset, size_t size) { + std::array result = { 0 }; + + SHA512_CTX ctx; + + SHA384_Init(&ctx); + + std::array buffer = { 0 }; + for (u64 bufferOffset = 0; bufferOffset < size; bufferOffset += buffer.size()) { + const u64 readSize = std::min(buffer.size(), size - bufferOffset); + data->read(offset + bufferOffset, buffer.data(), readSize); + SHA384_Update(&ctx, buffer.data(), readSize); + } + + SHA384_Final(reinterpret_cast(result.data()), &ctx); + + return result; + } + + std::array sha512(prv::Provider* &data, u64 offset, size_t size) { + std::array result = { 0 }; + + SHA512_CTX ctx; + + SHA512_Init(&ctx); + + std::array buffer = { 0 }; + for (u64 bufferOffset = 0; bufferOffset < size; bufferOffset += buffer.size()) { + const u64 readSize = std::min(buffer.size(), size - bufferOffset); + data->read(offset + bufferOffset, buffer.data(), readSize); + SHA512_Update(&ctx, buffer.data(), readSize); + } + + SHA512_Final(reinterpret_cast(result.data()), &ctx); + + return result; + } + +} \ No newline at end of file diff --git a/source/utils.cpp b/source/utils.cpp index fb135272f..1b9116c7d 100644 --- a/source/utils.cpp +++ b/source/utils.cpp @@ -3,12 +3,8 @@ #include #include -#include -#include #include -#include #include -#include namespace hex { @@ -50,141 +46,4 @@ namespace hex { return { }; } - u16 crc16(u8 *data, 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; - - for (size_t i = 0; i < size; i++) { - crc = (crc >> 8) ^ table[(crc ^ u16(*data++)) & 0x00FF]; - } - - return crc; - } - - u32 crc32(u8 *buffer, size_t size, u32 polynomial, u32 init) { - auto table = [polynomial] { - std::array table = {0}; - - 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; - } - table[i] = c; - } - - return table; - }(); - - uint32_t c = init; - const uint8_t *u = static_cast(buffer); - - for (size_t i = 0; i < size; ++i) - c = table[(c ^ u[i]) & 0xFF] ^ (c >> 8); - - return ~c; - } - - std::array md5(u8 *data, size_t size) { - constexpr u32 r[] = { 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, - 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, - 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, - 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21 - }; - - constexpr u32 k[] = { - 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, - 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, - 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, - 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, - 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, - 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8, - 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, - 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, - 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, - 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, - 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05, - 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, - 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, - 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, - 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, - 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391 - }; - - std::array h = { 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476 }; - - u32 newSize = ((((size + 8) / 64) + 1) * 64) - 8; - - std::vector buffer(newSize + 64, 0x00); - std::memcpy(buffer.data(), data, size); - buffer[size] = 128; - - u32 numBits = 8 * size; - std::memcpy(buffer.data() + newSize, &numBits, 4); - - for (s32 offset = 0; offset < newSize; offset += (512/8)) { - u32 *w = reinterpret_cast(buffer.data() + offset); - - u32 a = h[0]; - u32 b = h[1]; - u32 c = h[2]; - u32 d = h[3]; - - for (u32 i = 0; i < 64; i++) { - u32 f, g; - - if (i < 16) { - f = (b & c) | ((~b) & d); - g = i; - } else if (i < 32) { - f = (d & b) | ((~d) & c); - g = (5 * i + 1) & 0x0F; - } else if (i < 48) { - f = b ^ c ^ d; - g = (3 * i + 5) & 0x0F; - } else { - f = c ^ (b | (~d)); - g = (7 * i) & 0x0F; - } - - u32 temp = d; - d = c; - c = b; - b = b + std::rotl(a + f + k[i] + w[g], r[i]); - a = temp; - } - - h[0] += a; - h[1] += b; - h[2] += c; - h[3] += d; - } - - return h; - } - } \ No newline at end of file diff --git a/source/views/view_hashes.cpp b/source/views/view_hashes.cpp index 1069a52a8..e0b7b64c8 100644 --- a/source/views/view_hashes.cpp +++ b/source/views/view_hashes.cpp @@ -2,7 +2,7 @@ #include "providers/provider.hpp" -#include "utils.hpp" +#include "crypto.hpp" #include @@ -19,6 +19,11 @@ namespace hex { } + static void formatBigHexInt(auto dataArray, char *buffer, size_t bufferSize) { + for (int i = 0; i < dataArray.size(); i++) + snprintf(buffer + 8 * i, bufferSize - 8 * i, "%08X", __builtin_bswap32(dataArray[i])); + } + void ViewHashes::createView() { if (!this->m_windowOpen) return; @@ -29,8 +34,8 @@ namespace hex { if (this->m_dataProvider != nullptr && this->m_dataProvider->isAvailable()) { - ImGui::Combo("Hash Function", &this->m_currHashFunction, HashFunctionNames,sizeof(HashFunctionNames) / sizeof(const char *)); - if (ImGui::IsItemEdited()) this->m_shouldInvalidate = true; + if (ImGui::Combo("Hash Function", &this->m_currHashFunction, HashFunctionNames,sizeof(HashFunctionNames) / sizeof(const char *))) + this->m_shouldInvalidate = true; ImGui::NewLine(); ImGui::Separator(); @@ -52,17 +57,10 @@ namespace hex { if (this->m_hashEnd >= this->m_hashStart) { - std::vector buffer; - - if (this->m_shouldInvalidate) { - buffer = std::vector(this->m_hashEnd - this->m_hashStart + 1, 0x00); - this->m_dataProvider->read(this->m_hashStart, buffer.data(), buffer.size()); - } - switch (this->m_currHashFunction) { case 0: // CRC16 { - static int polynomial = 0, init = 0; + int polynomial = 0, init = 0; ImGui::InputInt("Initial Value", &init, 0, 0, ImGuiInputTextFlags_CharsHexadecimal); if (ImGui::IsItemEdited()) this->m_shouldInvalidate = true; @@ -77,14 +75,16 @@ namespace hex { static u16 result = 0; if (this->m_shouldInvalidate) - result = crc16(buffer.data(), buffer.size(), polynomial, init); + result = crc16(this->m_dataProvider, this->m_hashStart, this->m_hashEnd - this->m_hashStart + 1, polynomial, init); - ImGui::LabelText("##nolabel", "%X", result); + char buffer[sizeof(result) * 2 + 1]; + snprintf(buffer, sizeof(buffer), "%04X", result); + ImGui::InputText("Hash value", buffer, ImGuiInputTextFlags_ReadOnly); } break; case 1: // CRC32 { - static int polynomial = 0, init = 0; + int polynomial = 0, init = 0; ImGui::InputInt("Initial Value", &init, 0, 0, ImGuiInputTextFlags_CharsHexadecimal); if (ImGui::IsItemEdited()) this->m_shouldInvalidate = true; @@ -99,23 +99,95 @@ namespace hex { static u32 result = 0; if (this->m_shouldInvalidate) - result = crc32(buffer.data(), buffer.size(), polynomial, init); + result = crc32(this->m_dataProvider, this->m_hashStart, this->m_hashEnd - this->m_hashStart + 1, polynomial, init); - ImGui::LabelText("##nolabel", "%X", result); + char buffer[sizeof(result) * 2 + 1]; + snprintf(buffer, sizeof(buffer), "%08X", result); + ImGui::InputText("Hash value", buffer, ImGuiInputTextFlags_ReadOnly); } break; - case 2: // MD5 + case 2: // MD4 { static std::array result; if (this->m_shouldInvalidate) - result = md5(buffer.data(), buffer.size()); + result = md4(this->m_dataProvider, this->m_hashStart, this->m_hashEnd - this->m_hashStart + 1); - ImGui::LabelText("##nolabel", "%08X%08X%08X%08X", - __builtin_bswap32(result[0]), - __builtin_bswap32(result[1]), - __builtin_bswap32(result[2]), - __builtin_bswap32(result[3])); + char buffer[sizeof(result) * 2 + 1]; + formatBigHexInt(result, buffer, sizeof(buffer)); + ImGui::InputText("Hash value", buffer, ImGuiInputTextFlags_ReadOnly); + } + break; + case 3: // MD5 + { + static std::array result = { 0 }; + + if (this->m_shouldInvalidate) + result = md5(this->m_dataProvider, this->m_hashStart, this->m_hashEnd - this->m_hashStart + 1); + + char buffer[sizeof(result) * 2 + 1]; + formatBigHexInt(result, buffer, sizeof(buffer)); + ImGui::InputText("Hash value", buffer, ImGuiInputTextFlags_ReadOnly); + } + break; + case 4: // SHA-1 + { + static std::array result = { 0 }; + + if (this->m_shouldInvalidate) + result = sha1(this->m_dataProvider, this->m_hashStart, this->m_hashEnd - this->m_hashStart + 1); + + char buffer[sizeof(result) * 2 + 1]; + formatBigHexInt(result, buffer, sizeof(buffer)); + ImGui::InputText("Hash value", buffer, ImGuiInputTextFlags_ReadOnly); + } + break; + case 5: // SHA-224 + { + static std::array result = { 0 }; + + if (this->m_shouldInvalidate) + result = sha224(this->m_dataProvider, this->m_hashStart, this->m_hashEnd - this->m_hashStart + 1); + + char buffer[sizeof(result) * 2 + 1]; + formatBigHexInt(result, buffer, sizeof(buffer)); + ImGui::InputText("Hash value", buffer, ImGuiInputTextFlags_ReadOnly); + } + break; + case 6: // SHA-256 + { + static std::array result; + + if (this->m_shouldInvalidate) + result = sha256(this->m_dataProvider, this->m_hashStart, this->m_hashEnd - this->m_hashStart + 1); + + char buffer[sizeof(result) * 2 + 1]; + formatBigHexInt(result, buffer, sizeof(buffer)); + ImGui::InputText("Hash value", buffer, ImGuiInputTextFlags_ReadOnly); + } + break; + case 7: // SHA-384 + { + static std::array result; + + if (this->m_shouldInvalidate) + result = sha384(this->m_dataProvider, this->m_hashStart, this->m_hashEnd - this->m_hashStart + 1); + + char buffer[sizeof(result) * 2 + 1]; + formatBigHexInt(result, buffer, sizeof(buffer)); + ImGui::InputText("Hash value", buffer, ImGuiInputTextFlags_ReadOnly); + } + break; + case 8: // SHA-512 + { + static std::array result; + + if (this->m_shouldInvalidate) + result = sha512(this->m_dataProvider, this->m_hashStart, this->m_hashEnd - this->m_hashStart + 1); + + char buffer[sizeof(result) * 2 + 1]; + formatBigHexInt(result, buffer, sizeof(buffer)); + ImGui::InputText("Hash value", buffer, ImGuiInputTextFlags_ReadOnly); } break; }