From 1a31b70fbb039d955db7edb720101a94a47b2392 Mon Sep 17 00:00:00 2001 From: zsyg <3872006562@qq.com> Date: Fri, 1 Aug 2025 11:11:21 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=93=88=E5=B8=8C=E6=8F=90?= =?UTF-8?q?=E5=8F=96=E5=99=A8=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- others/C/hash_value_extractor/CMakeLists.txt | 55 +++++ .../include/hash_calculator.h | 37 ++++ .../include/string_util.h | 21 ++ .../src/hash_calculator.c | 53 +++++ others/C/hash_value_extractor/src/main.c | 204 ++++++++++++++++++ others/C/hash_value_extractor/src/md5.c | 35 +++ others/C/hash_value_extractor/src/sha256.c | 35 +++ others/C/hash_value_extractor/src/sha512.c | 35 +++ .../C/hash_value_extractor/src/string_util.c | 120 +++++++++++ 9 files changed, 595 insertions(+) create mode 100644 others/C/hash_value_extractor/CMakeLists.txt create mode 100644 others/C/hash_value_extractor/include/hash_calculator.h create mode 100644 others/C/hash_value_extractor/include/string_util.h create mode 100644 others/C/hash_value_extractor/src/hash_calculator.c create mode 100644 others/C/hash_value_extractor/src/main.c create mode 100644 others/C/hash_value_extractor/src/md5.c create mode 100644 others/C/hash_value_extractor/src/sha256.c create mode 100644 others/C/hash_value_extractor/src/sha512.c create mode 100644 others/C/hash_value_extractor/src/string_util.c diff --git a/others/C/hash_value_extractor/CMakeLists.txt b/others/C/hash_value_extractor/CMakeLists.txt new file mode 100644 index 0000000..66e7e3e --- /dev/null +++ b/others/C/hash_value_extractor/CMakeLists.txt @@ -0,0 +1,55 @@ +cmake_minimum_required(VERSION 3.10) +project(hash_value_extractor) + +set(CMAKE_C_STANDARD 11) +set(CMAKE_C_STANDARD_REQUIRED ON) + +# 静态编译选项 +option(BUILD_STATIC "Build with static linking" ON) + +# 查找OpenSSL +find_package(OpenSSL REQUIRED) + +# 设置Windows子系统 +if(WIN32) + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -mwindows") + if(BUILD_STATIC) + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static") + set(CMAKE_FIND_LIBRARY_SUFFIXES .a) + set(CMAKE_EXE_LINK_DYNAMIC_C_FLAGS) + set(CMAKE_EXE_LINK_DYNAMIC_CXX_FLAGS) + set(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS) + set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS) + endif() +endif() + +# 包含目录 +include_directories(include) + +# 添加可执行文件 +add_executable(hash_value_extractor + src/main.c + src/md5.c + src/sha256.c + src/sha512.c + src/string_util.c +) + +# 链接OpenSSL库 +if(BUILD_STATIC) + # 显式指定静态库路径和名称 + find_library(OPENSSL_SSL_STATIC_LIBRARY NAMES ssl libssl.a PATHS ${OPENSSL_ROOT_DIR}/lib) + find_library(OPENSSL_CRYPTO_STATIC_LIBRARY NAMES crypto libcrypto.a PATHS ${OPENSSL_ROOT_DIR}/lib) + + target_link_libraries(hash_value_extractor + ${OPENSSL_SSL_STATIC_LIBRARY} + ${OPENSSL_CRYPTO_STATIC_LIBRARY} + -lcrypt32 + -lws2_32 + ) +else() + target_link_libraries(hash_value_extractor + OpenSSL::SSL + OpenSSL::Crypto + ) +endif() diff --git a/others/C/hash_value_extractor/include/hash_calculator.h b/others/C/hash_value_extractor/include/hash_calculator.h new file mode 100644 index 0000000..83ede8e --- /dev/null +++ b/others/C/hash_value_extractor/include/hash_calculator.h @@ -0,0 +1,37 @@ +#ifndef HASH_CALCULATOR_H +#define HASH_CALCULATOR_H + +#include + +typedef enum { + HASH_MD5, + HASH_SHA256, + HASH_SHA512 +} HashAlgorithm; + +// 各算法计算函数 +int calculate_md5(const char* filename, char* output); +int calculate_sha256(const char* filename, char* output); +int calculate_sha512(const char* filename, char* output); + +/** + * 计算文件的哈希值 + * @param filename 文件路径 + * @param algorithm 哈希算法 + * @param output 输出缓冲区(必须足够大) + * @return 成功返回0,失败返回-1 + */ +static inline int calculate_file_hash(const char* filename, HashAlgorithm algorithm, char* output) { + switch (algorithm) { + case HASH_MD5: + return calculate_md5(filename, output); + case HASH_SHA256: + return calculate_sha256(filename, output); + case HASH_SHA512: + return calculate_sha512(filename, output); + default: + return -1; + } +} + +#endif // HASH_CALCULATOR_H diff --git a/others/C/hash_value_extractor/include/string_util.h b/others/C/hash_value_extractor/include/string_util.h new file mode 100644 index 0000000..7c1ea60 --- /dev/null +++ b/others/C/hash_value_extractor/include/string_util.h @@ -0,0 +1,21 @@ +#ifndef STRING_UTIL_H +#define STRING_UTIL_H + +#include + +// 快速分配字符串内存 +char* str_alloc(size_t size); + +// 快速释放字符串内存 +void str_free(char* str); + +// 快速字符串复制 +char* str_copy(const char* src); + +// 快速字符串连接 +char* str_concat(const char* str1, const char* str2); + +// 二进制转十六进制字符串 +char* bin_to_hex(const unsigned char* data, size_t len); + +#endif // STRING_UTIL_H diff --git a/others/C/hash_value_extractor/src/hash_calculator.c b/others/C/hash_value_extractor/src/hash_calculator.c new file mode 100644 index 0000000..62281cc --- /dev/null +++ b/others/C/hash_value_extractor/src/hash_calculator.c @@ -0,0 +1,53 @@ +#include "hash_calculator.h" +#include +#include +#include +#include + +int calculate_file_hash(const char* filename, HashAlgorithm algorithm, char* output) { + FILE* file = fopen(filename, "rb"); + if (!file) return -1; + + const EVP_MD* md = NULL; + EVP_MD_CTX* mdctx = EVP_MD_CTX_new(); + unsigned char hash[EVP_MAX_MD_SIZE]; + unsigned int hash_len = 0; + + switch (algorithm) { + case HASH_MD5: + md = EVP_md5(); + break; + case HASH_SHA256: + md = EVP_sha256(); + break; + case HASH_SHA512: + md = EVP_sha512(); + break; + default: + fclose(file); + return -1; + } + + EVP_DigestInit_ex(mdctx, md, NULL); + + unsigned char buffer[1024]; + size_t bytes_read; + while ((bytes_read = fread(buffer, 1, sizeof(buffer), file))) { + EVP_DigestUpdate(mdctx, buffer, bytes_read); + } + + EVP_DigestFinal_ex(mdctx, hash, &hash_len); + EVP_MD_CTX_free(mdctx); + fclose(file); + + hash_to_hex(hash, hash_len, output); + return 0; +} + +void hash_to_hex(const unsigned char* hash, size_t hash_len, char* output) { + for (size_t i = 0; i < hash_len; i++) { + sprintf(output + (i * 2), "%02x", hash[i]); + } + output[hash_len * 2] = '\0'; +} + diff --git a/others/C/hash_value_extractor/src/main.c b/others/C/hash_value_extractor/src/main.c new file mode 100644 index 0000000..14205fc --- /dev/null +++ b/others/C/hash_value_extractor/src/main.c @@ -0,0 +1,204 @@ +// 确保使用Unicode字符集 +#define UNICODE +#define _UNICODE + +#include +#include +#include "hash_calculator.h" +#include +#include + +#define IDC_ALGORITHM_COMBO 1001 +#define IDC_FILE_EDIT 1002 +#define IDC_HASH_EDIT 1003 +#define IDC_BROWSE_BUTTON 1004 +#define IDC_CALCULATE_BUTTON 1005 +#define IDC_COPY_BUTTON 1006 + +// 中文UI字符串定义 +static const wchar_t* APP_TITLE = L"哈希值提取器"; +static const wchar_t* ALGORITHMS[] = {L"MD5", L"SHA-256", L"SHA-512"}; +static const wchar_t* CALCULATE_BTN = L"计算哈希"; +static const wchar_t* BROWSE_BTN = L"浏览..."; +static const wchar_t* COPY_BTN = L"复制哈希值"; +static const wchar_t* CALC_FAILED = L"计算哈希值失败"; + +// 全局变量 +HWND g_hAlgorithmCombo, g_hFileEdit, g_hHashEdit; + +// 初始化控件 +void InitControls(HWND hWnd) { + // 算法选择下拉框 + g_hAlgorithmCombo = CreateWindowW(L"COMBOBOX", NULL, + WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST | WS_VSCROLL, + 10, 10, 200, 200, hWnd, (HMENU)IDC_ALGORITHM_COMBO, NULL, NULL); + + // 添加算法选项 + SendMessageW(g_hAlgorithmCombo, CB_ADDSTRING, 0, (LPARAM)L"MD5"); + SendMessageW(g_hAlgorithmCombo, CB_ADDSTRING, 0, (LPARAM)L"SHA-256"); + SendMessageW(g_hAlgorithmCombo, CB_ADDSTRING, 0, (LPARAM)L"SHA-512"); + SendMessageW(g_hAlgorithmCombo, CB_SETCURSEL, 0, 0); + + // 文件路径编辑框 + g_hFileEdit = CreateWindowW(L"EDIT", NULL, + WS_CHILD | WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL, + 10, 40, 300, 25, hWnd, (HMENU)IDC_FILE_EDIT, NULL, NULL); + + // 浏览按钮 + CreateWindowW(L"BUTTON", L"浏览...", + WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, + 320, 40, 80, 25, hWnd, (HMENU)IDC_BROWSE_BUTTON, NULL, NULL); + + // 计算按钮 + CreateWindowW(L"BUTTON", L"计算哈希", + WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, + 10, 75, 100, 30, hWnd, (HMENU)IDC_CALCULATE_BUTTON, NULL, NULL); + + // 哈希结果显示框 + g_hHashEdit = CreateWindowW(L"EDIT", NULL, + WS_CHILD | WS_VISIBLE | WS_BORDER | ES_MULTILINE | ES_AUTOVSCROLL | ES_READONLY, + 10, 115, 380, 100, hWnd, (HMENU)IDC_HASH_EDIT, NULL, NULL); + + // 复制按钮 + CreateWindowW(L"BUTTON", L"复制哈希值", + WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, + 10, 225, 100, 30, hWnd, (HMENU)IDC_COPY_BUTTON, NULL, NULL); +} + +// 选择文件 +void BrowseFile(HWND hWnd) { + OPENFILENAMEW ofn; + WCHAR szFile[MAX_PATH] = {0}; + + ZeroMemory(&ofn, sizeof(ofn)); + ofn.lStructSize = sizeof(ofn); + ofn.hwndOwner = hWnd; + ofn.lpstrFile = szFile; + ofn.nMaxFile = sizeof(szFile)/sizeof(szFile[0]); + ofn.lpstrFilter = L"所有文件\0*.*\0"; + ofn.nFilterIndex = 1; + ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST; + + if (GetOpenFileNameW(&ofn)) { + SetWindowTextW(g_hFileEdit, szFile); + } +} + +// 计算哈希值 +void CalculateHash() { + WCHAR wszFile[MAX_PATH]; + char szFile[MAX_PATH]; + char szHash[EVP_MAX_MD_SIZE * 2 + 1]; + + GetWindowTextW(g_hFileEdit, wszFile, MAX_PATH); + WideCharToMultiByte(CP_UTF8, 0, wszFile, -1, szFile, MAX_PATH, NULL, NULL); + + int algorithm = SendMessageW(g_hAlgorithmCombo, CB_GETCURSEL, 0, 0); + + if (calculate_file_hash(szFile, algorithm, szHash) == 0) { + WCHAR wszHash[EVP_MAX_MD_SIZE * 2 + 1]; + MultiByteToWideChar(CP_UTF8, 0, szHash, -1, wszHash, EVP_MAX_MD_SIZE * 2 + 1); + SetWindowTextW(g_hHashEdit, wszHash); + } else { + SetWindowTextW(g_hHashEdit, L"计算哈希值失败"); + } +} + +// 复制哈希值到剪贴板 +void CopyHashToClipboard() { + if (OpenClipboard(NULL)) { + EmptyClipboard(); + + int len = GetWindowTextLengthW(g_hHashEdit) + 1; + HGLOBAL hMem = GlobalAlloc(GMEM_MOVEABLE, len * sizeof(WCHAR)); + + if (hMem) { + WCHAR* pszMem = (WCHAR*)GlobalLock(hMem); + GetWindowTextW(g_hHashEdit, pszMem, len); + GlobalUnlock(hMem); + + SetClipboardData(CF_UNICODETEXT, hMem); + } + + CloseClipboard(); + } +} + +// 窗口过程 +LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { + switch (message) { + case WM_CREATE: + InitControls(hWnd); + break; + + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDC_BROWSE_BUTTON: + BrowseFile(hWnd); + break; + + case IDC_CALCULATE_BUTTON: + CalculateHash(); + break; + + case IDC_COPY_BUTTON: + CopyHashToClipboard(); + break; + } + break; + + case WM_DESTROY: + PostQuitMessage(0); + break; + + default: + return DefWindowProc(hWnd, message, wParam, lParam); + } + return 0; +} + +// 程序入口 +int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { + // 注册窗口类 + WNDCLASSEXW wcex; + wcex.cbSize = sizeof(WNDCLASSEX); + wcex.style = CS_HREDRAW | CS_VREDRAW; + wcex.lpfnWndProc = WndProc; + wcex.cbClsExtra = 0; + wcex.cbWndExtra = 0; + wcex.hInstance = hInstance; + wcex.hIcon = LoadIcon(NULL, IDI_APPLICATION); + wcex.hCursor = LoadCursor(NULL, IDC_ARROW); + wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); + wcex.lpszMenuName = NULL; + wcex.lpszClassName = L"HashValueExtractor"; + wcex.hIconSm = LoadIcon(NULL, IDI_APPLICATION); + + if (!RegisterClassExW(&wcex)) { + return 1; + } + + // 创建窗口 + HWND hWnd = CreateWindowW( + L"HashValueExtractor", L"哈希值提取器", + WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT, CW_USEDEFAULT, 420, 300, + NULL, NULL, hInstance, NULL); + + if (!hWnd) { + return 1; + } + + // 显示窗口 + ShowWindow(hWnd, nCmdShow); + UpdateWindow(hWnd); + + // 消息循环 + MSG msg; + while (GetMessage(&msg, NULL, 0, 0)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + + return (int)msg.wParam; +} diff --git a/others/C/hash_value_extractor/src/md5.c b/others/C/hash_value_extractor/src/md5.c new file mode 100644 index 0000000..32b539e --- /dev/null +++ b/others/C/hash_value_extractor/src/md5.c @@ -0,0 +1,35 @@ +#include "hash_calculator.h" +#include "string_util.h" +#include +#include +#include + +int calculate_md5(const char* filename, char* output) { + FILE* file = fopen(filename, "rb"); + if (!file) return -1; + + EVP_MD_CTX* mdctx = EVP_MD_CTX_new(); + const EVP_MD* md = EVP_md5(); + unsigned char hash[EVP_MAX_MD_SIZE]; + unsigned int hash_len = 0; + + EVP_DigestInit_ex(mdctx, md, NULL); + + unsigned char buffer[1024]; + size_t bytes_read; + while ((bytes_read = fread(buffer, 1, sizeof(buffer), file))) { + EVP_DigestUpdate(mdctx, buffer, bytes_read); + } + + EVP_DigestFinal_ex(mdctx, hash, &hash_len); + EVP_MD_CTX_free(mdctx); + fclose(file); + + char* hex = bin_to_hex(hash, hash_len); + if (hex) { + strcpy(output, hex); + str_free(hex); + return 0; + } + return -1; +} diff --git a/others/C/hash_value_extractor/src/sha256.c b/others/C/hash_value_extractor/src/sha256.c new file mode 100644 index 0000000..b6df859 --- /dev/null +++ b/others/C/hash_value_extractor/src/sha256.c @@ -0,0 +1,35 @@ +#include "hash_calculator.h" +#include "string_util.h" +#include +#include +#include + +int calculate_sha256(const char* filename, char* output) { + FILE* file = fopen(filename, "rb"); + if (!file) return -1; + + EVP_MD_CTX* mdctx = EVP_MD_CTX_new(); + const EVP_MD* md = EVP_sha256(); + unsigned char hash[EVP_MAX_MD_SIZE]; + unsigned int hash_len = 0; + + EVP_DigestInit_ex(mdctx, md, NULL); + + unsigned char buffer[1024]; + size_t bytes_read; + while ((bytes_read = fread(buffer, 1, sizeof(buffer), file))) { + EVP_DigestUpdate(mdctx, buffer, bytes_read); + } + + EVP_DigestFinal_ex(mdctx, hash, &hash_len); + EVP_MD_CTX_free(mdctx); + fclose(file); + + char* hex = bin_to_hex(hash, hash_len); + if (hex) { + strcpy(output, hex); + str_free(hex); + return 0; + } + return -1; +} diff --git a/others/C/hash_value_extractor/src/sha512.c b/others/C/hash_value_extractor/src/sha512.c new file mode 100644 index 0000000..a6dd1b6 --- /dev/null +++ b/others/C/hash_value_extractor/src/sha512.c @@ -0,0 +1,35 @@ +#include "hash_calculator.h" +#include "string_util.h" +#include +#include +#include + +int calculate_sha512(const char* filename, char* output) { + FILE* file = fopen(filename, "rb"); + if (!file) return -1; + + EVP_MD_CTX* mdctx = EVP_MD_CTX_new(); + const EVP_MD* md = EVP_sha512(); + unsigned char hash[EVP_MAX_MD_SIZE]; + unsigned int hash_len = 0; + + EVP_DigestInit_ex(mdctx, md, NULL); + + unsigned char buffer[1024]; + size_t bytes_read; + while ((bytes_read = fread(buffer, 1, sizeof(buffer), file))) { + EVP_DigestUpdate(mdctx, buffer, bytes_read); + } + + EVP_DigestFinal_ex(mdctx, hash, &hash_len); + EVP_MD_CTX_free(mdctx); + fclose(file); + + char* hex = bin_to_hex(hash, hash_len); + if (hex) { + strcpy(output, hex); + str_free(hex); + return 0; + } + return -1; +} diff --git a/others/C/hash_value_extractor/src/string_util.c b/others/C/hash_value_extractor/src/string_util.c new file mode 100644 index 0000000..220d980 --- /dev/null +++ b/others/C/hash_value_extractor/src/string_util.c @@ -0,0 +1,120 @@ +#include "string_util.h" +#include +#include + +// 内存池块大小 +#define MEMORY_BLOCK_SIZE 4096 + +// 内存池结构 +typedef struct MemoryBlock { + char* buffer; + size_t used; + struct MemoryBlock* next; +} MemoryBlock; + +static MemoryBlock* memory_pool = NULL; + +// 初始化内存池 +static void init_memory_pool() { + if (memory_pool == NULL) { + memory_pool = malloc(sizeof(MemoryBlock)); + memory_pool->buffer = malloc(MEMORY_BLOCK_SIZE); + memory_pool->used = 0; + memory_pool->next = NULL; + } +} + +// 从内存池分配 +static char* pool_alloc(size_t size) { + init_memory_pool(); + + MemoryBlock* block = memory_pool; + while (block != NULL) { + if (MEMORY_BLOCK_SIZE - block->used >= size) { + char* ptr = block->buffer + block->used; + block->used += size; + return ptr; + } + if (block->next == NULL) { + block->next = malloc(sizeof(MemoryBlock)); + block = block->next; + block->buffer = malloc(MEMORY_BLOCK_SIZE); + block->used = 0; + block->next = NULL; + } else { + block = block->next; + } + } + return NULL; +} + +char* str_alloc(size_t size) { + // 小内存从池分配,大内存直接分配 + if (size <= MEMORY_BLOCK_SIZE / 4) { + char* ptr = pool_alloc(size + 1); // +1 for null terminator + if (ptr != NULL) { + ptr[size] = '\0'; + return ptr; + } + } + char* ptr = malloc(size + 1); + if (ptr != NULL) { + ptr[size] = '\0'; + } + return ptr; +} + +void str_free(char* str) { + // 池分配的内存不单独释放 + if (str == NULL) return; + + // 检查是否在内存池中 + MemoryBlock* block = memory_pool; + while (block != NULL) { + if (str >= block->buffer && str < block->buffer + MEMORY_BLOCK_SIZE) { + return; // 池内存不释放 + } + block = block->next; + } + + free(str); +} + +char* str_copy(const char* src) { + if (src == NULL) return NULL; + + size_t len = strlen(src); + char* dest = str_alloc(len); + if (dest != NULL) { + memcpy(dest, src, len); + } + return dest; +} + +char* str_concat(const char* str1, const char* str2) { + if (str1 == NULL) return str_copy(str2); + if (str2 == NULL) return str_copy(str1); + + size_t len1 = strlen(str1); + size_t len2 = strlen(str2); + char* result = str_alloc(len1 + len2); + if (result != NULL) { + memcpy(result, str1, len1); + memcpy(result + len1, str2, len2); + } + return result; +} + +char* bin_to_hex(const unsigned char* data, size_t len) { + if (data == NULL || len == 0) return NULL; + + char* hex = str_alloc(len * 2); + if (hex != NULL) { + static const char hex_chars[] = "0123456789abcdef"; + for (size_t i = 0; i < len; i++) { + hex[i * 2] = hex_chars[(data[i] >> 4) & 0x0F]; + hex[i * 2 + 1] = hex_chars[data[i] & 0x0F]; + } + } + return hex; +}