#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"