Что отличает libgcrypt при вызове шифра aes128 с 256-битным ключом?

Это продолжение моего предыдущего вопроса (расшифровки RSA).

Изменить. Ответ ниже был четким и кратким. Ниже я добавил пример кода, который помог мне проверить, что, по моему мнению, происходит. Сегодня протестирую и отпишусь. Клиентское приложение создает 256-битный ключ, но когда оно вызывает gcry_cipher_setkey, оно использует длину ключа, возвращенную алгоритмом. Итак, я предполагаю, что setkey усекает 256-битный ключ до 128-битного. Достаточно легко проверить.

Я пытаюсь расшифровать файл, зашифрованный с помощью libgcrypt с помощью aes128/cbc/no padding. Есть два разных приложения, которые выполняют шифрование, над каждым из которых я не контролирую. Один использует 128-битный ключ AES, а другой использует 256-битный ключ. В остальном все внутренние вызовы одинаковы.

Изменить: Вот код псевдошифрования: Изменить 2: Исправлен порядок и добавлены комментарии для будущих пользователей:

#define AES_KEY_SIZE 32
char AESKey[AES_KEY_SIZE+1];
GenerateAESKey(AESKey);

Error = gcry_cipher_open(AesHandle, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CBC, 0);
// this is always 128bits (16 bytes)
BlockLength = gcry_cipher_get_algo_blklen(GCRY_CIPHER_AES128);
// this should return 128bits (16 bytes)
KeyLength = gcry_cipher_get_algo_keylen(GCRY_CIPHER_AES128);
Error = gcry_cipher_setiv(AesHandle, NULL, 0);
// AESKey is a 32byte (256bit) char array & KeyLength is 128bits (16bytes)
// so gcry_cipher_setkey only uses the first 'KeLength' bytes of 'AESKey'
// which in this case is the first 16 bytes of 'AESKey'
Error = gcry_cipher_setkey(*AesHandle, AESKey, KeyLength);
Error = gcry_cipher_encrypt(AesHandle, Encrypted, BlockLength, ToEncrypt, BlockLenth);


void GenerateAESKey( char * AESKey ) {
    int i;

    srand(time(NULL));
    for ( i = 0; i < AES_KEY_SIZE; i++ ) {
        AESKey[i] = (rand() % 93)+33;
    }
    AESKey[AES_KEY_SIZE] = '\0';
}

Итак, в моем коде C# я делаю это до того, как начну расшифровывать:

var aesKey = DecryptAesKey(s);
if (aesKey.Length == 32)
{
   var tempKey = new byte[16];
   Buffer.BlockCopy(aesKey,0,tempKey,0,16);
   aesKey = tempKey;
}

Я использую С# и bouncycastle для расшифровки файлов. Я успешно расшифровываю файлы, зашифрованные с помощью 128-битного ключа. Но сбой, когда ключ 256 бит. Ошибка означает, что вывод искажен.

Я убедился, что ключ AES правильно расшифровывается для обоих источников.

Мой вопрос: что делает Libgrypt по-другому, когда ключ 256 бит? Или это даже правильный путь, чтобы выяснить, почему моя расшифровка не работает? Спасибо за любую информацию или направление, в котором вы можете мне указать.

Брайан


person TheBrian    schedule 17.07.2013    source источник


Ответы (1)


Я предполагаю, что у вас есть

  1. 2 разных ключа (128 и 256 бит)
  2. 2 разных источника зашифрованного текста (1: AES128 2: AES256 Оба: CBC/No Padding)
  3. Может расшифровать 128 зашифрованных текстов
  4. Сбой с 256 (все искажено и ничего из открытого текста не расшифровано).

Основное отличие заключается в длине ключа: 128 или 256 бит. Он указывает количество повторений раундов преобразования, которые преобразуют ввод. Вам, вероятно, никогда не понадобятся детали внутренней реализации. AES использует больше раундов с большими ключами. 10 для 128-битных ключей, 14 для 256-битных ключей.

Важная часть заключается в том, что Размер блока всегда равен 128 битам для 128 и 256 CBC AES.

И AES-128-CBC, и AES-256-CBC используют 128-битный IV.

Итак, мое дикое предположение (не видя вашего кода AES256) заключается в том, что где-то в вашем коде AES256 может быть ошибка в размере блока или IV.

Если вы просто установили ключ для 128AES с помощью этой функции, проверьте это документы

 gcry_error_t gcry_cipher_setkey (gcry_cipher_hd_t h, const void *k, size_t l)

Длина l (в байтах) ключа k должна соответствовать требуемой длине набора алгоритмов для данного контекста или находиться в допустимом диапазоне для алгоритмов с переменным размером ключа. Функция проверяет это и возвращает ошибку, если есть проблема. Вызывающий всегда должен проверять наличие ошибки.

И обычно вы не хотите использовать CBC с NoPadding (если размер ваших данных всегда кратен 16 байтам), но проблемы с заполнением искажают только последний 16-байтовый блок открытого текста.

person varren    schedule 18.07.2013
comment
Спасибо @varren за ваш ответ! gcry_error_t gcry_cipher_setkey (gcry_cipher_hd_t h, const void *k, size_t l) был вызван, где l = 16, а k был 32-байтовым массивом. Таким образом, setkey будет использовать только первые «l» байтов «k». Проверено в моем коде C#, используя только первые 16 байт 32-байтового ключа для расшифровки с большим успехом. Еще раз спасибо! - person TheBrian; 18.07.2013