Windows api AES256 解密

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

我不太擅长加密 API,我正在尝试加密和解密二进制文件。我将以下代码放在一起来加密文件并将其存储回文件并且它可以工作,

#include <Windows.h>
#include <Wincrypt.h>
#include <iostream>
#include <vector>

bool EncryptAES256(char* data, DWORD dataSize, const char* key, DWORD keySize) {
    HCRYPTPROV hCryptProv = NULL;
    HCRYPTHASH hHash = NULL;
    HCRYPTKEY hKey = NULL;
    DWORD dwMode = CRYPT_MODE_CBC;

    // Create a cryptographic provider context handle.
    if (!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) {
        std::cerr << "Error: CryptAcquireContext failed with error code " << GetLastError() << std::endl;
        return false;
    }

    // Create a hash object of the key.
    if (!CryptCreateHash(hCryptProv, CALG_SHA_256, 0, 0, &hHash)) {
        std::cerr << "Error: CryptCreateHash failed with error code " << GetLastError() << std::endl;
        CryptReleaseContext(hCryptProv, 0);
        return false;
    }

    if (!CryptHashData(hHash, (const BYTE*)key, keySize, 0)) {
        std::cerr << "Error: CryptHashData failed with error code " << GetLastError() << std::endl;
        CryptDestroyHash(hHash);
        CryptReleaseContext(hCryptProv, 0);
        return false;
    }

    // Derive a symmetric key from the hash.
    if (!CryptDeriveKey(hCryptProv, CALG_AES_256, hHash, 0, &hKey)) {
        std::cerr << "Error: CryptDeriveKey failed with error code " << GetLastError() << std::endl;
        CryptDestroyHash(hHash);
        CryptReleaseContext(hCryptProv, 0);
        return false;
    }

    // Set encryption mode to CBC
    if (!CryptSetKeyParam(hKey, KP_MODE, (BYTE*)&dwMode, 0)) {
        std::cerr << "Error: CryptSetKeyParam failed with error code " << GetLastError() << std::endl;
        CryptDestroyKey(hKey);
        CryptDestroyHash(hHash);
        CryptReleaseContext(hCryptProv, 0);
        return false;
    }

    // Apply PKCS7 padding to the data buffer
    int padding = 16 - (dataSize % 16);
    for (int i = 0; i < padding; ++i) {
        data[dataSize + i] = padding;
    }
    dataSize += padding;

    // Encrypt the data using AES 256.
    if (!CryptEncrypt(hKey, 0, TRUE, 0, (BYTE*)data, &dataSize, dataSize * 2)) {
        std::cerr << "Error: CryptEncrypt failed with error code " << GetLastError() << std::endl;
        CryptDestroyKey(hKey);
        CryptDestroyHash(hHash);
        CryptReleaseContext(hCryptProv, 0);
        return false;
    }

    // Print the encrypted data
    std::cout << "Encrypted Data: ";
    for (DWORD i = 0; i < 8; ++i) {
        printf("%02x", (unsigned char)data[i]);
    }
    std::cout << std::endl;

    // Clean up resources.
    CryptDestroyKey(hKey);
    CryptDestroyHash(hHash);
    CryptReleaseContext(hCryptProv, 0);

    return true;
}

