我目前正在使用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密钥
答案 0 :(得分:3)
您根本没有进行任何错误处理。您调用的所有API函数都有返回值和错误代码,您正在检查它们。
您也没有正确管理bytesRead
。 CryptEncrypt()
会修改您传递给它的变量,这会影响您对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}}