крайняя разница во времени между AES-CBC + HMAC и AES-GCM

Итак, я искал повсюду различные реализации AES для CBC и GCM, я не хочу реализовывать это самостоятельно на случай, если я сделаю ошибки, поэтому я нашел следующие коды AES CBC и проверил их скорость на моем RX63NB (Тестовая доска Реннеса).

                    Encrypt                 Decrypt 
                    bytes   speed (us)      bytes   speed (us)
Tiny AES            64      1500            64      8900
                    128     2880            128     17820
aes-byte-29-08-08   64      1250            64      4900
                    128     1220            128     9740
Cyclone             64      230             64      237
                    128     375             128     387

Я был удивлен тем, насколько быстрее был Cyclone. Чтобы уточнить, я взял файлы AES, CBC и Endian из CycloneSSL и использовал только те.

Затем я попробовал GCM из CycloneSSl, и вот результат:

                    Encrypt                 Decrypt 
                    bytes   speed μs        bytes   speed μs
Cyclone   GCM       64      9340            64      9340
                    128     14900           128     14900

Я проверил время HMAC (от CycloneSSL), чтобы узнать, сколько это займет:

HMAC        bytes   speed μs
Sha1        64      746
            128     857
Sha224      64      918
            128     1066
Sha256      64      918
            128     1066
Sha384      64      2395
            128     2840
Sha512      64      2400
            128     2840
Sha512_224  64      2390
            128     2835
Sha512_356  64      2390
            128     2835
MD5         64      308
            128     345
Whirlpool   64      5630
            128     6420
Tiger       64      832
            128     952

Самый медленный из них - водоворот.

если вы добавите время шифрования cbc для 128 байтов к hmac Whirlpool со 128 байтами, вы получите 6795 мкс, что примерно вдвое меньше времени GCM.

теперь я могу понять, что GHASH занимает немного больше времени, чем HMAC, из-за поля galios и тому подобного, но в 2 раза медленнее по сравнению с самым медленным алгоритмом HASH, который я знаю, безумие.

Итак, я начал задаваться вопросом, сделал ли я что-то не так, или реализация CycloneSLL gcm просто показалась. к сожалению, я не нашел другой простой в использовании реализации GCM в c, чтобы сравнить ее.

Весь использованный мной код можно найти на pastebin, разные файлы разделены знаком -------- ------------

Это код, который я использую для шифрования с помощью GCM:

static void test_encrypt(void)
{
  uint8_t key[] = { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c };
  uint8_t iv[]  = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
  uint8_t in[]  = { 0x48, 0x61, 0x6c, 0x6c, 0x6f, 0x20, 0x68, 0x6f, 0x65, 0x20, 0x67, 0x61, 0x61, 0x74, 0x20, 0x68,
                    0x65, 0x74, 0x20, 0x6d, 0x65, 0x74, 0x20, 0x6a, 0x6f, 0x75, 0x20, 0x76, 0x61, 0x6e, 0x64, 0x61,
                    0x61, 0x67, 0x2c, 0x20, 0x6d, 0x65, 0x74, 0x20, 0x6d, 0x69, 0x6a, 0x20, 0x67, 0x61, 0x61, 0x74,
                    0x20, 0x68, 0x65, 0x74, 0x20, 0x67, 0x6f, 0x65, 0x64, 0x20, 0x68, 0x6f, 0x6f, 0x72, 0x2e, 0x21,
                    0x48, 0x61, 0x6c, 0x6c, 0x6f, 0x20, 0x68, 0x6f, 0x65, 0x20, 0x67, 0x61, 0x61, 0x74, 0x20, 0x68,
                    0x65, 0x74, 0x20, 0x6d, 0x65, 0x74, 0x20, 0x6a, 0x6f, 0x75, 0x20, 0x76, 0x61, 0x6e, 0x64, 0x61,
                    0x61, 0x67, 0x2c, 0x20, 0x6d, 0x65, 0x74, 0x20, 0x6d, 0x69, 0x6a, 0x20, 0x67, 0x61, 0x61, 0x74,
                    0x20, 0x68, 0x65, 0x74, 0x20, 0x67, 0x6f, 0x65, 0x64, 0x20, 0x68, 0x6f, 0x6f, 0x72, 0x2e, 0x21};

  AesContext context;
  aesInit(&context, key, 16 ); // 16 byte = 128 bit      
  error_crypto_t error = gcmEncrypt(AES_CIPHER_ALGO, &context, iv, 16, 0, 0, in, in, 128, key, 16);
}

