XNSim/XNSignature/verify.cpp

303 lines
7.8 KiB
C++
Raw Permalink Normal View History

#include "XNSignature_global.h"
#include <openssl/evp.h>
#include <openssl/pem.h>
#include <openssl/err.h>
#include <openssl/rsa.h>
#include <openssl/sha.h>
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
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<unsigned char> signature(signatureSize);
signatureFile.read(reinterpret_cast<char *>(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<unsigned char> signature(signatureSize);
signatureFile.read(reinterpret_cast<char *>(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"