我正在使用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
并使用相同的密钥对其进行解密,然后保存到decrypted.txt
。解密的.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解密数据。
如果要将数据添加到现有的加密文件中,则需要先将其内容读取到内存中并解密(oldData),然后添加newData,将oldData + newData一起加密,然后写入文件(覆盖)。
此代码对我有用:
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/