На недавнем вебинаре по TLS 1.3 была вскользь затронута одна неочевидная тема – вопрос выбора самой быстрой хэш-функции для работы TLS.
В самом деле, если подходить с “бытовой логикой”, основанной на наблюдаемой ситуации, логичным будет то, что чем длиннее в битах вывод функции, и чем она безопаснее, тем она дольше считается и больше нагружает процессор.
3DES безопаснее DES, “длиннее в битах” и дольше считается. SHA-1 безопаснее MD5, “длиннее в битах” и дольше считается. RC4-128 безопаснее RC2-40, “длиннее в битах” и… ну, этот пример можно считать исключением.
Логика подсказывает, что уж в пределах-то одного семейства алгоритмов разные варианты будут точно подпадать под эту систему, и “укороченный в плане бит” будет точно быстрее, чем “полный”.
Почему это не так?
Конструкция SHA-2
Семейство хэшей SHA-2 распадается на два подотряда – 32х битовых (SHA-224 и SHA-256) и 64х битовых (SHA-384, SHA-512, SHA-512/224, SHA-512/256) реализаций алгоритма SHA-2.
По сути, во всём семействе действует единообразный алгоритм работы, но в 32м подотряде работа идёт с 8 блоками по 32 бита, а в 64м, соответственно, с 8 блоками по 64 бита. Ну и раундов у 32х битового варианта будет 64, а у 64х битового – 80.
В результате можно говорить о том, что по сути есть всего 2 варианта алгоритмов SHA-2 – SHA-256 и SHA-512; остальные 4 варианта представляют из себя урезанные.
- SHA-224 – считаем обычный SHA-256, получаем 8 блоков по 32 бита, отбрасываем последний;
- SHA-384 – считаем обычный SHA-512, получаем 8 блоков по 64 бита, отбрасываем два последних;
- SHA-512/n – считаем обычный SHA-512, получаем 8 блоков по 64 бита, отбрасываем 512-n бит;
Важный вывод состоит в том, что все “урезанные” варианты считаются столько же времени, сколько и основные.
Поэтому логика “SHA-384 быстрее SHA-512, ведь надо покороче результат получить” – не работает.
Соответственно, имеет смысл сравнивать скорость только у “основных” вариантов – SHA-256 и SHA-512.
Сравниваем SHA-256 и SHA-512
Какой же из алгоритмов быстрее?
Тестовый прогон openssl speed sha256 sha512
показывает следующие результаты:
The 'numbers' are in 1000s of bytes per second processed.
type 16 bytes 64 bytes 256 bytes 1024 bytes 8192 bytes
sha256 27723.28k 60914.92k 103861.68k 124598.95k 131405.14k
sha512 21696.03k 87499.07k 129071.79k 180596.05k 202170.37k
Хорошо заметно, что чем больше данных подпадает под вычисления, тем более заметно преимущество SHA-512.
Можно прикинуть, к какому именно соотношению результатов стремится этот ряд.
SHA-512 будет тратить на четверть больше раундов (80 против 64), чем SHA-256. Но каждый раунд у SHA-512 обрабатывает 64 битовые операнды, а у SHA-256 – 32х битовые. Удвоенное КПД по операндам в сочетании с гарантированной потерей четверти скорости на дополнительных раундах даст 2 / (5/4) = 1.6 раз преимущества. Безусловно, это прикидка и будут дополнительные затраты в плане доступа к памяти, использования шины и так далее – но можно говорить о том, что SHA-512 на рабочих объёмах данных (в нашем варианте применения, в TLS, это будут отдельные пакеты данных, примерно по 1.5 килобайта) будет примерно в 1.5 раза быстрее, чем SHA-256.
Аппаратное ускорение SHA-2/256
Во второй половине 2016 года фирма Intel представила микроархитектуру Goldmont, в которой реализованы заявленные в 2013 году Intel SHA extensions. По сути это аппаратная реализация инструкций, ускоряющих выполнение SHA-1 и SHA-2/256. Процессоры, поддерживающие эту технологию, относятся к семейству Intel Apollo Lake и в основном представляют собой low-end встраиваемые решения, поэтому говорить о какой-то оптимизации под данный сценарий нет смысла. Кроме того, нет качественных результатов тестирования, которое показало бы значительное увеличение быстродействия при вычислении SHA-1 и SHA-2/256 на данных платформах – равно как и не то что серверных, а даже нормальных десктопных процессоров с поддержкой этого функционала.
Поэтому аппаратное ускорение по сути есть с 2016 года – только на весьма специфической и небольшой процессорной линейке. Из-за этого предпочитать SHA-2/256 нет никакого смысла.
Выводы
Если в cipher suites ставить варианты с SHA-512 и SHA-384 перед SHA-256, то загрузка процессора на обработку данных будет снижаться. SHA-256 будет выгоднее только в случае “32х битовый сервер с 32х битовым клиентом” – данный сценарий сейчас можно считать исчезающей экзотикой. Да, клиенты с 32х битовыми процессорами и 32х битовым ПО ещё могут встречаться – но обычно со стороны клиента CPU и так практически не загружен, поэтому разница не будет заметна. А вот со стороны прокси-сервера, который терминирует TLS-сессии и отдаёт из кэша данные, безусловно, вопрос загрузки CPU будет актуален всегда.
Учитывайте такие тонкости – из них состоит различие реально продуманной системы от “вроде поднял, вроде работает”.