我正在使用 Windows Crypto API,但无法解密文件。在 CryptDecrypt
之后,我的文件的一些第一个字节被解密,但其他字节是垃圾。
例如:
01234567012345670123456701234567012345670123456701234567012345670123456701234
56701234567012345670123456701234567012345670123456701234567012345670123456701
23456701234567012345670123456701234567012345670123456701234567012345670123456
70123456701еzc^HЏ-v"ЙЂQЋ;Ђ©ЕЮЃЛќА ы§Чюн-D„=оШХU†>™B‰Кy)Л¬6A)жO0”~sjё;<Лxj:("Ц
TвeхфOУKCв]H°фі"XШ8S{±~Ф\+a]gmъШie,Zџ§0ыќQq1ђ$sѓI~Чроы_2f
这是 MCVE。我从文件 input.txt
中读取内容,加密它,写入文件 encrypted.txt
。然后我读取 encrypted.txt
并使用相同的 key 解密它并保存到 decrypted.txt
。只有 decrypted.txt 的前几个字节是正确的。
#include "stdafx.h"
#include <fstream>
#include <Windows.h>
#include <wincrypt.h>
using namespace std;
HCRYPTPROV hProvider;
HCRYPTKEY hKey;
char* readFile(const char* filename, DWORD* bufferSize);
void encrypt();
void decrypt();
int main()
{
//Create context
if (!CryptAcquireContextA(&hProvider, "container", NULL, PROV_RSA_FULL, 0))
{
if (!CryptAcquireContextA(&hProvider, "container", NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET))
return 1;
}
//Create key
CryptGenKey(
hProvider,
CALG_RC4,
CRYPT_EXPORTABLE,
&hKey);
encrypt();
decrypt();
}
//Read all file content
char* readFile(const char* filename, DWORD* bufferSize)
{
//Чтение исходного файла
ifstream is(filename);
is.seekg(0, std::ios::end);
*bufferSize = is.tellg();
is.seekg(0, std::ios::beg);
char* buffer = new char[*bufferSize];
is.read(buffer, *bufferSize);
is.close();
return buffer;
}
void encrypt()
{
//Read file
DWORD dataSize;
char* data = readFile("input.txt", &dataSize);
//Encrypt
CryptEncrypt(
hKey,
NULL,
true,
NULL,
(unsigned char*)data,
&dataSize,
dataSize
);
//Write file
ofstream os("encrypted.txt");
os.write(data, dataSize);
os.close();
delete[] data;
}
void decrypt()
{
//Read file
DWORD dataSize;
char* data = readFile("encrypted.txt", &dataSize);
//Encrypt
CryptDecrypt(
hKey,
NULL,
true,
NULL,
(unsigned char*)data,
&dataSize
);
//Write file
ofstream os("decrypted.txt");
os.write(data, dataSize);
os.close();
delete[] data;
}
最佳答案
我猜你和我做的一样 - 将数据添加到加密文件,然后尝试解密它......好吧,似乎你无法使用 CryptDecrypt 立即解密数据.
如果你想将数据添加到现有的加密文件中,你需要先将其内容读取到内存中并对其进行解密(旧数据),然后添加新数据,将所有旧数据+新数据一起加密,然后写入文件(覆盖)。 它适用于我的代码:
void CMFCApplication2Dlg::log2File(CString newData) {
//Open or Create new log file
if (!(file.Open(_T(FILE_NAME), CFile::modeNoTruncate | CFile::modeCreate | CFile::modeReadWrite)))
{
AfxMessageBox(_T("Couldn't open file."));
return;
}
file.Close();
CString oldData;
//read binary data from file --> decrypt it and return decrypted oldData.
readFile(oldData);
//Add at the end of file new data to be encrypted.
oldData += newData;
newData = oldData;
CByteArray arBytes;
//Encypt new data
//Derive a key from a password.
crypto.DeriveKey(CRYPTO_PASS);
//put encypted newData to arBytes.
crypto.Encrypt(newData, arBytes);
//Delete file (we will write a new one ==> overwite)
CFile::Remove(_T(FILE_NAME));
//Create new log file
if (file.Open(_T(FILE_NAME), CFile::modeNoTruncate | CFile::modeCreate |CFile::modeReadWrite))
{
//Write the encrypted data (byte array) to a "new" file
//(we deleted the original one and creating a new one with the same name (overwrite)
file.Write(arBytes.GetData(), static_cast<UINT>(arBytes.GetCount()));
file.Close();
}
else {
AfxMessageBox(_T("Couldn't write newData to file."));
}
//For Debug only ==> popup the file content
CString str1;
readFile(str1);
AfxMessageBox((str1));
}
void CMFCApplication2Dlg::readFile(CString &str) {
//Open the file in read mode
if ( (file.Open(_T(FILE_NAME), CFile::modeRead) == TRUE) &&
(file.GetLength() == 0) )
{
//There is no file ==> first time
//Nothing to read, return empty string
file.Close();
str = "";
return;
}
CByteArray arBytes;
CString m_strData;
//Size the array to accomodate the file bytes.
arBytes.SetSize(static_cast<INT_PTR>(file.GetLength()));
// Copy the data and close the file.
file.Read(arBytes.GetData(), static_cast<UINT>(file.GetLength()));
file.Close();
// Try and deserialize the data.
//Derive a key from a password.
crypto.DeriveKey(CRYPTO_PASS);
if (crypto.Decrypt(arBytes, m_strData) == false)
AfxMessageBox(_T("Coudln't decrypt data- check password."));
else
{
//We have data !!
str = m_strData;
}
}
关于c++ - CryptDecrypt 只解密第一个字节,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39904267/