int main() {
    HANDLE hF = CreateFileA("C:\\temp\\test.bin",
        GENERIC_READ,
        0,
        NULL,
        OPEN_EXISTING,
        FILE_ATTRIBUTE_NORMAL,
        NULL);
    if (hF == INVALID_HANDLE_VALUE) {
        std::cout << "ERR CreateFileA failed" << std::endl;
        std::cout << GetLastError() << std::endl;
        return -1;
    }

    long r_dwSize = GetFileSize(hF, NULL);
    LPVOID lpbase = VirtualAlloc(NULL, r_dwSize * 2, MEM_COMMIT, PAGE_READWRITE);

    DWORD dwReadBytes = 0;
    BOOL r_read = ReadFile(hF, lpbase, r_dwSize, &dwReadBytes, NULL);
    if (!r_read) {
        std::cout << "ERR ReadFile failed" << std::endl;
        CloseHandle(hF);
        VirtualFree(lpbase, 0, MEM_RELEASE);
        return -1;
    }


    std::cout << "Original Data: ";
    for (DWORD i = 0; i < 8; ++i) {
        printf("%02x", (unsigned char)((char*)lpbase)[i]);
    }
    std::cout << std::endl;

    // Create a new file to write the encrypted data
    HANDLE hEncryptedFile = CreateFileA("C:\\temp\\encrypted_output.bin",
        GENERIC_WRITE,
        0,
        NULL,
        CREATE_ALWAYS, // Creates a new file; if the file exists, it's truncated
        FILE_ATTRIBUTE_NORMAL,
        NULL);

    if (hEncryptedFile == INVALID_HANDLE_VALUE) {
        std::cerr << "ERR CreateFileA for encrypted file failed with error code " << GetLastError() << std::endl;
        CloseHandle(hF);
        VirtualFree(lpbase, 0, MEM_RELEASE);
        return -1;
    }

    // Encrypt the data
    std::string key = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; // Replace with your 32-byte key in hexadecimal format
    bool encryptionResult = EncryptAES256((char*)lpbase, dwReadBytes, key.c_str(), key.size() / 2); // Divide by 2 for hexadecimal bytes

    if (encryptionResult) {
        std::cout << "Encryption successful!" << std::endl;
        // Write the encrypted data to the new file
        DWORD dwBytesWritten;
        BOOL writeResult = WriteFile(hEncryptedFile, lpbase, dwReadBytes, &dwBytesWritten, NULL);
        if (writeResult) {
            std::cout << "Encrypted data written to encrypted_output.bin" << std::endl;
        }
        else {
            std::cerr << "Error writing encrypted data to file with error code " << GetLastError() << std::endl;
        }
    }
    else {
        std::cerr << "Encryption failed!" << std::endl;
    }

    // Close the handles and free the allocated memory
    CloseHandle(hEncryptedFile);
    CloseHandle(hF);
    VirtualFree(lpbase, 0, MEM_RELEASE);
    return 0;

}

但是当我想解密它时,我不断从

2148073477
函数收到
CryptDecrypt
错误代码,下面是解密代码,

#include <Windows.h>
#include <Wincrypt.h>
#include <iostream>
#include <vector>

bool DecryptAES256(char* data, DWORD& dataSize, const char* key, DWORD keySize) {
    HCRYPTPROV hCryptProv = NULL;
    HCRYPTHASH hHash = NULL;
    HCRYPTKEY hKey = NULL;
    DWORD dwMode = CRYPT_MODE_CBC;

    // Create a cryptographic provider context handle.
    if (!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) {
        std::cerr << "Error: CryptAcquireContext failed with error code " << GetLastError() << std::endl;
        return false;
    }

    // Create a hash object of the key.
    if (!CryptCreateHash(hCryptProv, CALG_SHA_256, 0, 0, &hHash)) {
        std::cerr << "Error: CryptCreateHash failed with error code " << GetLastError() << std::endl;
        CryptReleaseContext(hCryptProv, 0);
        return false;
    }

    if (!CryptHashData(hHash, (const BYTE*)key, keySize, 0)) {
        std::cerr << "Error: CryptHashData failed with error code " << GetLastError() << std::endl;
        CryptDestroyHash(hHash);
        CryptReleaseContext(hCryptProv, 0);
        return false;
    }

    // Derive a symmetric key from the hash.
    if (!CryptDeriveKey(hCryptProv, CALG_AES_256, hHash, 0, &hKey)) {
        std::cerr << "Error: CryptDeriveKey failed with error code " << GetLastError() << std::endl;
        CryptDestroyHash(hHash);
        CryptReleaseContext(hCryptProv, 0);
        return false;
    }

    // Set decryption mode to CBC
    if (!CryptSetKeyParam(hKey, KP_MODE, (BYTE*)&dwMode, 0)) {
        std::cerr << "Error: CryptSetKeyParam failed with error code " << GetLastError() << std::endl;
        CryptDestroyKey(hKey);
        CryptDestroyHash(hHash);
        CryptReleaseContext(hCryptProv, 0);
        return false;
    }

    // Decrypt the data using AES 256.
    if (!CryptDecrypt(hKey, 0, TRUE, 0, (BYTE*)data, &dataSize)) {
        std::cerr << "Error: CryptDecrypt failed with error code " << GetLastError() << std::endl;
        CryptDestroyKey(hKey);
        CryptDestroyHash(hHash);
        CryptReleaseContext(hCryptProv, 0);
        return false;
    }

    // Remove PKCS7 padding
    BYTE padValue = data[dataSize - 1];
    if (padValue >= 1 && padValue <= 16) {
        dataSize -= padValue;
    }
    else {
        std::cerr << "Error: Invalid PKCS7 padding value" << std::endl;
        CryptDestroyKey(hKey);
        CryptDestroyHash(hHash);
        CryptReleaseContext(hCryptProv, 0);
        return false;
    }

    // Clean up resources.
    CryptDestroyKey(hKey);
    CryptDestroyHash(hHash);
    CryptReleaseContext(hCryptProv, 0);

    return true;
}


