首先,如果我在这里遗漏了什么,我道歉。这是我第一次尝试使用Windows CryptAPI,虽然我已经浏览了谷歌,MSDN,MSDN的例子等等,但我无法弄清楚为什么会出现这个问题。 我有以下代码,它应该复制在特定地址找到的操作码(字节块),加密它们,然后将它们写回。它绝不是一个完整的代码,它只进行很少的错误检查。我使用的是AES256。
bool CryptoClass::encrypt(DWORD address, DWORD len)
{
DWORD dwBlockLen = 0;
DWORD dwBufferLen = 0;
DWORD dwCount = 0;
PBYTE pbBuffer = NULL;
dwBlockLen = AES_BLOCK_SIZE - AES_BLOCK_SIZE % ENCRYPT_BLOCK_SIZE;
dwBufferLen = dwBlockLen + ENCRYPT_BLOCK_SIZE;
if(pbBuffer = (BYTE *)malloc(dwBufferLen))
{
bool EOB = FALSE;
while ( dwCount <= len) )
{
memcpy((void*)pbBuffer,(void*)address,dwBlockLen);
if ( (len - dwCount) < dwBlockLen) EOB = TRUE;
if(CryptEncrypt(hKey,NULL,EOB,0,pbBuffer,&dwBlockLen,dwBufferLen))
{
memcpy((void*)address,(void*)pbBuffer,dwBlockLen);
address += dwBlockLen;
dwCount += dwBlockLen;
}
else
{
error = GetLastError();
MessageBoxA(NULL,"problem","error",MB_OK);
}
}
free(pbBuffer);
return true;
}
else return false;
}
根据我的理解,AES可以加密16字节的块,因此AES_BLOCK_SIZE定义为16。 我的ENCRYPT_BLOCK_SIZE也设置为8.我基本上复制了一个我在MSDN上找到的例子,并调整了AES256并用于内存而不是文件。 但是在我的while循环中,只要它到达缓冲区的末尾,其中FINAL设置为TRUE,CryptEncrypt就会失败。我已尝试过许多不同的方法来做到这一点,但总是失败。 是因为最后的缓冲区小于16字节? 有些人可以帮忙,在加密方面我是一个完全的菜鸟。 谢谢 编辑:GetLastError返回:0x000000ea
答案 0 :(得分:4)
您收到错误ERROR_MORE_DATA。这转化为:
如果为pbData分配的缓冲区不足以容纳加密数据,则GetLastError返回ERROR_MORE_DATA并将所需的缓冲区大小(以字节为单位)存储在pdwDataLen指向的DWORD值中。
如果该方法使用CBC加密(微软,其智慧,未在其API中指定模式或填充算法),则应执行以下算法来计算缓冲区的输出大小:
buffer_size =(plain_size_bytes / AES_BLOCK_SIZE + 1)* AES_BLOCK_SIZE;
换句话说,如果plain_size_bytes是N * AES_BLOCK_SIZE,您仍然需要一个完整的填充块。这是因为你总是需要执行填充,否则unpadding算法不能区分纯文本和填充字节。
当然,您也可以简单地创建一个plain_size_bytes + AES_BLOCK_SIZE的缓冲区,并使用pdwDataLen值来获取实际长度。
编辑:如果你单独加密每个纯文本块,并且密码使用带填充的CBC或ECB,那么最后一个普通块可能需要2个整块,因为上面
答案 1 :(得分:1)
while ( address < (address + len) )
我的神秘答案是“想一想 - 你不会永远想想它,但......”
答案 2 :(得分:0)
if ( (len - dwCount) < dwBlockLen) EOB = TRUE;
也许应该像
if ( (len - dwCount) < dwBlockLen)
{
EOB = TRUE;
dwBlockLen = ENCRYPT_BLOCK_SIZE;
}