h_sw_registro/src/registration_api.cpp
2025-07-26 10:32:02 +08:00

215 lines
6.5 KiB
C++

#include "registration_api.h"
#include "machine_code.h"
#include "sha256.h"
#include <string>
#include <chrono>
#include <sstream>
#include <iomanip>
#include <fstream>
#include <vector>
#include <algorithm>
// 全局变量来存储机器码和密钥,避免重复计算
static std::string machineCode_cache;
static std::string licenseKey_cache;
static std::string expiration_date_str = "2099-12-31"; // 默认永久
// 内部函数,用于初始化缓存
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
}
}
// --- 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) {
std::stringstream ss;
ss << std::hex << std::setfill('0');
for (unsigned char c : in) {
ss << std::setw(2) << static_cast<int>(c);
}
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
}
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);
}
return output;
}
// 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.
static char machineCode_cstr[256];
static char licenseKey_cstr[256];
const char* GetMachineCode() {
InitializeCache();
strncpy_s(machineCode_cstr, machineCode_cache.c_str(), sizeof(machineCode_cstr) - 1);
machineCode_cstr[sizeof(machineCode_cstr) - 1] = '\0';
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; // 失败
}
std::string mc_str(machine_code);
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);
// 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; // 失败
}
license_file << encrypted_date_hex << std::endl;
license_file << signature << std::endl;
license_file.close();
return 0; // 成功
}
int ValidateLicenseFile() {
std::ifstream license_file("License.data");
if (!license_file.is_open()) {
return 1; // 失败 - 文件不存在
}
std::string file_encrypted_date_hex;
std::string file_signature;
std::getline(license_file, file_encrypted_date_hex);
std::getline(license_file, file_signature);
license_file.close();
if (file_encrypted_date_hex.empty() || file_signature.empty()) {
return 1; // 失败 - 文件格式错误
}
// 1. Verify the signature first to ensure integrity
InitializeCache(); // Loads local machine code into machineCode_cache
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; // 失败 - 签名不匹配, 文件被篡改或不属于此机器
}
// 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);
// 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; // 失败 - 日期格式损坏
}
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 0; // 成功
}