c++ - CryptEncrypt AES 256 在加密最后一个 block 时失败

标签 c++ winapi encryption

首先,如果我在这里遗漏了什么,我深表歉意。这是我对 Windows CryptAPI 的第一次尝试,虽然我已经通过谷歌、MSDN、MSDN 的示例等进行了搜索,但我无法弄清楚为什么会出现此问题。 我有以下代码,它应该复制在特定地址找到的操作码(字节 block ),加密它们,然后将它们写回。它绝不是一个完整的代码,而且它做的错误检查很少。我正在使用 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 个字节的 block ,因此 AES_BLOCK_SIZE 定义为 16。 此外,我的 ENCRYPT_BLOCK_SIZE 设置为 8。我基本上是在复制我在 MSDN 上找到的示例,并针对 AES256 进行调整并用于内存而不是文件。 但是在我的 while 循环中,每当它到达缓冲区的末尾时,FINAL 设置为 TRUE,CryptEncrypt 就会失败。我尝试了很多不同的方法来做到这一点,但总是失败。 是因为最后的缓冲区小于 16bytes 吗? 有人能帮忙吗,在加密方面我完全是菜鸟。 谢谢 编辑:GetLastError 返回:0x000000ea

最佳答案

您收到错误 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 你仍然需要一个完整的填充 block 。这是因为您始终需要执行填充,否则反填充算法无法将您的纯文本与填充字节区分开来。

当然,您也可以简单地创建一个 plain_size_bytes + AES_BLOCK_SIZE 的缓冲区,并使用 pdwDataLen 值来获取实际长度。

编辑:如果您分别加密每个纯文本 block ,并且密码使用带填充的 CBC 或 ECB,那么由于上述原因,最后一个纯文本 block 可能需要 2 个完整的 block

关于c++ - CryptEncrypt AES 256 在加密最后一个 block 时失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9091108/

相关文章:

c++ - 默认定义声明的不完整冗长

c++ - 类模板特化的前向声明

c - 如何通过中断ctrl+c关闭主线程之前的所有线程?

encryption - System.Security.Cryptography 可以添加到 Microsoft Access 中吗

c++ - 意外异常

c++ - 如果所包含的对象也继承,如何定义相互继承的容器? (以QObject为基础)

c++ - 在 Win32 C++ 中调用未导出的函数

c++ - 将 int 21h 与内联汇编一起使用

javascript - Curve25519 的 JavaScript 实现?

c# - SQL Server密码的保存方法