diff --git a/Doc/Pic_V1.0/仿真调度引擎作图.drawio b/Doc/Pic_V1.0/仿真调度引擎作图.drawio index 8bb629f..a0dfec9 100644 --- a/Doc/Pic_V1.0/仿真调度引擎作图.drawio +++ b/Doc/Pic_V1.0/仿真调度引擎作图.drawio @@ -1,141 +1,173 @@ - + - + - - + + - - + + - - + + - + + + + + + + + + + + + + + + + + + + - + + + + + - + - - - - - - - + - + - - + + - + - - + + - + - + - - + + - + - + - - + + - + - + - + - + - - + + - + - + - - - - + - - + + - - + + + + - + + + + + + + - + - + - - + + + + - + - - + + - - + + - + - + + + + + + + + + + + + + + + - - + + - - + + + + - - + + - - - - - - - - - - - + + + + diff --git a/Doc/一体化二进制数据包软件概要设计说明-V1.0.docx b/Doc/一体化二进制数据包软件概要设计说明-V1.0.docx index 0ec76df..0a09d9c 100644 Binary files a/Doc/一体化二进制数据包软件概要设计说明-V1.0.docx and b/Doc/一体化二进制数据包软件概要设计说明-V1.0.docx differ diff --git a/Doc/一体化二进制数据包软件概要设计说明-V1.0.pdf b/Doc/一体化二进制数据包软件概要设计说明-V1.0.pdf index 953ec82..f5dfaed 100644 Binary files a/Doc/一体化二进制数据包软件概要设计说明-V1.0.pdf and b/Doc/一体化二进制数据包软件概要设计说明-V1.0.pdf differ diff --git a/Doc/一体化二进制数据包软件详细设计说明-V1.0.docx b/Doc/一体化二进制数据包软件详细设计说明-V1.0.docx index e506168..3ffff4c 100644 Binary files a/Doc/一体化二进制数据包软件详细设计说明-V1.0.docx and b/Doc/一体化二进制数据包软件详细设计说明-V1.0.docx differ diff --git a/Release/database/XNSim.db b/Release/database/XNSim.db index add6004..5715766 100644 Binary files a/Release/database/XNSim.db and b/Release/database/XNSim.db differ diff --git a/Release/include/XNCore/XNCore_global.h b/Release/include/XNCore/XNCore_global.h index 7d5e11a..4186d67 100644 --- a/Release/include/XNCore/XNCore_global.h +++ b/Release/include/XNCore/XNCore_global.h @@ -256,8 +256,6 @@ public: using ThisType = cls; \ using SuperType = sup; -#define XN_UNUSED(x) (void)x - namespace XNSim { template diff --git a/Release/include/XNCore/XNLogger.h b/Release/include/XNCore/XNLogger.h index c9c2bfb..608544a 100644 --- a/Release/include/XNCore/XNLogger.h +++ b/Release/include/XNCore/XNLogger.h @@ -28,7 +28,7 @@ public: /** * @brief 日志等级 */ - enum LogLevel { Debug, Info, Warning, Error, Time }; + enum LogLevel { Debug, Info, Warning, Error }; /** * @brief 获取日志类实例 @@ -128,7 +128,7 @@ private: /** * @brief 调试颜色常量 */ - const std::string COLOR_DEBUG = "\033[34m"; // 蓝色 + const std::string COLOR_DEBUG = "\033[36m"; // 青色 /** * @brief 信息颜色常量 @@ -217,18 +217,20 @@ private: "A01021002: 单条日志参数数量超过限制,详见XNLogger.cpp:line 216"); std::string result = message; - // 使用初始化列表展开参数包 + + // 使用折叠表达式展开参数包 int index = 1; - // 使用lambda和std::initializer_list展开参数包 - (void)std::initializer_list{( - [&result, &index](const auto &value) { - std::string placeholder = "%" + std::to_string(index++); - size_t pos = result.find(placeholder); - if (pos != std::string::npos) { - result.replace(pos, placeholder.length(), convertToString(value)); - } - }(args), - 0)...}; + // 定义替换单个参数的lambda函数 + auto replacePlaceholder = [&result, &index](const auto &value) { + std::string placeholder = "%" + std::to_string(index++); + size_t pos = result.find(placeholder); + if (pos != std::string::npos) { + result.replace(pos, placeholder.length(), convertToString(value)); + } + }; + + // 使用折叠表达式对每个参数调用替换函数 + (replacePlaceholder(args), ...); return result; } }; @@ -236,19 +238,35 @@ private: /** * @brief 宏定义,用于输出调试日志 */ -#define LOG_DEBUG(message, ...) XNLoggerHelper::log(XNLogger::Debug, message, ##__VA_ARGS__) +template +inline void LOG_DEBUG(const std::string &message, Args &&...args) +{ + XNLoggerHelper::log(XNLogger::Debug, message, args...); +} /** - * @brief 宏定义,用于输出信息日志 + * @brief 模板函数,用于输出信息日志 */ -#define LOG_INFO(message, ...) XNLoggerHelper::log(XNLogger::Info, message, ##__VA_ARGS__) +template +inline void LOG_INFO(const std::string &message, Args &&...args) +{ + XNLoggerHelper::log(XNLogger::Info, message, args...); +} /** - * @brief 宏定义,用于输出警告日志 + * @brief 模板函数,用于输出警告日志 */ -#define LOG_WARNING(message, ...) XNLoggerHelper::log(XNLogger::Warning, message, ##__VA_ARGS__) +template +inline void LOG_WARNING(const std::string &message, Args &&...args) +{ + XNLoggerHelper::log(XNLogger::Warning, message, args...); +} /** - * @brief 宏定义,用于输出错误日志 + * @brief 模板函数,用于输出错误日志 */ -#define LOG_ERROR(message, ...) XNLoggerHelper::log(XNLogger::Error, message, ##__VA_ARGS__) +template +inline void LOG_ERROR(const std::string &message, Args &&...args) +{ + XNLoggerHelper::log(XNLogger::Error, message, args...); +} diff --git a/Release/include/XNMonitor/DataMonitor.h b/Release/include/XNMonitor/DataMonitor.h index 68d82bb..1a5ef14 100644 --- a/Release/include/XNMonitor/DataMonitor.h +++ b/Release/include/XNMonitor/DataMonitor.h @@ -4,8 +4,6 @@ #include "TypeDefine.h" #include "TopicManager.h" -#define THISUNUSED(x) (void)(x) - class XNFramework; using XNFrameworkPtr = std::shared_ptr; @@ -40,11 +38,10 @@ public: _isInitialized = false; }; - virtual void Initialize(XNFrameworkPtr framework, uint32_t modelId, uint32_t DDS_type) override + virtual void Initialize(XNFrameworkPtr framework [[maybe_unused]], + uint32_t modelId [[maybe_unused]], + uint32_t DDS_type [[maybe_unused]]) override { - THISUNUSED(framework); - THISUNUSED(modelId); - THISUNUSED(DDS_type); XNDDSErrorCode ret = TopicManager::Instance()->registerSubscriber( T::topic_name, diff --git a/Release/public_key.pem b/Release/public_key.pem new file mode 100644 index 0000000..576aa8e --- /dev/null +++ b/Release/public_key.pem @@ -0,0 +1,9 @@ +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxdmYwjqt2Jd7+PW4N/qi +KQALeEd4j6RqIiXMm8zYYYQSe3SSrEuOZYhUKqFcYX9KwEo05SeiJm6oiHJw/ADw +H6Tcn3XoNICrfeMdkpCV1OpAHq9WjaueYtwy3EZgBh7iFx0jOY8a4fpQUL+KeID9 +qeAYU+BXbPDIOkGVIu2saDfdwfMW2shR6kaNAto66MhfZMSqcGQfN9NkhmsdXahC +WuulopiM0k95LMr15TM3fqAvOOIvT+Us8l8OnnGYDYWPx6Gva3DILLa6ZvUXsLUE +519inlKdIILYszHCLnfs8hQPPrPk8Fa85v0PVVdSbBORCsQ0r9dN0dBFGJ/yGC8j +FQIDAQAB +-----END PUBLIC KEY----- diff --git a/XNCore/XNCore_global.h b/XNCore/XNCore_global.h index 7d5e11a..4186d67 100755 --- a/XNCore/XNCore_global.h +++ b/XNCore/XNCore_global.h @@ -256,8 +256,6 @@ public: using ThisType = cls; \ using SuperType = sup; -#define XN_UNUSED(x) (void)x - namespace XNSim { template diff --git a/XNCore/XNLogger.cpp b/XNCore/XNLogger.cpp index e754652..0398072 100755 --- a/XNCore/XNLogger.cpp +++ b/XNCore/XNLogger.cpp @@ -69,23 +69,16 @@ void XNLogger::log(LogLevel level, const std::string &message) break; } + coloredMessage += "\n"; + // 控制台输出 if (consoleOutputEnabled[level]) { - if (level == Time) { - // 如果是时间日志,则不换行,回退到该行开始 - std::cout << coloredMessage << "\r" << std::flush; - } else { - std::cout << coloredMessage << std::endl; - } + std::cout << coloredMessage; } // 文件输出 if (fileOutputEnabled[level] && logFile.is_open()) { - if (level == Time) { - logFile << logMessage << "\r" << std::flush; - } else { - logFile << logMessage << std::endl; - } + logFile << logMessage; } } @@ -110,8 +103,6 @@ std::string XNLogger::logLevelToString(LogLevel level) const return "WARNING"; case Error: return "ERROR"; - case Time: - return "TIME"; default: return "UNKNOWN"; } diff --git a/XNCore/XNLogger.h b/XNCore/XNLogger.h index c9c2bfb..608544a 100755 --- a/XNCore/XNLogger.h +++ b/XNCore/XNLogger.h @@ -28,7 +28,7 @@ public: /** * @brief 日志等级 */ - enum LogLevel { Debug, Info, Warning, Error, Time }; + enum LogLevel { Debug, Info, Warning, Error }; /** * @brief 获取日志类实例 @@ -128,7 +128,7 @@ private: /** * @brief 调试颜色常量 */ - const std::string COLOR_DEBUG = "\033[34m"; // 蓝色 + const std::string COLOR_DEBUG = "\033[36m"; // 青色 /** * @brief 信息颜色常量 @@ -217,18 +217,20 @@ private: "A01021002: 单条日志参数数量超过限制,详见XNLogger.cpp:line 216"); std::string result = message; - // 使用初始化列表展开参数包 + + // 使用折叠表达式展开参数包 int index = 1; - // 使用lambda和std::initializer_list展开参数包 - (void)std::initializer_list{( - [&result, &index](const auto &value) { - std::string placeholder = "%" + std::to_string(index++); - size_t pos = result.find(placeholder); - if (pos != std::string::npos) { - result.replace(pos, placeholder.length(), convertToString(value)); - } - }(args), - 0)...}; + // 定义替换单个参数的lambda函数 + auto replacePlaceholder = [&result, &index](const auto &value) { + std::string placeholder = "%" + std::to_string(index++); + size_t pos = result.find(placeholder); + if (pos != std::string::npos) { + result.replace(pos, placeholder.length(), convertToString(value)); + } + }; + + // 使用折叠表达式对每个参数调用替换函数 + (replacePlaceholder(args), ...); return result; } }; @@ -236,19 +238,35 @@ private: /** * @brief 宏定义,用于输出调试日志 */ -#define LOG_DEBUG(message, ...) XNLoggerHelper::log(XNLogger::Debug, message, ##__VA_ARGS__) +template +inline void LOG_DEBUG(const std::string &message, Args &&...args) +{ + XNLoggerHelper::log(XNLogger::Debug, message, args...); +} /** - * @brief 宏定义,用于输出信息日志 + * @brief 模板函数,用于输出信息日志 */ -#define LOG_INFO(message, ...) XNLoggerHelper::log(XNLogger::Info, message, ##__VA_ARGS__) +template +inline void LOG_INFO(const std::string &message, Args &&...args) +{ + XNLoggerHelper::log(XNLogger::Info, message, args...); +} /** - * @brief 宏定义,用于输出警告日志 + * @brief 模板函数,用于输出警告日志 */ -#define LOG_WARNING(message, ...) XNLoggerHelper::log(XNLogger::Warning, message, ##__VA_ARGS__) +template +inline void LOG_WARNING(const std::string &message, Args &&...args) +{ + XNLoggerHelper::log(XNLogger::Warning, message, args...); +} /** - * @brief 宏定义,用于输出错误日志 + * @brief 模板函数,用于输出错误日志 */ -#define LOG_ERROR(message, ...) XNLoggerHelper::log(XNLogger::Error, message, ##__VA_ARGS__) +template +inline void LOG_ERROR(const std::string &message, Args &&...args) +{ + XNLoggerHelper::log(XNLogger::Error, message, args...); +} diff --git a/XNMonitorServer/DataMonitor.h b/XNMonitorServer/DataMonitor.h index 68d82bb..1a5ef14 100644 --- a/XNMonitorServer/DataMonitor.h +++ b/XNMonitorServer/DataMonitor.h @@ -4,8 +4,6 @@ #include "TypeDefine.h" #include "TopicManager.h" -#define THISUNUSED(x) (void)(x) - class XNFramework; using XNFrameworkPtr = std::shared_ptr; @@ -40,11 +38,10 @@ public: _isInitialized = false; }; - virtual void Initialize(XNFrameworkPtr framework, uint32_t modelId, uint32_t DDS_type) override + virtual void Initialize(XNFrameworkPtr framework [[maybe_unused]], + uint32_t modelId [[maybe_unused]], + uint32_t DDS_type [[maybe_unused]]) override { - THISUNUSED(framework); - THISUNUSED(modelId); - THISUNUSED(DDS_type); XNDDSErrorCode ret = TopicManager::Instance()->registerSubscriber( T::topic_name, diff --git a/XNSignature/CMakeLists.txt b/XNSignature/CMakeLists.txt new file mode 100644 index 0000000..9a58482 --- /dev/null +++ b/XNSignature/CMakeLists.txt @@ -0,0 +1,56 @@ +cmake_minimum_required(VERSION 3.16) + +project(XNSignature LANGUAGES CXX) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +# 获取环境变量 +if(DEFINED ENV{XNCore}) + set(XNCore_PATH $ENV{XNCore}) +else() + message(FATAL_ERROR "Environment variable XNCore is not set.") +endif() + +# 查找依赖包 +find_package(OpenSSL REQUIRED) + +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${XNCore_PATH}" CACHE PATH "Install path prefix" FORCE) +endif() + +include(GNUInstallDirs) + +# 生成密钥对的可执行程序 +add_executable(XNSignatureKeygen keygen.cpp) +target_link_libraries(XNSignatureKeygen PRIVATE OpenSSL::SSL OpenSSL::Crypto) + +# 签名的可执行程序 +add_executable(XNSignatureSign sign.cpp) +target_link_libraries(XNSignatureSign PRIVATE OpenSSL::SSL OpenSSL::Crypto) + +# 验证签名的动态库 +add_library(XNSignatureVerify SHARED + XNSignature_global.h + XNSignatureVerify.h + verify.cpp +) + +target_include_directories(XNSignatureVerify PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) +target_link_libraries(XNSignatureVerify PRIVATE OpenSSL::SSL OpenSSL::Crypto) +target_compile_definitions(XNSignatureVerify PRIVATE XNSIGNATURE_LIBRARY XNSIGNATURE_EXPORTS) + +# 验证库测试程序 +add_executable(test_verify test_verify.cpp) +target_link_libraries(test_verify PRIVATE XNSignatureVerify) +target_compile_definitions(test_verify PRIVATE XNSIGNATURE_EXPORTS) + +# 完整性检测测试程序 +add_executable(test_integrity test_integrity.cpp) +target_link_libraries(test_integrity PRIVATE XNSignatureVerify) +target_compile_definitions(test_integrity PRIVATE XNSIGNATURE_EXPORTS) + +# 安装配置 - 只安装动态库 +install(TARGETS XNSignatureVerify + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} +) diff --git a/XNSignature/README.md b/XNSignature/README.md new file mode 100644 index 0000000..f3e3924 --- /dev/null +++ b/XNSignature/README.md @@ -0,0 +1,164 @@ +# XNSignature 数字签名工具集 + +这是一个基于 OpenSSL 的数字签名工具集,包含三个主要组件: + +## 项目结构 + +- **XNSignatureKeygen**: 密钥生成工具(可执行程序) +- **XNSignatureSign**: 文件签名工具(可执行程序) +- **XNSignatureVerify**: 签名验证库(动态库) + +## 编译和安装 + +### 依赖要求 + +- CMake 3.16+ +- OpenSSL 开发库 +- C++17 编译器 + +### 编译步骤 + +```bash +mkdir build +cd build +cmake .. +make +``` + +### 安装 + +```bash +make install +``` + +## 使用方法 + +### 1. 生成密钥对 + +运行密钥生成工具,会在当前目录生成密钥文件: + +```bash +./XNSignatureKeygen +``` + +这将生成: + +- `private_key.pem` - 私钥文件 +- `public_key.pem` - 公钥文件 + +### 2. 为文件创建数字签名 + +有两种使用方式: + +#### 方式一:签名所有文件 + +```bash +./XNSignatureSign +``` + +这将自动签名当前目录下的所有文件(除了密钥文件和已有的签名文件),每个文件会生成对应的 `.sig` 签名文件。 + +#### 方式二:签名指定文件 + +```bash +./XNSignatureSign <文件路径> +``` + +示例: + +```bash +./XNSignatureSign document.txt +./XNSignatureSign important_file.pdf +``` + +签名工具会使用当前目录下的 `private_key.pem` 私钥文件。 + +### 3. 验证数字签名 + +使用验证库验证文件签名: + +#### C++ 程序中使用 + +```cpp +#include "XNSignatureVerify.h" + +// 验证签名 +int result = verifySignature("document.txt", "public_key.pem", "document.sig"); +if (result == 0) { + std::cout << "签名验证成功!" << std::endl; +} else if (result == -1) { + std::cout << "签名验证失败!" << std::endl; +} else { + std::cout << "验证过程中发生错误!" << std::endl; +} +``` + +#### 测试验证库 + +```bash +./test_verify +``` + +## API 函数说明 + +### 验证库函数 + +#### `verifySignature` + +```cpp +int verifySignature(const char* filePath, const char* publicKeyPath, const char* signaturePath); +``` + +- **功能**: 验证文件数字签名 +- **返回值**: 0=成功, -1=验证失败, -2=其他错误 + +## 技术特点 + +- 使用 RSA-2048 算法进行数字签名 +- 采用 SHA256 哈希算法 +- 支持 PEM 格式的密钥文件 +- 提供 C 语言接口,便于集成 +- 完整的错误处理和资源管理 + +## 安全说明 + +- 私钥文件应妥善保管,不要泄露给他人 +- 公钥文件可以公开分发 +- 签名文件用于验证文件完整性,防止篡改 +- 建议定期更换密钥对 + +## 示例工作流程 + +1. 生成密钥对: + + ```bash + ./xn_keygen + ``` + +2. 签名重要文件: + + 方式一:签名所有文件 + + ```bash + ./XNSignatureSign + ``` + + 方式二:签名指定文件 + + ```bash + ./XNSignatureSign important_document.pdf + ``` + +3. 分发文件时包含: + + - `important_document.pdf` (原始文件) + - `important_document.sig` (签名文件) + - `public_key.pem` (公钥文件) + +4. 接收方验证文件完整性: + ```cpp + int result = verifySignature("important_document.pdf", "public_key.pem", "important_document.sig"); + if (result == 0) { + // 文件未被篡改,可以安全使用 + } + ``` diff --git a/XNSignature/XNSignatureVerify.h b/XNSignature/XNSignatureVerify.h new file mode 100644 index 0000000..ab7bb4b --- /dev/null +++ b/XNSignature/XNSignatureVerify.h @@ -0,0 +1,25 @@ +#ifndef XNSIGNATUREVERIFY_H +#define XNSIGNATUREVERIFY_H + +#include "XNSignature_global.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + + /** + * @brief 验证文件数字签名 + * @param filePath 原始文件路径 + * @param publicKeyPath 公钥文件路径 + * @param signaturePath 签名文件路径 + * @return 0表示验证成功,-1表示验证失败,-2表示其他错误 + */ + XNSIGNATURE_API int verifySignature(const char *filePath, const char *publicKeyPath, + const char *signaturePath); + +#ifdef __cplusplus +} +#endif + +#endif // XNSIGNATUREVERIFY_H \ No newline at end of file diff --git a/XNSignature/XNSignature_global.h b/XNSignature/XNSignature_global.h new file mode 100644 index 0000000..258f722 --- /dev/null +++ b/XNSignature/XNSignature_global.h @@ -0,0 +1,10 @@ +#ifndef XNSIGNATURE_GLOBAL_H +#define XNSIGNATURE_GLOBAL_H + +#ifdef XNSIGNATURE_EXPORTS +# define XNSIGNATURE_API __attribute__((visibility("default"))) +#else +# define XNSIGNATURE_API __attribute__((visibility("hidden"))) +#endif + +#endif // XNSIGNATURE_GLOBAL_H \ No newline at end of file diff --git a/XNSignature/keygen.cpp b/XNSignature/keygen.cpp new file mode 100644 index 0000000..227c35d --- /dev/null +++ b/XNSignature/keygen.cpp @@ -0,0 +1,133 @@ +#include +#include +#include +#include +#include +#include + +/** + * @brief 生成RSA密钥对 + * @param privateKeyPath 私钥保存路径 + * @param publicKeyPath 公钥保存路径 + * @param keySize 密钥长度(默认2048位) + * @return 0表示成功,-1表示失败 + */ +int generateRSAKeyPair(const char *privateKeyPath, const char *publicKeyPath, int keySize = 2048) +{ + if (!privateKeyPath || !publicKeyPath) { + std::cerr << "错误:密钥路径不能为空" << std::endl; + return -1; + } + + // 生成RSA密钥对 + EVP_PKEY *pkey = EVP_PKEY_new(); + if (!pkey) { + std::cerr << "错误:无法创建密钥对象" << std::endl; + return -1; + } + + // 创建RSA密钥生成上下文 + EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, nullptr); + if (!ctx) { + std::cerr << "错误:无法创建密钥生成上下文" << std::endl; + EVP_PKEY_free(pkey); + return -1; + } + + // 初始化密钥生成 + if (EVP_PKEY_keygen_init(ctx) <= 0) { + std::cerr << "错误:无法初始化密钥生成" << std::endl; + EVP_PKEY_CTX_free(ctx); + EVP_PKEY_free(pkey); + return -1; + } + + // 设置密钥长度 + if (EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, keySize) <= 0) { + std::cerr << "错误:无法设置密钥长度" << std::endl; + EVP_PKEY_CTX_free(ctx); + EVP_PKEY_free(pkey); + return -1; + } + + // 生成密钥对 + if (EVP_PKEY_keygen(ctx, &pkey) <= 0) { + std::cerr << "错误:密钥生成失败" << std::endl; + EVP_PKEY_CTX_free(ctx); + EVP_PKEY_free(pkey); + return -1; + } + + // 保存私钥到文件 + FILE *privateKeyFile = fopen(privateKeyPath, "w"); + if (!privateKeyFile) { + std::cerr << "错误:无法创建私钥文件" << std::endl; + EVP_PKEY_CTX_free(ctx); + EVP_PKEY_free(pkey); + return -1; + } + + if (PEM_write_PrivateKey(privateKeyFile, pkey, nullptr, nullptr, 0, nullptr, nullptr) != 1) { + std::cerr << "错误:无法写入私钥" << std::endl; + fclose(privateKeyFile); + EVP_PKEY_CTX_free(ctx); + EVP_PKEY_free(pkey); + return -1; + } + fclose(privateKeyFile); + + // 保存公钥到文件 + FILE *publicKeyFile = fopen(publicKeyPath, "w"); + if (!publicKeyFile) { + std::cerr << "错误:无法创建公钥文件" << std::endl; + EVP_PKEY_CTX_free(ctx); + EVP_PKEY_free(pkey); + return -1; + } + + if (PEM_write_PUBKEY(publicKeyFile, pkey) != 1) { + std::cerr << "错误:无法写入公钥" << std::endl; + fclose(publicKeyFile); + EVP_PKEY_CTX_free(ctx); + EVP_PKEY_free(pkey); + return -1; + } + fclose(publicKeyFile); + + // 清理资源 + EVP_PKEY_CTX_free(ctx); + EVP_PKEY_free(pkey); + + std::cout << "RSA密钥对生成成功!" << std::endl; + std::cout << "私钥保存到: " << privateKeyPath << std::endl; + std::cout << "公钥保存到: " << publicKeyPath << std::endl; + + return 0; +} + +/** + * @brief 主函数 + */ +int main(int argc, char *argv[]) +{ + // 固定文件名,生成在程序所在目录 + const char *privateKeyPath = "private_key.pem"; + const char *publicKeyPath = "public_key.pem"; + int keySize = 2048; // 默认密钥长度 + + std::cout << "=== XNSignature 密钥生成工具 ===" << std::endl; + std::cout << "私钥文件: " << privateKeyPath << std::endl; + std::cout << "公钥文件: " << publicKeyPath << std::endl; + std::cout << "密钥长度: " << keySize << " 位" << std::endl; + std::cout << "正在生成密钥对..." << std::endl; + + int result = generateRSAKeyPair(privateKeyPath, publicKeyPath, keySize); + + if (result == 0) { + std::cout << "密钥生成完成!" << std::endl; + return 0; + } else { + std::cerr << "密钥生成失败!" << std::endl; + return -1; + } +} \ No newline at end of file diff --git a/XNSignature/sign.cpp b/XNSignature/sign.cpp new file mode 100644 index 0000000..800e232 --- /dev/null +++ b/XNSignature/sign.cpp @@ -0,0 +1,253 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * @brief 计算文件的SHA256哈希值 + * @param filePath 文件路径 + * @param hash 输出哈希值(32字节) + * @return 0表示成功,-1表示失败 + */ +int calculateFileHash(const char *filePath, unsigned char *hash) +{ + if (!filePath || !hash) { + return -1; + } + + std::ifstream file(filePath, std::ios::binary); + if (!file.is_open()) { + std::cerr << "错误:无法打开文件 " << filePath << std::endl; + return -1; + } + + SHA256_CTX sha256; + SHA256_Init(&sha256); + + char buffer[4096]; + while (file) { + file.read(buffer, sizeof(buffer)); + std::streamsize bytesRead = file.gcount(); + if (bytesRead > 0) { + SHA256_Update(&sha256, buffer, bytesRead); + } + } + + SHA256_Final(hash, &sha256); + file.close(); + + return 0; +} + +/** + * @brief 为指定文件创建数字签名 + * @param filePath 要签名的文件路径 + * @param privateKeyPath 私钥文件路径 + * @param signaturePath 签名文件保存路径 + * @return 0表示成功,-1表示失败 + */ +int signFile(const char *filePath, const char *privateKeyPath, const char *signaturePath) +{ + if (!filePath || !privateKeyPath || !signaturePath) { + std::cerr << "错误:参数不能为空" << std::endl; + return -1; + } + + // 加载私钥 + FILE *privateKeyFile = fopen(privateKeyPath, "r"); + if (!privateKeyFile) { + std::cerr << "错误:无法打开私钥文件" << std::endl; + return -1; + } + + EVP_PKEY *privateKey = PEM_read_PrivateKey(privateKeyFile, nullptr, nullptr, nullptr); + fclose(privateKeyFile); + + if (!privateKey) { + std::cerr << "错误:无法读取私钥" << std::endl; + return -1; + } + + // 计算文件哈希 + unsigned char hash[SHA256_DIGEST_LENGTH]; + if (calculateFileHash(filePath, hash) != 0) { + EVP_PKEY_free(privateKey); + return -1; + } + + // 创建签名上下文 + EVP_MD_CTX *ctx = EVP_MD_CTX_new(); + if (!ctx) { + std::cerr << "错误:无法创建签名上下文" << std::endl; + EVP_PKEY_free(privateKey); + return -1; + } + + // 初始化签名 + if (EVP_DigestSignInit(ctx, nullptr, EVP_sha256(), nullptr, privateKey) <= 0) { + std::cerr << "错误:无法初始化签名" << std::endl; + EVP_MD_CTX_free(ctx); + EVP_PKEY_free(privateKey); + return -1; + } + + // 计算签名长度 + size_t signatureLen; + if (EVP_DigestSign(ctx, nullptr, &signatureLen, hash, SHA256_DIGEST_LENGTH) <= 0) { + std::cerr << "错误:无法计算签名长度" << std::endl; + EVP_MD_CTX_free(ctx); + EVP_PKEY_free(privateKey); + return -1; + } + + // 分配签名缓冲区 + std::vector signature(signatureLen); + + // 执行签名 + if (EVP_DigestSign(ctx, signature.data(), &signatureLen, hash, SHA256_DIGEST_LENGTH) <= 0) { + std::cerr << "错误:签名失败" << std::endl; + EVP_MD_CTX_free(ctx); + EVP_PKEY_free(privateKey); + return -1; + } + + // 保存签名到文件 + std::ofstream signatureFile(signaturePath, std::ios::binary); + if (!signatureFile.is_open()) { + std::cerr << "错误:无法创建签名文件" << std::endl; + EVP_MD_CTX_free(ctx); + EVP_PKEY_free(privateKey); + return -1; + } + + signatureFile.write(reinterpret_cast(signature.data()), signatureLen); + signatureFile.close(); + + // 清理资源 + EVP_MD_CTX_free(ctx); + EVP_PKEY_free(privateKey); + + std::cout << "文件签名成功!" << std::endl; + std::cout << "签名文件保存到: " << signaturePath << std::endl; + + return 0; +} + +#include +#include +#include + +/** + * @brief 获取目录下所有文件 + * @param directory 目录路径 + * @return 文件路径列表 + */ +std::vector getFilesInDirectory(const std::string &directory) +{ + std::vector files; + + try { + for (const auto &entry : std::filesystem::directory_iterator(directory)) { + if (entry.is_regular_file()) { + // 跳过密钥文件和签名文件 + std::string filename = entry.path().filename().string(); + if (filename != "private_key.pem" && filename != "public_key.pem" + && filename.find(".sig") == std::string::npos) { + files.push_back(entry.path().string()); + } + } + } + } catch (const std::filesystem::filesystem_error &e) { + std::cerr << "错误:无法读取目录 " << directory << ": " << e.what() << std::endl; + } + + return files; +} + +/** + * @brief 显示使用说明 + */ +void showUsage(const char *programName) +{ + std::cout << "用法: " << programName << " [文件路径]" << std::endl; + std::cout << "参数说明:" << std::endl; + std::cout << " 文件路径: 要签名的文件路径(可选)" << std::endl; + std::cout << " 如果不提供参数,将签名当前目录下的所有文件" << std::endl; + std::cout << "示例:" << std::endl; + std::cout << " " << programName << " # 签名所有文件" << std::endl; + std::cout << " " << programName << " document.txt # 签名指定文件" << std::endl; +} + +/** + * @brief 主函数 + */ +int main(int argc, char *argv[]) +{ + const char *privateKeyPath = "private_key.pem"; + std::vector filesToSign; + + std::cout << "=== XNSignature 文件签名工具 ===" << std::endl; + + if (argc == 1) { + // 没有参数,签名目录下所有文件 + std::cout << "未指定文件,将签名当前目录下的所有文件..." << std::endl; + filesToSign = getFilesInDirectory("."); + + if (filesToSign.empty()) { + std::cout << "当前目录下没有找到可签名的文件" << std::endl; + return 0; + } + + std::cout << "找到 " << filesToSign.size() << " 个文件:" << std::endl; + for (const auto &file : filesToSign) { + std::cout << " - " << file << std::endl; + } + } else if (argc == 2) { + // 指定了单个文件 + filesToSign.push_back(argv[1]); + std::cout << "将签名指定文件: " << argv[1] << std::endl; + } else { + std::cerr << "错误:参数数量不正确" << std::endl; + showUsage(argv[0]); + return -1; + } + + std::cout << "私钥文件: " << privateKeyPath << std::endl; + std::cout << "正在签名文件..." << std::endl; + + int successCount = 0; + int totalCount = filesToSign.size(); + + for (const auto &filePath : filesToSign) { + // 生成签名文件路径 + std::string signaturePath = filePath + ".sig"; + + std::cout << "\n正在签名: " << filePath << std::endl; + std::cout << "签名文件: " << signaturePath << std::endl; + + int result = signFile(filePath.c_str(), privateKeyPath, signaturePath.c_str()); + + if (result == 0) { + std::cout << "✓ 签名成功" << std::endl; + successCount++; + } else { + std::cout << "✗ 签名失败" << std::endl; + } + } + + std::cout << "\n=== 签名完成 ===" << std::endl; + std::cout << "成功签名: " << successCount << "/" << totalCount << " 个文件" << std::endl; + + if (successCount == totalCount) { + std::cout << "所有文件签名完成!" << std::endl; + return 0; + } else { + std::cerr << "部分文件签名失败!" << std::endl; + return -1; + } +} \ No newline at end of file diff --git a/XNSignature/test_integrity.cpp b/XNSignature/test_integrity.cpp new file mode 100644 index 0000000..d91c0f5 --- /dev/null +++ b/XNSignature/test_integrity.cpp @@ -0,0 +1,179 @@ +#include +#include +#include +#include +#include "XNSignatureVerify.h" + +/** + * @brief 测试文件完整性检测 + * 验证签名是否能检测到文件的任何微小变化 + */ +int main() +{ + std::cout << "=== 文件完整性检测测试 ===" << std::endl; + + // 创建测试文件 + std::string testFile = "test_integrity.txt"; + std::ofstream file(testFile); + if (!file.is_open()) { + std::cerr << "错误:无法创建测试文件" << std::endl; + return -1; + } + + file << "这是一个测试文件,用于验证数字签名的完整性检测功能。" << std::endl; + file << "任何微小的修改都应该被检测到。" << std::endl; + file.close(); + + std::cout << "1. 创建测试文件: " << testFile << std::endl; + + // 生成密钥对 + std::cout << "2. 生成密钥对..." << std::endl; + system("./XNSignatureKeygen"); + + // 对文件进行签名 + std::cout << "3. 对文件进行签名..." << std::endl; + system(("./XNSignatureSign " + testFile).c_str()); + + // 验证原始签名 + std::cout << "4. 验证原始签名..." << std::endl; + int result1 = verifySignature(testFile.c_str(), "public_key.pem", (testFile + ".sig").c_str()); + + if (result1 == 0) { + std::cout << "✓ 原始文件签名验证成功" << std::endl; + } else { + std::cout << "✗ 原始文件签名验证失败" << std::endl; + return -1; + } + + // 测试1:修改文件内容(添加一个字符) + std::cout << "\n5. 测试1:修改文件内容(添加字符)..." << std::endl; + std::ofstream modFile1(testFile, std::ios::app); + modFile1 << "X"; // 添加一个字符 + modFile1.close(); + + int result2 = verifySignature(testFile.c_str(), "public_key.pem", (testFile + ".sig").c_str()); + + if (result2 != 0) { + std::cout << "✓ 检测到文件内容修改" << std::endl; + } else { + std::cout << "✗ 未能检测到文件内容修改" << std::endl; + return -1; + } + + // 恢复文件内容 + std::ofstream restoreFile1(testFile); + restoreFile1 << "这是一个测试文件,用于验证数字签名的完整性检测功能。" << std::endl; + restoreFile1 << "任何微小的修改都应该被检测到。" << std::endl; + restoreFile1.close(); + + // 重新签名 + system(("./XNSignatureSign " + testFile).c_str()); + + // 测试2:修改文件内容(删除一个字符) + std::cout << "\n6. 测试2:修改文件内容(删除字符)..." << std::endl; + std::string content; + std::ifstream readFile(testFile); + std::getline(readFile, content); + readFile.close(); + + if (content.length() > 0) { + content = content.substr(0, content.length() - 1); // 删除最后一个字符 + std::ofstream modFile2(testFile); + modFile2 << content << std::endl; + modFile2.close(); + + int result3 = + verifySignature(testFile.c_str(), "public_key.pem", (testFile + ".sig").c_str()); + + if (result3 != 0) { + std::cout << "✓ 检测到文件内容修改" << std::endl; + } else { + std::cout << "✗ 未能检测到文件内容修改" << std::endl; + return -1; + } + } + + // 测试3:修改文件内容(替换一个字符) + std::cout << "\n7. 测试3:修改文件内容(替换字符)..." << std::endl; + std::ifstream readFile2(testFile); + std::getline(readFile2, content); + readFile2.close(); + + if (content.length() > 5) { + content[5] = 'X'; // 替换第6个字符 + std::ofstream modFile3(testFile); + modFile3 << content << std::endl; + modFile3.close(); + + int result4 = + verifySignature(testFile.c_str(), "public_key.pem", (testFile + ".sig").c_str()); + + if (result4 != 0) { + std::cout << "✓ 检测到文件内容修改" << std::endl; + } else { + std::cout << "✗ 未能检测到文件内容修改" << std::endl; + return -1; + } + } + + // 测试4:修改文件内容(添加空格) + std::cout << "\n8. 测试4:修改文件内容(添加空格)..." << std::endl; + std::ifstream readFile3(testFile); + std::getline(readFile3, content); + readFile3.close(); + + content.insert(10, " "); // 在第10个位置插入空格 + std::ofstream modFile4(testFile); + modFile4 << content << std::endl; + modFile4.close(); + + int result5 = verifySignature(testFile.c_str(), "public_key.pem", (testFile + ".sig").c_str()); + + if (result5 != 0) { + std::cout << "✓ 检测到文件内容修改" << std::endl; + } else { + std::cout << "✗ 未能检测到文件内容修改" << std::endl; + return -1; + } + + // 测试5:修改文件内容(改变换行符) + std::cout << "\n9. 测试5:修改文件内容(改变换行符)..." << std::endl; + std::ofstream modFile5(testFile); + modFile5 << "这是一个测试文件,用于验证数字签名的完整性检测功能。\r\n"; // 使用Windows换行符 + modFile5 << "任何微小的修改都应该被检测到。\r\n"; + modFile5.close(); + + int result6 = verifySignature(testFile.c_str(), "public_key.pem", (testFile + ".sig").c_str()); + + if (result6 != 0) { + std::cout << "✓ 检测到文件内容修改" << std::endl; + } else { + std::cout << "✗ 未能检测到文件内容修改" << std::endl; + return -1; + } + + // 测试6:修改文件内容(添加不可见字符) + std::cout << "\n10. 测试6:修改文件内容(添加不可见字符)..." << std::endl; + std::ofstream modFile6(testFile); + modFile6 << "这是一个测试文件,用于验证数字签名的完整性检测功能。" << std::endl; + modFile6 << "任何微小的修改都应该被检测到。" << (char)0x00 << std::endl; // 添加null字符 + modFile6.close(); + + int result7 = verifySignature(testFile.c_str(), "public_key.pem", (testFile + ".sig").c_str()); + + if (result7 != 0) { + std::cout << "✓ 检测到文件内容修改" << std::endl; + } else { + std::cout << "✗ 未能检测到文件内容修改" << std::endl; + return -1; + } + + std::cout << "\n=== 测试完成 ===" << std::endl; + std::cout << "✓ 所有完整性检测测试通过!" << std::endl; + std::cout << "✓ 数字签名能够检测到文件的任何微小变化" << std::endl; + + // 清理测试文件 + system(("rm -f " + testFile + " " + testFile + ".sig").c_str()); + + return 0; +} \ No newline at end of file diff --git a/XNSignature/test_verify.cpp b/XNSignature/test_verify.cpp new file mode 100644 index 0000000..c967b24 --- /dev/null +++ b/XNSignature/test_verify.cpp @@ -0,0 +1,51 @@ +#include "XNSignatureVerify.h" +#include +#include + +/** + * @brief 创建测试文件 + * @param filename 文件名 + * @param content 文件内容 + */ +void createTestFile(const char *filename, const char *content) +{ + std::ofstream file(filename); + if (file.is_open()) { + file << content; + file.close(); + std::cout << "测试文件创建成功: " << filename << std::endl; + } else { + std::cerr << "无法创建测试文件: " << filename << std::endl; + } +} + +/** + * @brief 主测试函数 + */ +int main() +{ + std::cout << "=== XNSignature 验证库测试程序 ===" << std::endl; + + // 测试文件路径 + const char *testFile = "test_document.txt"; + const char *publicKeyFile = "public_key.pem"; + const char *signatureFile = "test_document.txt.sig"; + + // 创建测试文件 + //createTestFile(testFile, "这是一个测试文档,用于验证数字签名功能。\n包含一些重要信息。"); + + std::cout << "\n1. 验证数字签名..." << std::endl; + int verifyResult = verifySignature(testFile, publicKeyFile, signatureFile); + if (verifyResult == 0) { + std::cout << "签名验证成功!" << std::endl; + } else if (verifyResult == -1) { + std::cout << "签名验证失败!" << std::endl; + } else { + std::cout << "验证过程中发生错误!" << std::endl; + } + + std::cout << "\n2. 验证完成" << std::endl; + + std::cout << "\n=== 测试完成 ===" << std::endl; + return 0; +} \ No newline at end of file diff --git a/XNSignature/verify.cpp b/XNSignature/verify.cpp new file mode 100644 index 0000000..3996c18 --- /dev/null +++ b/XNSignature/verify.cpp @@ -0,0 +1,303 @@ +#include "XNSignature_global.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern "C" +{ + + /** + * @brief 计算文件的SHA256哈希值 + * @param filePath 文件路径 + * @param hash 输出哈希值(32字节) + * @return 0表示成功,-1表示失败 + */ + int calculateFileHash(const char *filePath, unsigned char *hash) + { + if (!filePath || !hash) { + return -1; + } + + std::ifstream file(filePath, std::ios::binary); + if (!file.is_open()) { + std::cerr << "错误:无法打开文件 " << filePath << std::endl; + return -1; + } + + SHA256_CTX sha256; + SHA256_Init(&sha256); + + char buffer[4096]; + while (file) { + file.read(buffer, sizeof(buffer)); + std::streamsize bytesRead = file.gcount(); + if (bytesRead > 0) { + SHA256_Update(&sha256, buffer, bytesRead); + } + } + + SHA256_Final(hash, &sha256); + file.close(); + + return 0; + } + + /** + * @brief 验证文件数字签名 + * @param filePath 原始文件路径 + * @param publicKeyPath 公钥文件路径 + * @param signaturePath 签名文件路径 + * @return 0表示验证成功,-1表示验证失败,-2表示其他错误 + */ + XNSIGNATURE_API int verifySignature(const char *filePath, const char *publicKeyPath, + const char *signaturePath) + { + if (!filePath || !publicKeyPath || !signaturePath) { + std::cerr << "错误:参数不能为空" << std::endl; + return -2; + } + + // 加载公钥 + FILE *publicKeyFile = fopen(publicKeyPath, "r"); + if (!publicKeyFile) { + std::cerr << "错误:无法打开公钥文件" << std::endl; + return -2; + } + + EVP_PKEY *publicKey = PEM_read_PUBKEY(publicKeyFile, nullptr, nullptr, nullptr); + fclose(publicKeyFile); + + if (!publicKey) { + std::cerr << "错误:无法读取公钥" << std::endl; + return -2; + } + + // 计算文件哈希 + unsigned char hash[SHA256_DIGEST_LENGTH]; + if (calculateFileHash(filePath, hash) != 0) { + EVP_PKEY_free(publicKey); + return -2; + } + + // 读取签名文件 + std::ifstream signatureFile(signaturePath, std::ios::binary); + if (!signatureFile.is_open()) { + std::cerr << "错误:无法打开签名文件" << std::endl; + EVP_PKEY_free(publicKey); + return -2; + } + + signatureFile.seekg(0, std::ios::end); + size_t signatureSize = signatureFile.tellg(); + signatureFile.seekg(0, std::ios::beg); + + std::vector signature(signatureSize); + signatureFile.read(reinterpret_cast(signature.data()), signatureSize); + signatureFile.close(); + + // 创建验证上下文 + EVP_MD_CTX *ctx = EVP_MD_CTX_new(); + if (!ctx) { + std::cerr << "错误:无法创建验证上下文" << std::endl; + EVP_PKEY_free(publicKey); + return -2; + } + + // 初始化验证 + if (EVP_DigestVerifyInit(ctx, nullptr, EVP_sha256(), nullptr, publicKey) <= 0) { + std::cerr << "错误:无法初始化验证" << std::endl; + EVP_MD_CTX_free(ctx); + EVP_PKEY_free(publicKey); + return -2; + } + + // 执行验证 + int result = + EVP_DigestVerify(ctx, signature.data(), signature.size(), hash, SHA256_DIGEST_LENGTH); + + // 清理资源 + EVP_MD_CTX_free(ctx); + EVP_PKEY_free(publicKey); + + if (result == 1) { + std::cout << "签名验证成功!文件完整性确认。" << std::endl; + return 0; + } else if (result == 0) { + std::cout << "签名验证失败!文件可能已被篡改。" << std::endl; + return -1; + } else { + std::cerr << "错误:验证过程中发生错误" << std::endl; + return -2; + } + } + + /** + * @brief 显示文件哈希值 + * @param filePath 文件路径 + * @return 0表示成功,-1表示失败 + */ + int showFileHash(const char *filePath) + { + if (!filePath) { + std::cerr << "错误:文件路径不能为空" << std::endl; + return -1; + } + + unsigned char hash[SHA256_DIGEST_LENGTH]; + if (calculateFileHash(filePath, hash) != 0) { + return -1; + } + + std::cout << "文件 " << filePath << " 的SHA256哈希值:" << std::endl; + for (int i = 0; i < SHA256_DIGEST_LENGTH; i++) { + printf("%02x", hash[i]); + } + std::cout << std::endl; + + return 0; + } + + /** + * @brief 获取文件哈希值的十六进制字符串 + * @param filePath 文件路径 + * @param hashString 输出哈希字符串缓冲区(至少65字节) + * @return 0表示成功,-1表示失败 + */ + int getFileHashString(const char *filePath, char *hashString) + { + if (!filePath || !hashString) { + return -1; + } + + unsigned char hash[SHA256_DIGEST_LENGTH]; + if (calculateFileHash(filePath, hash) != 0) { + return -1; + } + + for (int i = 0; i < SHA256_DIGEST_LENGTH; i++) { + sprintf(hashString + i * 2, "%02x", hash[i]); + } + hashString[64] = '\0'; // 确保字符串结束 + + return 0; + } + + /** + * @brief 验证签名并返回详细结果 + * @param filePath 原始文件路径 + * @param publicKeyPath 公钥文件路径 + * @param signaturePath 签名文件路径 + * @param resultMessage 结果消息缓冲区 + * @param messageSize 缓冲区大小 + * @return 0表示验证成功,-1表示验证失败,-2表示其他错误 + */ + int verifySignatureWithMessage(const char *filePath, const char *publicKeyPath, + const char *signaturePath, char *resultMessage, int messageSize) + { + if (!filePath || !publicKeyPath || !signaturePath || !resultMessage) { + if (resultMessage && messageSize > 0) { + snprintf(resultMessage, messageSize, "错误:参数不能为空"); + } + return -2; + } + + // 加载公钥 + FILE *publicKeyFile = fopen(publicKeyPath, "r"); + if (!publicKeyFile) { + if (messageSize > 0) { + snprintf(resultMessage, messageSize, "错误:无法打开公钥文件"); + } + return -2; + } + + EVP_PKEY *publicKey = PEM_read_PUBKEY(publicKeyFile, nullptr, nullptr, nullptr); + fclose(publicKeyFile); + + if (!publicKey) { + if (messageSize > 0) { + snprintf(resultMessage, messageSize, "错误:无法读取公钥"); + } + return -2; + } + + // 计算文件哈希 + unsigned char hash[SHA256_DIGEST_LENGTH]; + if (calculateFileHash(filePath, hash) != 0) { + EVP_PKEY_free(publicKey); + if (messageSize > 0) { + snprintf(resultMessage, messageSize, "错误:无法计算文件哈希"); + } + return -2; + } + + // 读取签名文件 + std::ifstream signatureFile(signaturePath, std::ios::binary); + if (!signatureFile.is_open()) { + EVP_PKEY_free(publicKey); + if (messageSize > 0) { + snprintf(resultMessage, messageSize, "错误:无法打开签名文件"); + } + return -2; + } + + signatureFile.seekg(0, std::ios::end); + size_t signatureSize = signatureFile.tellg(); + signatureFile.seekg(0, std::ios::beg); + + std::vector signature(signatureSize); + signatureFile.read(reinterpret_cast(signature.data()), signatureSize); + signatureFile.close(); + + // 创建验证上下文 + EVP_MD_CTX *ctx = EVP_MD_CTX_new(); + if (!ctx) { + EVP_PKEY_free(publicKey); + if (messageSize > 0) { + snprintf(resultMessage, messageSize, "错误:无法创建验证上下文"); + } + return -2; + } + + // 初始化验证 + if (EVP_DigestVerifyInit(ctx, nullptr, EVP_sha256(), nullptr, publicKey) <= 0) { + EVP_MD_CTX_free(ctx); + EVP_PKEY_free(publicKey); + if (messageSize > 0) { + snprintf(resultMessage, messageSize, "错误:无法初始化验证"); + } + return -2; + } + + // 执行验证 + int result = + EVP_DigestVerify(ctx, signature.data(), signature.size(), hash, SHA256_DIGEST_LENGTH); + + // 清理资源 + EVP_MD_CTX_free(ctx); + EVP_PKEY_free(publicKey); + + if (result == 1) { + if (messageSize > 0) { + snprintf(resultMessage, messageSize, "签名验证成功!文件完整性确认。"); + } + return 0; + } else if (result == 0) { + if (messageSize > 0) { + snprintf(resultMessage, messageSize, "签名验证失败!文件可能已被篡改。"); + } + return -1; + } else { + if (messageSize > 0) { + snprintf(resultMessage, messageSize, "错误:验证过程中发生错误"); + } + return -2; + } + } + +} // extern "C" \ No newline at end of file diff --git a/private_key.pem b/private_key.pem new file mode 100644 index 0000000..c27f6e2 --- /dev/null +++ b/private_key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEwAIBADANBgkqhkiG9w0BAQEFAASCBKowggSmAgEAAoIBAQDF2ZjCOq3Yl3v4 +9bg3+qIpAAt4R3iPpGoiJcybzNhhhBJ7dJKsS45liFQqoVxhf0rASjTlJ6ImbqiI +cnD8APAfpNyfdeg0gKt94x2SkJXU6kAer1aNq55i3DLcRmAGHuIXHSM5jxrh+lBQ +v4p4gP2p4BhT4Fds8Mg6QZUi7axoN93B8xbayFHqRo0C2jroyF9kxKpwZB8302SG +ax1dqEJa66WimIzST3ksyvXlMzd+oC844i9P5SzyXw6ecZgNhY/Hoa9rcMgstrpm +9RewtQTnX2KeUp0ggtizMcIud+zyFA8+s+TwVrzm/Q9VV1JsE5EKxDSv103R0EUY +n/IYLyMVAgMBAAECggEBAKl1CgWxxJyygphlvXcU0DdVtn06meRN6il9PpZjCSHc +wQfEfKvduwTzk0NAGaPYJuozpMJxA8zvEqJrgqIVG5W+2sgpcM0nN7sG/5k9BVfr +myes/fExgOMjvtwz2qLjaLprVnRCQcAzaP8AT1WPBbSuH6gXikngoV5kNZxI/VX0 +oYniHmGUlfOC2LKYXvSpHEmXhEyuZFDLxNqEpUPG2xHot7HUYklJKR4qxhD44CZJ +UvOs5AeXxXlKVUpY0Ue+DGbd8kzNyVD+MChRKCDe+pwdIMP1u5yOwNNLqkveszOh +9RH85l07cFrB68+Qycx+HqhzkNgjafqKZt08PAR6PzECgYEA7SzL3pOtfVUMwPNd +6o1I8dfsSM7PxSWswUFkGF9ULijX4TbsQ3kli6Y3ZZZ4I1g4rEv3LKF1KB98Pv2T +iKID1scEke4cYy8Q69wvXgektPgEf2JDdOOm7mFADAvAh4oIvjHSDXaFeskqnhhZ +Vc3K64/7NNfd7NwT+dk69uNgVQMCgYEA1Y2/i5f2Es7xLAK1+NeoSYuDsKhfK3bn +sWEKmJflIchvQ/GcUthawKuACv2u59xLtDHI8+Jky3ISobVYKREP+otWv2rndSQk +XpfmsBLgIrcmgkBaZF+ebln8qwclqMjMW5hItfRKb/f57RTM+wsoGvNzWAxrtuR1 +O27PtrOe8AcCgYEA5x/FWBR/d2h/MjS3K9Ac6phpSRZIwK0TKYzItzuGtCjXH0C/ +go03OlxzFYtJbeAV8klhCNwaaEwubs/7iqWfqhhtaqwoe7ss+Tur6Sz3o+chsuUW +KX2Dej/JAzQcnbi1BmtUcAw0zU/mOQQvYn9WJLI9seQ+/wgEa3D2lgtEH/MCgYEA +hXPmfprBOTG/fwxWoaJLVWJtMmmVx7ivw6ZsE73gf8Mc3S3QzejMldjW1IeB1P1T +BdGSze3tpUGtKQcFh+xUuvJ2jHqHGCo03DQ7Ak9ZZ/hihUUn98/VVwq/HjYCL78E +Dj1VOvflyKEDu0ejbUKklmsK6rwgWBPeuvxdq8QGD+MCgYEAjXiRR7Jo+zKPZFmC +P7G4YURBxAXNAneHTS6NXrXqf8l6ST1yPMfy+AoBtW6IkwQuob8e0aR7WiAtK427 +OQicnMap9/oDZ+tm2po7O3FQ7EJKiPYdltuCS/H4rYHm70oMiuMvWb5tzlYSbk4Z +2LZ2Omi+NQyZiuHUWhnm8nQaQmc= +-----END PRIVATE KEY-----