我正在使用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/

10-11 22:35
查看更多