static void test_decrypt(void)
{
  uint8_t key[] = { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c };
  uint8_t tag[] = { 0x56, 0x56, 0x5C, 0xCD, 0x5C, 0x57, 0x36, 0x66, 0x73, 0xF7, 0xFF, 0x2A, 0x17, 0x49, 0x0E, 0xC4};
  uint8_t iv[]  = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
  uint8_t out[] = { 0x05, 0x7C, 0x51, 0xFF, 0xE4, 0x9F, 0x8C, 0x90, 0xF1, 0x7D, 0x56, 0xFB, 0x87, 0xB9, 0x44, 0x79,
                    0xB1, 0x04, 0x32, 0x39, 0x78, 0xFF, 0x51, 0x60, 0x48, 0x0B, 0x21, 0x77, 0xF2, 0x26, 0x0B, 0x94,
                    0x7B, 0xA7, 0x26, 0x74, 0x87, 0xA8, 0x2C, 0x5A, 0xA1, 0x19, 0x03, 0x17, 0x66, 0x3A, 0x46, 0x9F,
                    0xE6, 0x1D, 0x3B, 0x65, 0xFD, 0xC0, 0xBA, 0xC0, 0xD9, 0x45, 0xE7, 0x17, 0x74, 0x0F, 0xB7, 0x4B,
                    0x0F, 0xF0, 0x16, 0xF6, 0xE8, 0x4F, 0xFD, 0x96, 0x64, 0x5E, 0xDB, 0x9E, 0x3A, 0x0B, 0x93, 0x8F,
                    0x87, 0x83, 0x90, 0xF8, 0xF9, 0xE6, 0xA3, 0xE7, 0x5E, 0x72, 0x3C, 0xB5, 0x98, 0x54, 0x11, 0xD7,
                    0xB4, 0x7C, 0xFF, 0xA3, 0x51, 0x1A, 0xB0, 0x69, 0x4F, 0x57, 0xBB, 0x83, 0x40, 0x2A, 0xE6, 0x75,
                    0x8B, 0xB5, 0xCA, 0xA4, 0x84, 0x82, 0x1D, 0xA8, 0x94, 0x03, 0x77, 0x9C, 0x3B, 0xF8, 0xA0, 0x60};

  AesContext context;
  aesInit(&context, key, 16 ); // 16 byte = 128 bit
  error_crypto_t error = gcmDecrypt(AES_CIPHER_ALGO, &context, iv, 16, 0, 0, out, out, 128, tag, 16);
}

