我不太擅长加密 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;
}
不幸的是我不知道如何解决它!我对填充其他细节感到非常困惑,我希望我能从你们那里得到一些帮助。
谢谢
您对填充的处理方式不正确。对于像 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
将密钥大小减半。