我正在尝试使用 RSA public_key 加密 AES 密钥并在控制台上打印加密字节。我正在使用 Windows 加密 API 来加密密钥,还使用 Microsoft 记录的方式获取加密字节所需的缓冲区大小,如下面提供的代码所示:
我面临的问题是,每次执行我的程序并调用 lockKey 函数时,即使 lockKey 函数中的所有代码都已成功执行,每次返回时都会出现堆损坏错误。我已经调试了代码,但找不到原因,因为每次函数返回(结束括号)都会抛出异常。
完整代码如下:
#include <windows.h>
#include <wincrypt.h>
#include <iostream>
#include <vector>
#include <string>
#include <iomanip>
#include <fstream>
#pragma comment(lib, "crypt32.lib")
using namespace std;
void lockKey(std::string, HCRYPTKEY, HCRYPTPROV);
void handleError(const char*);
std::string byteToHex(BYTE*, DWORD);
void handleError(const char* message)
{
cerr << message << " error code: " << GetLastError() << endl;
exit(1);
}
std::string byteToHex(BYTE* inputBytes, DWORD inputSize)
{
std::string outputString;
DWORD hexSize = 0;
if (!CryptBinaryToStringA(inputBytes, inputSize, CRYPT_STRING_HEX, NULL, &hexSize))
{
// handle error
handleError("Failed to get size of encrypted bytes key");
return NULL;
}
outputString.resize(hexSize, '\0');
if (!CryptBinaryToStringA(inputBytes, inputSize, CRYPT_STRING_HEX, &outputString[0], &hexSize))
{
// handle error
handleError("Failed to convert encrypted bytes key to hexSize");
return NULL;
}
//outputString.resize(hexSize - 1); // remove null terminator
return outputString;
}
void lockKey(std::string publickey, HCRYPTKEY hKey, HCRYPTPROV hCryptProv)
{
//Import RSA public key
std::vector<BYTE> publicKeyBytes;
DWORD publicKeySize = 0;
if (!CryptStringToBinaryA(publickey.c_str(), publickey.length(), CRYPT_STRING_BASE64, NULL, &publicKeySize, NULL, NULL)) {
CryptReleaseContext(hCryptProv, 0);
handleError("Error getting binary size");
}
publicKeyBytes.resize(publicKeySize);
if (!CryptStringToBinaryA(publickey.c_str(), publickey.length(), CRYPT_STRING_BASE64, publicKeyBytes.data(), &publicKeySize, NULL, NULL)) {
CryptReleaseContext(hCryptProv, 0);
handleError("Error converting to binary");
}
HCRYPTKEY phKey = NULL;
if (!CryptImportKey(hCryptProv, publicKeyBytes.data(), publicKeyBytes.size(), 0, 0, &phKey)) {
CryptDestroyKey(phKey);
CryptDestroyKey(hKey);
CryptReleaseContext(hCryptProv, 0);
handleError("Error importing key");
}
//Export AES key for encryption
//Determine the size of the buffer needed for the exported key
DWORD dwBufSizeAES = 0;
if (!CryptExportKey(hKey, NULL, PLAINTEXTKEYBLOB, NULL, NULL, &dwBufSizeAES))
{
CryptDestroyKey(phKey);
CryptDestroyKey(hKey);
CryptReleaseContext(hCryptProv, 0);
handleError("Error determining key buffer size");
}
// Allocate a buffer for the exported key
//BYTE* pbAesKey = new BYTE[dwBufSizeAES];
//memset(pbAesKey, 0, dwBufSizeAES);
std::vector<BYTE> pbAesKey(dwBufSizeAES, 0);
// Export the key to the buffer
if (!CryptExportKey(hKey, NULL, PLAINTEXTKEYBLOB, NULL, pbAesKey.data(), &dwBufSizeAES))
{
CryptDestroyKey(phKey);
CryptDestroyKey(hKey);
CryptReleaseContext(hCryptProv, 0);
handleError("Error exporting key");
}
//Encrypt AES key with RSA public key
//Determine the size of the buffer needed for the encrypted key
DWORD dwBufSize = 0;
if (!CryptEncrypt(phKey, NULL, TRUE, 0, NULL, &dwBufSize, 0))
{
CryptDestroyKey(phKey);
CryptDestroyKey(hKey);
CryptReleaseContext(hCryptProv, 0);
handleError("Error determining encrypted buffer size");
}
//PBYTE pbEncryptedKey = (PBYTE)malloc(dwBufSize);
std::vector<BYTE> pbEncryptedKey(dwBufSize, 0);
// Encrypt the AES key with RSA-OAEP padding
DWORD cbAesKey = 0;
if (!CryptEncrypt(phKey, NULL, TRUE, 0, pbAesKey.data(), &cbAesKey, dwBufSize))
{
CryptDestroyKey(phKey);
CryptDestroyKey(hKey);
CryptReleaseContext(hCryptProv, 0);
handleError("Error encrypting AES key");
}
memcpy(pbEncryptedKey.data(), pbAesKey.data(), dwBufSize);
// Now pbEncryptedKey contains the encrypted AES key
std::string hexEncryptedKey = byteToHex(pbEncryptedKey.data(), dwBufSize);
cout << "Encrypted AES Key Bytes: \n" << hexEncryptedKey << endl;
CryptDestroyKey(phKey);
} //error always on this line of code.
int main()
{
DWORD blockSize;
HCRYPTKEY hKey;
HCRYPTPROV hCryptProv;
// Import the RSA public key as in the previous example.
std::string publickey = "valid public key"; //removed
// Generate aes key
hCryptProv;
if (!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) {
CryptReleaseContext(hCryptProv, 0);
handleError("Failed to acquire cryptographic context");
}
hKey;
if (!CryptGenKey(hCryptProv, CALG_AES_256, CRYPT_EXPORTABLE, &hKey)) {
CryptReleaseContext(hCryptProv, 0);
handleError("Failed to generate key");
}
// Get the block size for the algorithm
blockSize;
DWORD dwDataLen = sizeof(DWORD);
if (!CryptGetKeyParam(hKey, KP_BLOCKLEN, (BYTE*)&blockSize, &dwDataLen, 0)) {
CryptDestroyKey(hKey);
CryptReleaseContext(hCryptProv, 0);
handleError("Failed to get block size");
}
lockKey(publickey, hKey, hCryptProv);
CryptDestroyKey(hKey);
CryptReleaseContext(hCryptProv, 0);
return 0;
}
报错截图如下:
如果继续那么它会给出堆损坏错误:
我一开始使用内存管理函数,比如 memset、malloc、free、delete 等。但是因为堆错误。我已经将我的缓冲区转移到矢量,据我所知,使用它们可以更好地避免内存损坏。但是,我的错误仍然没有解决。我已经调试了程序并检查了每个变量的可用值和缓冲区。一切都在它应该的。我错过了一些东西。任何帮助,将不胜感激。谢谢!