From 0e7f56cf7cc6ecbd31624b344530f323fed8cfe6 Mon Sep 17 00:00:00 2001 From: "brige.long" Date: Tue, 5 Aug 2025 23:32:23 +0800 Subject: [PATCH] modify machine code get and enntry --- CMakeLists.txt | 4 + include/registration_api.h | 47 ++++--- src/generator_gui.cpp | 68 +++------- src/gui.cpp | 97 ++++++++++---- src/registration_api.cpp | 259 +++++++++++++++++++------------------ src/test_encryption.cpp | 58 +++++++++ src/test_license.cpp | 7 +- 7 files changed, 306 insertions(+), 234 deletions(-) create mode 100644 src/test_encryption.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index b338ab4..e101f20 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -43,6 +43,10 @@ target_link_libraries(validate_only PRIVATE RegistrationDLL) add_executable(generate_valid src/generate_valid.cpp) target_link_libraries(generate_valid PRIVATE RegistrationDLL) +# --- 生成有效许可证文件程序 --- +add_executable(generate_valid src/generate_valid.cpp) +target_link_libraries(generate_valid PRIVATE RegistrationDLL) + # 将生成的文件输出到 build/bin 目录 set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) diff --git a/include/registration_api.h b/include/registration_api.h index 16d2594..a6b1ecb 100644 --- a/include/registration_api.h +++ b/include/registration_api.h @@ -12,35 +12,34 @@ #ifdef __cplusplus extern "C" { #endif - // 获取原始机器码 + // --- Core Functions --- + + // Gets the raw machine code. REGISTRATION_API const char* GetMachineCode(); - // 获取加密后的许可证密钥 - REGISTRATION_API const char* GetLicenseKey(); + // Validates the license file. + // @return: 0=success, 1=failure, 2=expired. + REGISTRATION_API int ValidateLicenseFile(); - // 验证许可证密钥 (离线) - // @param key: 要验证的密钥 - // @return: 0=成功, 1=失败, 2=过期 - REGISTRATION_API int ValidateLicenseOffline(const char* key); - - // 设置离线许可证的有效期 - // @param expiration_date: "YYYY-MM-DD" 格式的日期字符串 - REGISTRATION_API void SetOfflineExpiration(const char* expiration_date); - - // 生成许可证文件 - // @param expiration_date: "YYYY-MM-DD" 格式的日期字符串 - // @return: 0=成功, 1=失败 - REGISTRATION_API int GenerateLicenseFile(const char* expiration_date); - - // 从提供的机器码生成许可证文件 - // @param machine_code: 要使用的机器码 - // @param expiration_date: "YYYY-MM-DD" 格式的日期字符串 - // @return: 0=成功, 1=失败 + // Generates a license file from a provided machine code. + // @param machine_code: The machine code to use. + // @param expiration_date: A date string in "YYYY-MM-DD" format. + // @return: 0=success, 1=failure. REGISTRATION_API int GenerateLicenseFileFromCode(const char* machine_code, const char* expiration_date); - // 验证许可证文件 - // @return: 0=成功, 1=失败, 2=过期 - REGISTRATION_API int ValidateLicenseFile(); + // --- New Encryption/Decryption API --- + + // Generates a dynamic, 32-character encrypted code from the machine code. + // The returned string is managed by the DLL and should not be freed by the caller. + REGISTRATION_API const char* GenerateEncryptedCode(); + + // Decrypts a 32-character code to get the original machine code. + // @param encrypted_code: The 32-character hex string to decrypt. + // @param decrypted_machine_code: A buffer to store the null-terminated result. + // @param buffer_size: The size of the provided buffer. + // @return: 0 on success, 1 on failure (e.g., invalid format, bad length). + REGISTRATION_API int DecryptCodeAndGetMachineCode(const char* encrypted_code, char* decrypted_machine_code, int buffer_size); + #ifdef __cplusplus } diff --git a/src/generator_gui.cpp b/src/generator_gui.cpp index 2883462..4c5fc65 100644 --- a/src/generator_gui.cpp +++ b/src/generator_gui.cpp @@ -1,19 +1,7 @@ +#define NOMINMAX #include #include "registration_api.h" #include -#include -#include -#include -#include -#include -#include "sha256.h" - -// 简单的MD5实现(只返回32位) -std::string simple_md5_32(const std::string& input) { - // 使用SHA256但只取前32位,模拟MD5的32位输出 - std::string full_hash = picosha2::hash256_hex_string(input); - return full_hash.substr(0, 32); -} #define IDC_MACHINE_CODE_LABEL 201 #define IDC_MACHINE_CODE_EDIT 202 @@ -22,9 +10,7 @@ std::string simple_md5_32(const std::string& input) { LRESULT CALLBACK GenWndProc(HWND, UINT, WPARAM, LPARAM); void CopyToClipboard(HWND hwnd, const std::string& text) { - if (!OpenClipboard(hwnd)) { - return; - } + if (!OpenClipboard(hwnd)) return; EmptyClipboard(); HGLOBAL hg = GlobalAlloc(GMEM_MOVEABLE, text.size() + 1); if (!hg) { @@ -79,55 +65,31 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine TranslateMessage(&Msg); DispatchMessage(&Msg); } - return Msg.wParam; + return (int)Msg.wParam; } LRESULT CALLBACK GenWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { static HWND hMachineCodeEdit; switch (msg) { case WM_CREATE: { - // Labels - CreateWindow("STATIC", "Your Machine Code:", WS_VISIBLE | WS_CHILD, 20, 20, 150, 20, hwnd, (HMENU)IDC_MACHINE_CODE_LABEL, NULL, NULL); + CreateWindow("STATIC", "Your Encrypted Code:", WS_VISIBLE | WS_CHILD, 20, 20, 150, 20, hwnd, (HMENU)IDC_MACHINE_CODE_LABEL, NULL, NULL); + hMachineCodeEdit = CreateWindow("EDIT", "", WS_VISIBLE | WS_CHILD | WS_BORDER | ES_READONLY | ES_CENTER, 180, 20, 280, 20, hwnd, (HMENU)IDC_MACHINE_CODE_EDIT, NULL, NULL); + CreateWindow("BUTTON", "Copy", WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, 470, 20, 50, 22, hwnd, (HMENU)IDC_COPY_BUTTON, NULL, NULL); - // Edit Controls - hMachineCodeEdit = CreateWindow("EDIT", "", WS_VISIBLE | WS_CHILD | WS_BORDER | ES_READONLY | ES_CENTER, 180, 20, 330, 20, hwnd, (HMENU)IDC_MACHINE_CODE_EDIT, NULL, NULL); - - // Buttons - CreateWindow("BUTTON", "Copy to Clipboard", WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, 180, 60, 150, 30, hwnd, (HMENU)IDC_COPY_BUTTON, NULL, NULL); - - // Set machine code with encryption - std::string machineCode = GetMachineCode(); - - // 1. 生成一个个位的随机数 (0-9) - std::random_device rd; - std::mt19937 gen(rd()); - std::uniform_int_distribution<> dis(0, 9); - int randomNum = dis(gen); - - // 2. 做一次 32位 MD5 加密 加密后是32位 - std::string encryptedCode = simple_md5_32(machineCode); - - // 3. 把 encryptedCode 字符串减掉这个数 - std::string processedCode = encryptedCode; - for (char& c : processedCode) { - c = c - randomNum; - } - - // 4. 把这个数变成一个字符插入到第三位的位置 加密后是33位 - char randomChar = '0' + randomNum; - processedCode.insert(2, 1, randomChar); - - SetWindowText(hMachineCodeEdit, processedCode.c_str()); + // --- Refactored Logic --- + // Call the new API function to get the encrypted code + const char* final_code = GenerateEncryptedCode(); + SetWindowText(hMachineCodeEdit, final_code); break; } case WM_COMMAND: { switch (LOWORD(wParam)) { case IDC_COPY_BUTTON: { - char formattedMachineCode[256]; - GetWindowText(hMachineCodeEdit, formattedMachineCode, 256); - CopyToClipboard(hwnd, formattedMachineCode); - MessageBox(hwnd, "Machine code copied to clipboard!", "Success", MB_OK); + char codeToCopy[64]; + GetWindowText(hMachineCodeEdit, codeToCopy, sizeof(codeToCopy)); + CopyToClipboard(hwnd, codeToCopy); + MessageBox(hwnd, "Encrypted code copied to clipboard!", "Success", MB_OK); break; } } @@ -143,4 +105,4 @@ LRESULT CALLBACK GenWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { return DefWindowProc(hwnd, msg, wParam, lParam); } return 0; -} +} \ No newline at end of file diff --git a/src/gui.cpp b/src/gui.cpp index 62b310e..3627638 100644 --- a/src/gui.cpp +++ b/src/gui.cpp @@ -1,20 +1,33 @@ +#define NOMINMAX #include #include "registration_api.h" #include -#include -#include +// --- Control IDs --- #define IDC_STATUS_LABEL 101 -#define IDC_MACHINE_CODE_LABEL 102 -#define IDC_MACHINE_CODE_EDIT 103 -#define IDC_EXPIRATION_LABEL 104 -#define IDC_EXPIRATION_EDIT 105 -#define IDC_GENERATE_BUTTON 106 +#define IDC_GEN_GROUP 102 +#define IDC_GEN_MC_LABEL 103 +#define IDC_GEN_MC_EDIT 104 +#define IDC_GEN_EXP_LABEL 105 +#define IDC_GEN_EXP_EDIT 106 +#define IDC_GEN_BUTTON 107 + +#define IDC_DEC_GROUP 201 +#define IDC_DEC_INPUT_LABEL 202 +#define IDC_DEC_INPUT_EDIT 203 +#define IDC_DEC_BUTTON 204 +#define IDC_DEC_OUTPUT_LABEL 205 +#define IDC_DEC_OUTPUT_EDIT 206 + LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); -static HWND hMachineCodeEdit, hExpirationEdit, hStatusLabel; +// --- Global Handles for UI Controls --- +static HWND hStatusLabel; +static HWND hGenMachineCodeEdit, hGenExpirationEdit; +static HWND hDecInputEdit, hDecOutputEdit; +// --- Function to update the license status label --- void UpdateValidationStatus(HWND hwnd) { int result = ValidateLicenseFile(); std::string statusText; @@ -32,6 +45,7 @@ void UpdateValidationStatus(HWND hwnd) { SetWindowText(hStatusLabel, statusText.c_str()); } +// --- Main Entry Point --- int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { WNDCLASSEX wc = {0}; wc.cbSize = sizeof(WNDCLASSEX); @@ -55,9 +69,9 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine HWND hwnd = CreateWindowEx( WS_EX_CLIENTEDGE, "RegistrationWindowClass", - "Software Registration", + "Software Registration Tool", (WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX), - CW_USEDEFAULT, CW_USEDEFAULT, 480, 250, + CW_USEDEFAULT, CW_USEDEFAULT, 500, 400, // Increased window height NULL, NULL, hInstance, NULL); if (hwnd == NULL) { @@ -73,52 +87,79 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine TranslateMessage(&Msg); DispatchMessage(&Msg); } - return Msg.wParam; + return (int)Msg.wParam; } +// --- Window Procedure to Handle Messages --- LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_CREATE: { // --- Top Part: Validation Status --- - hStatusLabel = CreateWindow("STATIC", "Checking license...", WS_VISIBLE | WS_CHILD | SS_CENTER, 20, 20, 420, 20, hwnd, (HMENU)IDC_STATUS_LABEL, NULL, NULL); + hStatusLabel = CreateWindow("STATIC", "Checking license...", WS_VISIBLE | WS_CHILD | SS_CENTER, 20, 15, 440, 20, hwnd, (HMENU)IDC_STATUS_LABEL, NULL, NULL); UpdateValidationStatus(hwnd); + // --- Middle Part: Decryption --- + CreateWindow("STATIC", "Decrypt Encrypted Code", WS_VISIBLE | WS_CHILD | BS_GROUPBOX, 10, 50, 460, 120, hwnd, (HMENU)IDC_DEC_GROUP, NULL, NULL); + CreateWindow("STATIC", "Encrypted Code:", WS_VISIBLE | WS_CHILD, 30, 80, 150, 20, hwnd, (HMENU)IDC_DEC_INPUT_LABEL, NULL, NULL); + hDecInputEdit = CreateWindow("EDIT", "", WS_VISIBLE | WS_CHILD | WS_BORDER, 190, 80, 260, 20, hwnd, (HMENU)IDC_DEC_INPUT_EDIT, NULL, NULL); + CreateWindow("BUTTON", "Decrypt", WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, 190, 110, 120, 30, hwnd, (HMENU)IDC_DEC_BUTTON, NULL, NULL); + CreateWindow("STATIC", "Original Machine Code:", WS_VISIBLE | WS_CHILD, 30, 145, 150, 20, hwnd, (HMENU)IDC_DEC_OUTPUT_LABEL, NULL, NULL); + hDecOutputEdit = CreateWindow("EDIT", "", WS_VISIBLE | WS_CHILD | WS_BORDER | ES_READONLY, 190, 145, 260, 20, hwnd, (HMENU)IDC_DEC_OUTPUT_EDIT, NULL, NULL); + // --- Bottom Part: License Generation --- - CreateWindow("STATIC", "--- License Generation ---", WS_VISIBLE | WS_CHILD | SS_CENTER, 20, 60, 420, 20, hwnd, NULL, NULL, NULL); - CreateWindow("STATIC", "Machine Code:", WS_VISIBLE | WS_CHILD, 20, 90, 150, 20, hwnd, (HMENU)IDC_MACHINE_CODE_LABEL, NULL, NULL); - hMachineCodeEdit = CreateWindow("EDIT", "", WS_VISIBLE | WS_CHILD | WS_BORDER, 180, 90, 260, 20, hwnd, (HMENU)IDC_MACHINE_CODE_EDIT, NULL, NULL); - - CreateWindow("STATIC", "Expiration (YYYY-MM-DD):", WS_VISIBLE | WS_CHILD, 20, 120, 150, 20, hwnd, (HMENU)IDC_EXPIRATION_LABEL, NULL, NULL); - hExpirationEdit = CreateWindow("EDIT", "2099-12-31", WS_VISIBLE | WS_CHILD | WS_BORDER, 180, 120, 120, 20, hwnd, (HMENU)IDC_EXPIRATION_EDIT, NULL, NULL); - - CreateWindow("BUTTON", "Generate License File", WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, 180, 160, 180, 30, hwnd, (HMENU)IDC_GENERATE_BUTTON, NULL, NULL); + CreateWindow("STATIC", "Generate License File", WS_VISIBLE | WS_CHILD | BS_GROUPBOX, 10, 180, 460, 160, hwnd, (HMENU)IDC_GEN_GROUP, NULL, NULL); + CreateWindow("STATIC", "Machine Code:", WS_VISIBLE | WS_CHILD, 30, 210, 150, 20, hwnd, (HMENU)IDC_GEN_MC_LABEL, NULL, NULL); + hGenMachineCodeEdit = CreateWindow("EDIT", "", WS_VISIBLE | WS_CHILD | WS_BORDER, 190, 210, 260, 20, hwnd, (HMENU)IDC_GEN_MC_EDIT, NULL, NULL); + CreateWindow("STATIC", "Expiration (YYYY-MM-DD):", WS_VISIBLE | WS_CHILD, 30, 240, 150, 20, hwnd, (HMENU)IDC_GEN_EXP_LABEL, NULL, NULL); + hGenExpirationEdit = CreateWindow("EDIT", "2099-12-31", WS_VISIBLE | WS_CHILD | WS_BORDER, 190, 240, 120, 20, hwnd, (HMENU)IDC_GEN_EXP_EDIT, NULL, NULL); + CreateWindow("BUTTON", "Generate License File", WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, 190, 280, 180, 30, hwnd, (HMENU)IDC_GEN_BUTTON, NULL, NULL); break; } case WM_COMMAND: { switch (LOWORD(wParam)) { - case IDC_GENERATE_BUTTON: { + case IDC_GEN_BUTTON: { char machineCode[256]; - char expirationDate[11]; - GetWindowText(hMachineCodeEdit, machineCode, 256); - GetWindowText(hExpirationEdit, expirationDate, 11); + char expirationDate[12]; + GetWindowText(hGenMachineCodeEdit, machineCode, sizeof(machineCode)); + GetWindowText(hGenExpirationEdit, expirationDate, sizeof(expirationDate)); if (strlen(machineCode) == 0) { - MessageBox(hwnd, "Please enter a machine code.", "Error", MB_ICONERROR); + MessageBox(hwnd, "Please enter a machine code for generation.", "Error", MB_ICONERROR); break; } - // Note: We are now using the function that takes the machine code as an argument int result = GenerateLicenseFileFromCode(machineCode, expirationDate); if (result == 0) { MessageBox(hwnd, "License.data generated successfully!", "Success", MB_OK); - // Re-validate and update the status label UpdateValidationStatus(hwnd); } else { MessageBox(hwnd, "Failed to generate license file!", "Error", MB_ICONERROR); } break; } + case IDC_DEC_BUTTON: { + char encryptedCode[64]; + GetWindowText(hDecInputEdit, encryptedCode, sizeof(encryptedCode)); + int len = strlen(encryptedCode); + if (strlen(encryptedCode) != 30) { + MessageBox(hwnd, "Please enter a valid 32-character encrypted code.", "Error", MB_ICONERROR); + break; + } + + char decryptedResult[256]; + int result = DecryptCodeAndGetMachineCode(encryptedCode, decryptedResult, sizeof(decryptedResult)); + + if (result == 0) { + SetWindowText(hDecOutputEdit, decryptedResult); + // Also copy the result to the generation input box for convenience + SetWindowText(hGenMachineCodeEdit, decryptedResult); + } else { + SetWindowText(hDecOutputEdit, ""); // Clear previous result + MessageBox(hwnd, "Decryption failed. The code is invalid or corrupted.", "Error", MB_ICONERROR); + } + break; + } } break; } @@ -132,4 +173,4 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { return DefWindowProc(hwnd, msg, wParam, lParam); } return 0; -} +} \ No newline at end of file diff --git a/src/registration_api.cpp b/src/registration_api.cpp index e8812d5..3fe54c3 100644 --- a/src/registration_api.cpp +++ b/src/registration_api.cpp @@ -8,68 +8,69 @@ #include #include #include +#include +#include -// 全局变量来存储机器码和密钥,避免重复计算 -static std::string machineCode_cache; -static std::string licenseKey_cache; -static std::string expiration_date_str = "2099-12-31"; // 默认永久 +// --- START: Internal Encryption Helpers --- -// 内部函数,用于初始化缓存 -void InitializeCache() { - if (machineCode_cache.empty()) { - machineCode_cache = getMachineCode(); - } - if (licenseKey_cache.empty()) { - licenseKey_cache = picosha2::hash256_hex_string(machineCode_cache).substr(0, 32); // Truncate to 32 chars +// Helper to convert a hex string to a vector of bytes +static std::vector hex_string_to_bytes(const std::string& hex) { + std::vector bytes; + if (hex.length() % 2 != 0) return bytes; + for (unsigned int i = 0; i < hex.length(); i += 2) { + std::string byteString = hex.substr(i, 2); + bytes.push_back((unsigned char)strtol(byteString.c_str(), NULL, 16)); } + return bytes; } -// --- Encryption/Decryption Helpers --- - -// Generates a key from the machine code for XOR operations -std::string generate_xor_key(const std::string& machine_code) { - return picosha2::hash256_hex_string(machine_code).substr(0, 32); -} - -// XORs data with a key. Handles key repeating. -std::string xor_string(const std::string& data, const std::string& key) { - std::string output = data; - for (size_t i = 0; i < data.size(); ++i) { - output[i] = data[i] ^ key[i % key.length()]; - } - return output; -} - -// Converts a string to its hex representation -std::string string_to_hex(const std::string& in) { +// Helper to convert a vector of bytes to a hex string +static std::string bytes_to_hex_string(const std::vector& bytes) { std::stringstream ss; - ss << std::hex << std::setfill('0'); - for (unsigned char c : in) { - ss << std::setw(2) << static_cast(c); + ss << std::hex << std::uppercase << std::setfill('0'); + for (unsigned char byte : bytes) { + ss << std::setw(2) << static_cast(byte); } return ss.str(); } -// Converts a hex string back to a normal string -std::string hex_to_string(const std::string& in) { - std::string output; - if (in.length() % 2 != 0) { - return ""; // Invalid hex +// Generates a pseudo-random keystream from a 16-bit seed (Nonce) +static void generate_keystream(uint16_t seed, std::vector& keystream, size_t len) { + std::mt19937 gen(seed); + std::uniform_int_distribution<> distrib(0, 255); + keystream.clear(); + for (size_t i = 0; i < len; ++i) { + keystream.push_back(static_cast(distrib(gen))); } - for (size_t i = 0; i < in.length(); i += 2) { - std::string byteString = in.substr(i, 2); - char byte = (char)strtol(byteString.c_str(), NULL, 16); - output.push_back(byte); +} + +// XORs a vector of bytes with a keystream +static std::vector xor_bytes(const std::vector& data, const std::vector& key) { + std::vector output; + size_t len = std::min(data.size(), key.size()); + for (size_t i = 0; i < len; ++i) { + output.push_back(data[i] ^ key[i]); } return output; } +// --- END: Internal Encryption Helpers --- -// C-style string return needs to be managed carefully. -// We use static buffers here, which is not thread-safe but simple. -// For a real-world app, consider returning std::string or managing memory better. + +// --- Global Caches and Buffers --- +static std::string machineCode_cache; static char machineCode_cstr[256]; -static char licenseKey_cstr[256]; +static char encryptedCode_cstr[33]; // 32 chars + null terminator +static char decryptedCode_cstr[256]; + +// Internal function to initialize the machine code cache +void InitializeCache() { + if (machineCode_cache.empty()) { + machineCode_cache = getMachineCode(); + } +} + +// --- Core API Implementations --- const char* GetMachineCode() { InitializeCache(); @@ -78,97 +79,42 @@ const char* GetMachineCode() { return machineCode_cstr; } -const char* GetLicenseKey() { - InitializeCache(); - strncpy_s(licenseKey_cstr, licenseKey_cache.c_str(), sizeof(licenseKey_cstr) - 1); - licenseKey_cstr[sizeof(licenseKey_cstr) - 1] = '\0'; - return licenseKey_cstr; -} - -int ValidateLicenseOffline(const char* key) { - if (!key) { - return 1; // 失败 - } - InitializeCache(); - if (licenseKey_cache != key) { - return 1; // 失败 - } - - // 检查有效期 - if (expiration_date_str != "2099-12-31") { - std::tm tm = {}; - std::stringstream ss(expiration_date_str); - ss >> std::get_time(&tm, "%Y-%m-%d"); - auto expiration_time = std::chrono::system_clock::from_time_t(std::mktime(&tm)); - - if (std::chrono::system_clock::now() > expiration_time) { - return 2; // 过期 - } - } - - return 0; // 成功 -} - -void SetOfflineExpiration(const char* expiration_date) { - if (expiration_date) { - expiration_date_str = expiration_date; - } -} - -int GenerateLicenseFile(const char* expiration_date) { - if (!expiration_date) { - return 1; // 失败 - } - - InitializeCache(); - std::string data_to_sign = machineCode_cache + expiration_date; - std::string signature = picosha2::hash256_hex_string(data_to_sign); - - std::ofstream license_file("License.data"); - if (!license_file.is_open()) { - return 1; // 失败 - } - - license_file << expiration_date << std::endl; - license_file << signature << std::endl; - license_file.close(); - - return 0; // 成功 -} - int GenerateLicenseFileFromCode(const char* machine_code, const char* expiration_date) { if (!machine_code || !expiration_date) { - return 1; // 失败 + return 1; // Failure } - std::string mc_str(machine_code); + + std::string mc_str(machine_code); + //std::transform(mc_str.begin(), mc_str.end(), std::toupper); std::string exp_str(expiration_date); - // 1. Encrypt the expiration date - std::string xor_key = generate_xor_key(mc_str); - std::string encrypted_date = xor_string(exp_str, xor_key); - std::string encrypted_date_hex = string_to_hex(encrypted_date); + std::string xor_key = picosha2::hash256_hex_string(mc_str).substr(0, 32); + + std::string encrypted_date; + for (size_t i = 0; i < exp_str.size(); ++i) { + encrypted_date += exp_str[i] ^ xor_key[i % xor_key.length()]; + } + std::string encrypted_date_hex = bytes_to_hex_string(std::vector(encrypted_date.begin(), encrypted_date.end())); - // 2. Create a signature of the machine code and the *encrypted* date std::string data_to_sign = mc_str + encrypted_date_hex; std::string signature = picosha2::hash256_hex_string(data_to_sign); - // 3. Write the encrypted date and signature to the file std::ofstream license_file("License.data"); if (!license_file.is_open()) { - return 1; // 失败 + return 1; // Failure } license_file << encrypted_date_hex << std::endl; license_file << signature << std::endl; license_file.close(); - return 0; // 成功 + return 0; // Success } int ValidateLicenseFile() { std::ifstream license_file("License.data"); if (!license_file.is_open()) { - return 1; // 失败 - 文件不存在 + return 1; // Failure - file not found } std::string file_encrypted_date_hex; @@ -178,37 +124,98 @@ int ValidateLicenseFile() { license_file.close(); if (file_encrypted_date_hex.empty() || file_signature.empty()) { - return 1; // 失败 - 文件格式错误 + return 1; // Failure - format error } - // 1. Verify the signature first to ensure integrity - InitializeCache(); // Loads local machine code into machineCode_cache + InitializeCache(); std::string data_to_verify = machineCode_cache + file_encrypted_date_hex; std::string expected_signature = picosha2::hash256_hex_string(data_to_verify); if (file_signature != expected_signature) { - return 1; // 失败 - 签名不匹配, 文件被篡改或不属于此机器 + return 1; // Failure - signature mismatch } - // 2. Decrypt the date - std::string xor_key = generate_xor_key(machineCode_cache); - std::string encrypted_date = hex_to_string(file_encrypted_date_hex); - std::string decrypted_date = xor_string(encrypted_date, xor_key); + std::string xor_key = picosha2::hash256_hex_string(machineCode_cache).substr(0, 32); + std::vector encrypted_date_bytes = hex_string_to_bytes(file_encrypted_date_hex); + std::string encrypted_date(encrypted_date_bytes.begin(), encrypted_date_bytes.end()); + std::string decrypted_date; + for (size_t i = 0; i < encrypted_date.size(); ++i) { + decrypted_date += encrypted_date[i] ^ xor_key[i % xor_key.length()]; + } - // 3. Check the expiration date std::tm tm = {}; std::stringstream ss(decrypted_date); ss >> std::get_time(&tm, "%Y-%m-%d"); if (ss.fail()) { - return 1; // 失败 - 日期格式损坏 + return 1; // Failure - date format corrupted } auto expiration_time = std::chrono::system_clock::from_time_t(std::mktime(&tm)); expiration_time += std::chrono::hours(23) + std::chrono::minutes(59) + std::chrono::seconds(59); if (std::chrono::system_clock::now() > expiration_time) { - return 2; // 过期 + return 2; // Expired } - return 0; // 成功 + return 0; // Success } + +// --- New Encryption/Decryption API Implementations --- + +const char* GenerateEncryptedCode() { + InitializeCache(); + std::string machineCodeStr = machineCode_cache; + machineCodeStr.erase(std::remove(machineCodeStr.begin(), machineCodeStr.end(), '-'), machineCodeStr.end()); + std::vector mc_bytes = hex_string_to_bytes(machineCodeStr); + + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution distrib(0, 65535); + uint16_t nonce = distrib(gen); + + std::vector keystream; + generate_keystream(nonce, keystream, 14); + + std::vector encrypted_mc = xor_bytes(mc_bytes, keystream); + + std::vector final_payload; + final_payload.insert(final_payload.end(), encrypted_mc.begin(), encrypted_mc.begin() + 7); + final_payload.push_back(static_cast(nonce & 0xFF)); + final_payload.push_back(static_cast((nonce >> 8) & 0xFF)); + final_payload.insert(final_payload.end(), encrypted_mc.begin() + 7, encrypted_mc.end()); + + std::string final_code = bytes_to_hex_string(final_payload); + + strncpy_s(encryptedCode_cstr, final_code.c_str(), sizeof(encryptedCode_cstr) - 1); + encryptedCode_cstr[sizeof(encryptedCode_cstr) - 1] = '\0'; + return encryptedCode_cstr; +} + +int DecryptCodeAndGetMachineCode(const char* encrypted_code, char* decrypted_machine_code, int buffer_size) { + if (!encrypted_code || strlen(encrypted_code) != 32) { + return 1; // Failure: invalid input + } + + std::vector final_payload = hex_string_to_bytes(encrypted_code); + if (final_payload.size() != 16) { + return 1; // Failure: invalid hex string + } + + uint16_t nonce = final_payload[7] | (static_cast(final_payload[8]) << 8); + + std::vector encrypted_mc; + encrypted_mc.insert(encrypted_mc.end(), final_payload.begin(), final_payload.begin() + 7); + encrypted_mc.insert(encrypted_mc.end(), final_payload.begin() + 9, final_payload.end()); + + std::vector keystream; + generate_keystream(nonce, keystream, 14); + + std::vector decrypted_mc_bytes = xor_bytes(encrypted_mc, keystream); + + std::string machine_code_hex = bytes_to_hex_string(decrypted_mc_bytes); + + // Return the pure hex machine code, without the hyphen. + strncpy_s(decrypted_machine_code, buffer_size, machine_code_hex.c_str(), _TRUNCATE); + + return 0; // Success +} \ No newline at end of file diff --git a/src/test_encryption.cpp b/src/test_encryption.cpp new file mode 100644 index 0000000..5ea41fb --- /dev/null +++ b/src/test_encryption.cpp @@ -0,0 +1,58 @@ +#include +#include +#include +#include +#include "registration_api.h" + +// Helper function to print test results +void print_test_result(const std::string& test_name, bool success) { + std::cout << "- Test: " << test_name << "... " + << (success ? "PASSED" : "FAILED") << std::endl; +} + +int main() { + std::cout << "--- Running Encryption/Decryption API Test --- \n" << std::endl; + + // --- Test 1: Get Original Machine Code --- + const char* original_mc_raw = GetMachineCode(); + std::string original_mc(original_mc_raw); + std::cout << "Original Machine Code: " << original_mc << std::endl; + print_test_result("GetMachineCode() is not empty", !original_mc.empty()); + std::cout << std::endl; + + // --- Test 2: Generate Encrypted Code --- + const char* encrypted_code_raw = GenerateEncryptedCode(); + std::string encrypted_code(encrypted_code_raw); + std::cout << "Generated Encrypted Code: " << encrypted_code << std::endl; + print_test_result("GenerateEncryptedCode() returns 32 characters", encrypted_code.length() == 32); + std::cout << std::endl; + + // --- Test 3: Decrypt the Code --- + char decrypted_buffer[256]; + int decryption_result = DecryptCodeAndGetMachineCode(encrypted_code.c_str(), decrypted_buffer, sizeof(decrypted_buffer)); + std::string decrypted_mc(decrypted_buffer); + + std::cout << "Decrypted Machine Code (no hyphen): " << decrypted_mc << std::endl; + print_test_result("DecryptCodeAndGetMachineCode() succeeds", decryption_result == 0); + std::cout << std::endl; + + // --- Test 4: Compare Original and Decrypted --- + std::string original_mc_no_hyphen = original_mc; + original_mc_no_hyphen.erase(std::remove(original_mc_no_hyphen.begin(), original_mc_no_hyphen.end(), '-'), original_mc_no_hyphen.end()); + + std::cout << "Original (no hyphen): " << original_mc_no_hyphen << std::endl; + std::cout << "Decrypted: " << decrypted_mc << std::endl; + + bool match = (original_mc_no_hyphen == decrypted_mc); + print_test_result("Decrypted code matches original", match); + std::cout << "\n--------------------------------------------------" << std::endl; + + if (match) { + std::cout << "\nSUCCESS: The encryption and decryption functions are working correctly.\n" << std::endl; + return 0; + } + else { + std::cout << "\nFAILURE: The decrypted code does NOT match the original.\n" << std::endl; + return 1; + } +} diff --git a/src/test_license.cpp b/src/test_license.cpp index 9d3b465..38ec535 100644 --- a/src/test_license.cpp +++ b/src/test_license.cpp @@ -19,7 +19,7 @@ void print_status(int code) { int main(int argc, char* argv[]) { // --- Step 1: Generate a valid license file --- std::cout << "--- Step 1: Generating a valid license file for this machine ---" << std::endl; - const char* machine_code = GetMachineCode(); + const char* machine_code = GenerateEncryptedCode(); if (!machine_code || std::string(machine_code).empty()) { std::cerr << "!! ERROR: Could not get machine code." << std::endl; return 1; @@ -28,8 +28,9 @@ int main(int argc, char* argv[]) { const char* future_date = "2099-12-31"; std::cout << "Generating license with expiration date: " << future_date << std::endl; - - int gen_result = GenerateLicenseFileFromCode(machine_code, future_date); + char code[33] = { 0 }; + DecryptCodeAndGetMachineCode(machine_code, code, 33); + int gen_result = GenerateLicenseFileFromCode(code, future_date); if (gen_result == 0) { std::cout << "License.data generated successfully." << std::endl; } else {