来源:chatGPT
#include <iostream>
#include <fstream>
#include <openssl/evp.h>
#include <openssl/pem.h>
#include <openssl/err.h>
// 函数:生成数字签名
bool generateSignature(const std::string& filename, const std::string& privateKeyFile, std::string& signature) {
// 打开私钥文件
FILE* privateKeyFP = fopen(privateKeyFile.c_str(), "rb");
if (!privateKeyFP) {
std::cerr << "无法打开私钥文件" << std::endl;
return false;
}
// 读取私钥
EVP_PKEY* privateKey = PEM_read_PrivateKey(privateKeyFP, NULL, NULL, NULL);
fclose(privateKeyFP);
if (!privateKey) {
std::cerr << "无法读取私钥" << std::endl;
return false;
}
// 打开待签名文件
std::ifstream file(filename, std::ios::binary);
if (!file) {
std::cerr << "无法打开待签名文件" << std::endl;
EVP_PKEY_free(privateKey);
return false;
}
// 计算文件摘要
EVP_MD_CTX* mdctx = EVP_MD_CTX_new();
EVP_MD_CTX_init(mdctx);
EVP_DigestInit_ex(mdctx, EVP_sha256(), NULL);
char buffer[4096];
while (file.read(buffer, sizeof(buffer))) {
EVP_DigestUpdate(mdctx, buffer, file.gcount());
}
EVP_DigestFinal_ex(mdctx, buffer, NULL);
EVP_MD_CTX_free(mdctx);
// 对文件摘要进行签名
EVP_MD_CTX* signctx = EVP_MD_CTX_new();
EVP_MD_CTX_init(signctx);
EVP_SignInit_ex(signctx, EVP_sha256(), NULL);
EVP_SignUpdate(signctx, buffer, sizeof(buffer));
unsigned int signatureLength;
unsigned char* signatureData = (unsigned char*)malloc(EVP_PKEY_size(privateKey));
EVP_SignFinal(signctx, signatureData, &signatureLength, privateKey);
EVP_MD_CTX_free(signctx);
// 将签名数据转为字符串形式
signature.assign((char*)signatureData, signatureLength);
free(signatureData);
EVP_PKEY_free(privateKey);
return true;
}
// 函数:验证数字签名
bool verifySignature(const std::string& filename, const std::string& publicKeyFile, const std::string& signature) {
// 打开公钥文件
FILE* publicKeyFP = fopen(publicKeyFile.c_str(), "rb");
if (!publicKeyFP) {
std::cerr << "无法打开公钥文件" << std::endl;
return false;
}
// 读取公钥
EVP_PKEY* publicKey = PEM_read_PUBKEY(publicKeyFP, NULL, NULL, NULL);
fclose(publicKeyFP);
if (!publicKey) {
std::cerr << "无法读取公钥" << std::endl;
return false;
}
// 打开待验证文件
std::ifstream file(filename, std::ios::binary);
if (!file) {
std::cerr << "无法打开待验证文件" << std::endl;
EVP_PKEY_free(publicKey);
return false;
}
// 计算文件摘要
EVP_MD_CTX* mdctx = EVP_MD_CTX_new();
EVP_MD_CTX_init(mdctx);
EVP_DigestInit_ex(mdctx, EVP_sha256(), NULL);
char buffer[4096];
while (file.read(buffer, sizeof(buffer))) {
EVP_DigestUpdate(mdctx, buffer, file.gcount());
}
EVP_DigestFinal_ex(mdctx, buffer, NULL);
EVP_MD_CTX_free(mdctx);
// 验证签名
EVP_MD_CTX* verifyctx = EVP_MD_CTX_new();
EVP_MD_CTX_init(verifyctx);
EVP_VerifyInit_ex(verifyctx, EVP_sha256(), NULL);
EVP_VerifyUpdate(verifyctx, buffer, sizeof(buffer));
int result = EVP_VerifyFinal(verifyctx, (unsigned char*)signature.c_str(), signature.length(), publicKey);
EVP_MD_CTX_free(verifyctx);
EVP_PKEY_free(publicKey);
return (result == 1);
}
int main() {
std::string filename = "file.txt"; // 待签名的文件名
std::string privateKeyFile = "private.pem"; // 私钥文件名
std::string publicKeyFile = "public.pem"; // 公钥文件名
// 生成数字签名
std::string signature;
if (generateSignature(filename, privateKeyFile, signature)) {
std::cout << "数字签名生成成功" << std::endl;
// 将签名保存到文件或发送给其他人进行验证
std::ofstream signatureFile("signature.txt");
if (signatureFile) {
signatureFile << signature;
signatureFile.close();
} else {
std::cerr << "无法保存签名到文件" << std::endl;
}
} else {
std::cerr << "数字签名生成失败" << std::endl;
}
// 验证数字签名
std::string loadedSignature;
std::ifstream loadedSignatureFile("signature.txt");
if (loadedSignatureFile) {
loadedSignatureFile.seekg(0, std::ios::end);
loadedSignature.reserve(loadedSignatureFile.tellg());
loadedSignatureFile.seekg(0, std::ios::beg);
loadedSignature.assign((std::istreambuf_iterator<char>(loadedSignatureFile)), std::istreambuf_iterator<char>());
loadedSignatureFile.close();
if (verifySignature(filename, publicKeyFile, loadedSignature)) {
std::cout << "数字签名验证通过" << std::endl;
} else {
std::cout << "数字签名验证失败" << std::endl;
}
} else {
std::cerr << "无法加载签名文件" << std::endl;
}
return 0;
}