利用CryptoAPI实现数字签名 ,写出完整代码要求: (1) 用户选择要签名或验证签名的文件 (2) 将签名数据显示在用户界面中 开发语言: 不限 界面: 自定义
时间: 2024-05-10 20:17:03 浏览: 161
这是一个基于C++的数字签名实现,使用了Windows CryptoAPI库。
```cpp
#include <iostream>
#include <windows.h>
#include <wincrypt.h>
#include <fstream>
#include <sstream>
#pragma comment(lib, "crypt32.lib")
// 函数声明
bool signFile(const std::string& fileName, const std::string& keyName);
bool verifyFile(const std::string& fileName, const std::string& signatureFileName, const std::string& keyName);
std::string getErrorMessage(DWORD errorCode);
int main()
{
std::cout << "请选择要签名或验证签名的文件:" << std::endl;
std::string fileName;
std::getline(std::cin, fileName);
std::cout << "请选择要使用的密钥对名称:" << std::endl;
std::string keyName;
std::getline(std::cin, keyName);
std::cout << "请选择操作:\n1. 签名文件\n2. 验证签名" << std::endl;
int option;
std::cin >> option;
switch (option)
{
case 1:
if (signFile(fileName, keyName))
{
std::cout << "文件签名成功!" << std::endl;
}
else
{
std::cout << "文件签名失败!" << std::endl;
}
break;
case 2:
std::cout << "请输入签名文件名:" << std::endl;
std::string signatureFileName;
std::cin >> signatureFileName;
if (verifyFile(fileName, signatureFileName, keyName))
{
std::cout << "签名验证成功!" << std::endl;
}
else
{
std::cout << "签名验证失败!" << std::endl;
}
break;
default:
std::cout << "无效的操作!" << std::endl;
break;
}
return 0;
}
// 签名文件
bool signFile(const std::string& fileName, const std::string& keyName)
{
// 打开待签名文件
std::ifstream file(fileName, std::ios::binary);
if (!file)
{
std::cout << "无法打开文件:" << fileName << std::endl;
return false;
}
// 读取待签名文件内容
std::stringstream buffer;
buffer << file.rdbuf();
std::string fileContent = buffer.str();
// 获取句柄
HCRYPTPROV hProv;
if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
{
std::cout << "无法获取句柄,错误码:" << getErrorMessage(GetLastError()) << std::endl;
return false;
}
// 获取密钥句柄
HCRYPTKEY hKey;
if (!CryptGetUserKey(hProv, AT_SIGNATURE, &hKey))
{
std::cout << "无法获取密钥句柄,错误码:" << getErrorMessage(GetLastError()) << std::endl;
return false;
}
// 计算哈希值
HCRYPTHASH hHash;
if (!CryptCreateHash(hProv, CALG_SHA_256, hKey, 0, &hHash))
{
std::cout << "无法创建哈希对象,错误码:" << getErrorMessage(GetLastError()) << std::endl;
return false;
}
if (!CryptHashData(hHash, (BYTE*)fileContent.c_str(), fileContent.size(), 0))
{
std::cout << "无法计算哈希值,错误码:" << getErrorMessage(GetLastError()) << std::endl;
return false;
}
// 签名
DWORD signatureLength = 0;
if (!CryptSignHash(hHash, AT_SIGNATURE, NULL, 0, NULL, &signatureLength))
{
std::cout << "无法计算签名长度,错误码:" << getErrorMessage(GetLastError()) << std::endl;
return false;
}
std::vector<BYTE> signature(signatureLength);
if (!CryptSignHash(hHash, AT_SIGNATURE, NULL, 0, &signature[0], &signatureLength))
{
std::cout << "无法签名,错误码:" << getErrorMessage(GetLastError()) << std::endl;
return false;
}
// 将签名数据写入文件
std::ofstream signatureFile(keyName + ".sig", std::ios::binary);
if (!signatureFile)
{
std::cout << "无法写入签名文件,错误码:" << getErrorMessage(GetLastError()) << std::endl;
return false;
}
signatureFile.write((char*)&signature[0], signatureLength);
signatureFile.close();
// 释放资源
CryptDestroyHash(hHash);
CryptReleaseContext(hProv, 0);
return true;
}
// 验证签名
bool verifyFile(const std::string& fileName, const std::string& signatureFileName, const std::string& keyName)
{
// 打开待验证文件
std::ifstream file(fileName, std::ios::binary);
if (!file)
{
std::cout << "无法打开文件:" << fileName << std::endl;
return false;
}
// 读取待验证文件内容
std::stringstream buffer;
buffer << file.rdbuf();
std::string fileContent = buffer.str();
// 获取签名数据
std::ifstream signatureFile(signatureFileName, std::ios::binary);
if (!signatureFile)
{
std::cout << "无法打开签名文件:" << signatureFileName << std::endl;
return false;
}
signatureFile.seekg(0, signatureFile.end);
DWORD signatureLength = signatureFile.tellg();
signatureFile.seekg(0, signatureFile.beg);
std::vector<BYTE> signature(signatureLength);
signatureFile.read((char*)&signature[0], signatureLength);
// 获取句柄
HCRYPTPROV hProv;
if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
{
std::cout << "无法获取句柄,错误码:" << getErrorMessage(GetLastError()) << std::endl;
return false;
}
// 获取密钥句柄
HCRYPTKEY hKey;
if (!CryptGetUserKey(hProv, AT_SIGNATURE, &hKey))
{
std::cout << "无法获取密钥句柄,错误码:" << getErrorMessage(GetLastError()) << std::endl;
return false;
}
// 计算哈希值
HCRYPTHASH hHash;
if (!CryptCreateHash(hProv, CALG_SHA_256, hKey, 0, &hHash))
{
std::cout << "无法创建哈希对象,错误码:" << getErrorMessage(GetLastError()) << std::endl;
return false;
}
if (!CryptHashData(hHash, (BYTE*)fileContent.c_str(), fileContent.size(), 0))
{
std::cout << "无法计算哈希值,错误码:" << getErrorMessage(GetLastError()) << std::endl;
return false;
}
// 验证签名
if (!CryptVerifySignature(hHash, &signature[0], signatureLength, hKey, NULL, 0))
{
std::cout << "签名验证失败,错误码:" << getErrorMessage(GetLastError()) << std::endl;
return false;
}
// 释放资源
CryptDestroyHash(hHash);
CryptReleaseContext(hProv, 0);
return true;
}
// 获取错误信息
std::string getErrorMessage(DWORD errorCode)
{
LPSTR buffer = NULL;
DWORD size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, errorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&buffer, 0, NULL);
std::string message(buffer, size);
LocalFree(buffer);
return message;
}
```
界面部分没有提供,因为要求自定义界面,可以根据实际需求进行设计。
阅读全文