Reputation: 1566
I am using Windows Crypto API and can't decrypt file. After CryptDecrypt
I got some first bytes of my file is decrypted, but other bytes are rubbish.
For example:
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
This is MCVE. I read content from file input.txt
, ecnrypt it, write to file encrypted.txt
. Then I read encrypted.txt
and decrypt it with the same key and save to decrypted.txt
. The only first bytes of decrypted.txt is correct.
#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;
}
Upvotes: 0
Views: 672
Reputation: 81
I'm guessing that you did the same as I did - adding data to an encrypted file and then try to decrypt it... Well, it seems that you can not decrypt data using CryptDecrypt that was not encrypted all at once.
If you want to add data to an existing encrypted file you'll need to first read it's content to the memory and decrypt it (oldData), then add the newData, encrypt all together oldData+newData and then write to file (overwrite). It works for me with this code:
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;
}
}
Upvotes: 1