CryptEncrypt AES 256 не удается зашифровать последний блок - PullRequest
3 голосов
/ 01 февраля 2012

Прежде всего, я прошу прощения, если я что-то здесь упускаю.Это моя первая попытка использования Windows CryptAPI, и, хотя я прошел через Google, 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

Ответы [ 3 ]

4 голосов
/ 02 февраля 2012

Вы получаете ошибку ERROR_MORE_DATA. Что переводится как:

Если буфер, выделенный для pbData, недостаточно велик для хранения зашифрованных данных, GetLastError возвращает ERROR_MORE_DATA и сохраняет требуемый размер буфера в байтах в значении DWORD, на которое указывает pdwDataLen.

Если в этом методе используется шифрование CBC (Microsoft считает, что в их API-интерфейсе не указан алгоритм ИЛИ заполнения режима), то для вычисления размера буфера вывода должен быть выполнен следующий алгоритм:

buffer_size = (plain_size_bytes / AES_BLOCK_SIZE + 1) * AES_BLOCK_SIZE;

Другими словами, если plain_size_bytes равен N * AES_BLOCK_SIZE, вам все еще нужен полный блок заполнения. Это потому, что вам всегда нужно выполнять заполнение, иначе алгоритм удаления не сможет отличить обычный текст от байтов заполнения.

Конечно, вы также можете просто создать буфер из plain_size_bytes + AES_BLOCK_SIZE и использовать значение pdwDataLen для получения фактической длины.

РЕДАКТИРОВАТЬ: если вы шифруете каждый простой текстовый блок отдельно, а шифр использует CBC или ECB с заполнением, то последний простой блок может потребовать 2 целых блока из-за выше

1 голос
/ 01 февраля 2012
while ( address < (address + len) )

Мой загадочный ответ: «Подумай об этом - ты не будешь думать об этом вечно, но ...»

0 голосов
/ 01 февраля 2012
if ( (len - dwCount) < dwBlockLen) EOB = TRUE;

может быть что-то вроде

if ( (len - dwCount) < dwBlockLen)
{
    EOB = TRUE;
    dwBlockLen = ENCRYPT_BLOCK_SIZE;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...