данные в out [] - это зашифрованные gcm данные из in [], и все они работают правильно. (правильно расшифровывает и проходит аутентификацию.

Вопрос

  • Все ли реализации GCM такие медленные?
  • Есть ли другие (лучшие) реализации GCM?
  • Стоит ли мне просто использовать HMAC, если мне нужно быстрое шифрование + проверка?

ИЗМЕНИТЬ

Мне удалось заставить работать метод GCM из mbedTLS (PolarSSL), что примерно в 11 раз быстрее, чем циклон (требуется 880 мкс для шифрования / дешифрования 128 байт). и он дает тот же результат, что и Cylcone GCM, поэтому я уверен, что он работает правильно.

gcm_context gcm_ctx;
gcm_init(&gcm_ctx, POLARSSL_CIPHER_ID_AES,key, 128);
int error = gcm_auth_decrypt(&gcm_ctx, 128,iv, 16, NULL, 0, tag, 16, out, buffer );

person Vincent    schedule 19.03.2015    source источник
comment
Справедливо ли предположение, что это может быть связано с параллельными возможностями (или их отсутствием) вашей платы? en.wikipedia.org/wiki/Galois/Counter_Mode#Performance   -  person Henrik    schedule 25.03.2015


Ответы (1)


Ваши числа кажутся нечетными, 128 байт для aes-byte-29-08-08 занимает меньше времени, чем 64 байта для шифрования?

Предполагая, что RX63N сравним с Cortex-M (они оба 32-битные, без векторной единицы, и сложно найти информацию о RX63N):

Заявленный тест для SharkSSL показывает CBC чуть более чем в два раза быстрее, чем GCM, 2.6, если оптимизировать по скорости. 9340 намного больше 340.

Тест Cifra показывает 10-кратную разницу между их AES и AES-GCM, хотя тест GCM также включал auth -данные. Все еще далеко от вашей разницы между прямым AES и GCM.

В относительном выражении, отвечая на вопрос 1, я не думаю, что все реализации GCM настолько медленны по сравнению с обычным AES.

Что касается других реализаций GCM, есть вышеупомянутая Cifra (хотя я не слышал о ней до сих пор, и у нее всего 3 звезды на GitHub (если это что-то значит), поэтому уровень проверки, вероятно, будет довольно низким) , и, возможно, вы сможете извлечь реализацию AES-GCM из FreeBSD . Я не могу говорить о производительности в абсолютном выражении на вашей платформе.

HMAC, вероятно, будет быстрее на платформах без аппаратной поддержки, такой как поддержка AES-NI (CLMUL), независимо от реализации. Насколько это критично для производительности? Вам нужно использовать AES или блочный шифр? Возможно, ChaCha20 + Poly1305 лучше соответствует вашим потребностям в производительности (см. Показатели производительности от Cifra). Сейчас это используется в OpenSSH - chacha. * И poly1305. *

Помните об атаках по побочным каналам. Программные реализации AES могут быть чувствительны к атакам по времени кэширования, хотя я не думаю, что это применимо к микроконтроллерам, где все в любом случае находится в SRAM.

* Salsa20 является предшественником ChaCha20.

person jhnphm    schedule 27.03.2015
comment
Я тестировал код Cifra, но это занимает 300+ мс для 128 байт, так что на rx63n это определенно не быстро. Я попытался получить исходный код sharkSSL, но могу загружать только файлы .exe. нет настоящего кода, так что это облом. - person Vincent; 27.03.2015
comment
CBC занимает 250 мс для кода cifra. разница в скорости по сравнению с cycloneSSL огромна. видимо потому, что cifra сделана для других контроллеров. Мне нужно использовать AES, мы могли бы сделать начальную часть с AES, а затем переключиться на более быстрый потоковый шифр, но AES является обязательным, и, глядя, насколько быстро он работает в режиме cbc, я думаю, это не будет проблемой. Я просто хочу, чтобы мы могли сделать GCM, HMAC sha256 все еще меньше 1 мс, что достаточно быстро, я просто не могу понять, почему GCM занимает так много времени. - person Vincent; 27.03.2015
comment
1/3 секунды всего для 128 байт - это смешно, и на несколько порядков больше всего остального. 300 мс * 100 МГц (максимальная частота для вашего микроконтроллера) составляет 234375 циклов на байт, или 3 750 000 циклов на блок, что в 750 (!) Раз больше циклов на байт, чем опубликованные числа. Это действительно маловероятная разница, и то, что она сделана для других микроконтроллеров, не объясняет этого, поскольку разница на байт для этого, вероятно, меньше 10. В любом случае это общая реализация C, поэтому на самом деле она ни для чего не оптимизирована. Определенно происходит что-то еще. - person jhnphm; 27.03.2015
comment
Есть ли способ напрямую получить количество циклов из регистров вместо значений времени? Возможно, тактовая частота настраивается неправильно? - person jhnphm; 27.03.2015
comment
Для сравнения, процессор настольного ПК может выполнять 12 циклов AES на байт для оптимизированной реализации сборки. Цифры, приведенные для Cifra на Cortex M, составляют 193 цикла на байт (277 с планированием), что составляет 19-кратную разницу, намного меньше, чем 750. Это два совершенно разных процессора, и настольный компьютер гораздо более способен быть суперскалярным. порядка, а разница за такт всего 19x - person jhnphm; 27.03.2015
comment
тесты настольных компьютеров: bench.cr.yp.to/results-stream.html (игнорируйте тесты HW + AES, которые используют AES-NI) - AES CTR должен быть сопоставим со скоростью CBC, если только сообщение не разбивается и не вычисляется параллельный поток ключей (также преимущество GCM), но это распараллеливание неприменимо к микроконтроллерам . - person jhnphm; 27.03.2015