在加密函数期间返回函数或子例程时发生堆损坏

问题描述 投票:0回答:0

我正在尝试使用 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;

}

报错截图如下:

Exception in visual studio

如果继续那么它会给出堆损坏错误:

Heap corruption

我一开始使用内存管理函数,比如 memset、malloc、free、delete 等。但是因为堆错误。我已经将我的缓冲区转移到矢量,据我所知,使用它们可以更好地避免内存损坏。但是,我的错误仍然没有解决。我已经调试了程序并检查了每个变量的可用值和缓冲区。一切都在它应该的。我错过了一些东西。任何帮助,将不胜感激。谢谢!

c++ encryption memory-leaks heap-corruption
© www.soinside.com 2019 - 2024. All rights reserved.