CryptDecrypt()无法解密某些块C ++

时间:2014-04-15 04:09:14

标签: c++ winapi encryption cryptoapi

我目前正在使用Windows API在C ++中开发一个简单的加密/解密系统。

我相信我已经成功地让CryptEncrypt()工作(AES_128)来加密文件。 但是,当我使用CryptDecrypt()解密文件时,前16个字节已损坏,然后4000字节(这是我从ReadFile()拉出的块的大小并加密)是另一个块损坏的字节等等。如果我尝试解密总长度小于4000字节的文件,则解密工作完美。

我很困惑为什么会这样。根本没有错误。

以下是我的代码片段(我有CryptEncrypt()CryptDecrypt(),以便我保存导出密钥并加快测试速度:

DWORD bytesRead;
DWORD bytesWritten;
DWORD pointer = 0;
unsigned int blockSize = 4000;
void *fileBuffer = new unsigned char[4106];
bool EOF = false;
do
{
    SetFilePointer(hFileOrginal,pointer,0,0);
    ReadFile(hFileOrginal,fileBuffer,blockSize,&bytesRead,NULL);
    if(bytesRead<blockSize)
    {
        EOF=true;
    }
    CryptEncrypt(aesKey,NULL,EOF,0,(BYTE *)fileBuffer,&bytesRead,(blockSize+16));
    CryptDecrypt(aesKey,NULL,EOF,0,(BYTE *)fileBuffer,&bytesRead);

    WriteFile(hTempFile,fileBuffer,bytesRead,&bytesWritten,NULL);
    pointer +=bytesRead;
}
while(!EOF);
delete[] fileBuffer;

我真的很感激任何关于什么是错误的建议。

编辑:在一个4704字节的文件中,我使用断点获得了以下内容。

First ReadFile bytesread 4000 First CryptEncrypt bytesRead 4000 第一个CryptDecrypt bytesRead 4000 第二个ReadFile bytesread 704 第二个CryptEncrypt bytesread 720 第二个CryptDecrupt bytesread 704

一切似乎都很好但我仍然遇到问题。

我正在使用增强型加密api(使用verifycontext)生成一个带有CRYPT_EXPORTABLE属性的AES密钥

1 个答案:

答案 0 :(得分:3)

您根本没有进行任何错误处理。您调用的所有API函数都有返回值和错误代码,您正在检查它们。

您也没有正确管理bytesReadCryptEncrypt()会修改您传递给它的变量,这会影响您对CreateDecrypt()的调用,该SetFilePointer()也会对其进行修改,然后影响后续调用bytesRead,您不应该调用你的循环开始。您没有验证您拥有的字节数与预期的一样多,或者ReadFile()最终返回bool ReadFromFile(HANDLE hFile, void *Buffer, DWORD BufSize, DWORD *BytesRead) { if (BytesRead) *BytesRead = 0; LPBYTE pBuffer = (LPBYTE) Buffer; DWORD dwRead; while (BufSize > 0) { if (!ReadFile(hFile, pBuffer, BufSize, &dwRead, NULL)) return false; if (dwRead == 0) break; pBuffer += dwRead; BufSize -= dwRead; if (BytesRead) *BytesRead += dwRead; } return true; } bool WriteToFile(HANDLE hFile, void *Buffer, DWORD BufSize) { LPBYTE pBuffer = (LPBYTE) Buffer; DWORD dwWritten; while (BufSize > 0) { if (!WriteFile(hFile, pBuffer, BufSize, &dwWritten, NULL)) return false; pBuffer += dwWritten; BufSize -= dwWritten; } return true; } 返回的原始值,因此您最终可能会跳过源文件中的字节。 / p>

尝试更像这样的东西:

DWORD bytesRead;
const UINT blockSize = 4000;
LPBYTE fileBuffer = new BYTE[blockSize+16];
bool EOF;

if (SetFilePointer(hFileOrginal, 0, NULL, FILE_BEGIN) != 0)
{
    errorCode = GetLastError();
    ...
}
else
{
    do
    {
        if (!ReadFromFile(hFileOrginal, fileBuffer, blockSize, &bytesRead))
        {
            errorCode = GetLastError();
            ...
            break;
        }

        EOF = (bytesRead < blockSize);

        bytesEncrypted = bytesRead;
        if (!CryptEncrypt(aesKey, NULL, EOF, 0, fileBuffer, &bytesEncrypted, blockSize+16))
        {
            errorCode = GetLastError();
            ...
            break;
        }

        bytesDecrypted = bytesEncrypted;
        if (!CryptDecrypt(aesKey, NULL, EOF, 0, fileBuffer, &bytesDecrypted))
        {
            errorCode = GetLastError();
            ...
            break;
        }

        if (!WriteToFile(hTempFile, fileBuffer, bytesDecrypted))
        {
            errorCode = GetLastError();
            ...
            break;
        }

        if (bytesDecrypted != bytesRead)
        {
            ...
            break;
        }
    }
    while (!EOF);
}
delete[] fileBuffer;

{{1}}