我尝试使用RSA public_key加密AES密钥,并在控制台上打印加密的字节。我使用Windows Cryptographic 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等,但是由于堆错误,我把缓冲区转移到了vector上,我知道这更好地避免了内存损坏。然而,我的错误仍然没有解决。我已经调试了程序,并检查了每个变量的可用值和缓冲区。一切都在它应该。我错过了一些东西。任何帮助都将不胜感激。
1条答案
按热度按时间gab6jxml1#
我已经向ChatGPT-4提出了同样的问题,并得到了准确的答案。看起来问题是我处理加密密钥缓冲区的方式。当我调用CryptEncrypt时,
pbAesKey
缓冲区被加密数据覆盖。然而,我已经分配了pbEncryptedKey
单独存储加密密钥。而不是将加密数据从pbAesKey
复制到pbEncryptedKey
,我应该直接将数据加密到pbEncryptedKey
中。所以替换代码
与
已解决问题。
这样,我首先将AES密钥复制到
pbEncryptedKey
中,然后使用pbEncryptedKey
作为加密数据的缓冲区,之后,我可以安全地使用pbEncryptedKey.data()
将加密密钥转换为十六进制字符串,而不会出现任何堆损坏问题。