int main() {
    // Open the encrypted file
    HANDLE hEncryptedFile = CreateFileA("C:\\temp\\encrypted_output.bin",
        GENERIC_READ,
        0,
        NULL,
        OPEN_EXISTING,
        FILE_ATTRIBUTE_NORMAL,
        NULL);

    if (hEncryptedFile == INVALID_HANDLE_VALUE) {
        std::cerr << "Error: Unable to open encrypted file. Error code: " << GetLastError() << std::endl;
        return -1;
    }

    // Get the size of the encrypted file
    DWORD encryptedFileSize = GetFileSize(hEncryptedFile, NULL);

    // Allocate memory to read the encrypted data
    std::vector<BYTE> encryptedData(encryptedFileSize);
    DWORD dwBytesRead;
    if (!ReadFile(hEncryptedFile, encryptedData.data(), encryptedFileSize, &dwBytesRead, NULL)) {
        std::cerr << "Error reading encrypted data from file. Error code: " << GetLastError() << std::endl;
        CloseHandle(hEncryptedFile);
        return -1;
    }

    CloseHandle(hEncryptedFile);

    // Decrypt the data
    std::string key = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
    DWORD dataSize = dwBytesRead; // Initial data size equals the read size

    if (DecryptAES256(reinterpret_cast<char*>(encryptedData.data()), dataSize, key.c_str(), key.size() / 2)) {
        std::cout << "Decryption successful!" << std::endl;

        // Create a new file to write the decrypted data
        HANDLE hDecryptedFile = CreateFileA("C:\\temp\\decrypted_output.exe",
            GENERIC_WRITE,
            0,
            NULL,
            CREATE_ALWAYS,
            FILE_ATTRIBUTE_NORMAL,
            NULL);

        if (hDecryptedFile == INVALID_HANDLE_VALUE) {
            std::cerr << "Error: Unable to create decrypted file. Error code: " << GetLastError() << std::endl;
            return -1;
        }

        // Write the decrypted data to the new file
        DWORD dwBytesWritten;
        if (!WriteFile(hDecryptedFile, encryptedData.data(), dataSize, &dwBytesWritten, NULL)) {
            std::cerr << "Error writing decrypted data to file. Error code: " << GetLastError() << std::endl;
        }
        else {
            std::cout << "Decrypted data written to decrypted_output.exe" << std::endl;
        }

        CloseHandle(hDecryptedFile);
    }
    else {
        std::cerr << "Decryption failed!" << std::endl;
    }

    return 0;
}

不幸的是我不知道如何解决它!我对填充其他细节感到非常困惑,我希望我能从你们那里得到一些帮助。

谢谢

winapi encryption wincrypt
1个回答
0
投票

您对填充的处理方式不正确。对于像 CBC 这样的分组密码模式,wincrypt 的默认填充是 PKCS#7。这可以通过

CryptGetKeyParam
KP_PADDING
一起验证(并用
CryptSetKeyParam
进行更改)。因此,您的自定义填充将被删除(在加密和解密中)。
密文的长度(例如将密文写入文件所需的长度)在使用
pdwDataLen
加密后存储在
CryptEncrypt()
中。
如果考虑到这一点,生成的密文的解密可以在我的机器上进行(假设加密和解密使用相同的密钥,这已经在评论中指出)。

安全性:请注意,CBC 使用 IV,并且对于每次加密,都应生成一个随机 IV。 IV 并不是秘密。因此,它通常与密文连接起来,以便在解密时可用。
如果您不生成 IV,则默认使用零 IV(由 16 个 0x00 值组成;这可以使用

CryptGetKeyParam()
KP_IV
结合进行验证),这会导致重复使用密钥/IV 对使用相同密钥进行多次加密是一个漏洞。
为了完整起见,请注意,实际上不需要使用
key.size() / 2
将密钥大小减半。

© www.soinside.com 2019 - 2024. All rights reserved.