AES CBC+HMAC и GCM сравнителни показатели за Golang

АКТУАЛИЗИРАН (30.06.2019 г.).

Моля, прочетете актуализираната публикация тук.

Резултатите в тази публикация не са правилни поради начина, по който интерпретирах резултата от бенчмарка на golang, моля, прочетете актуализираната публикация.

Преглед

Освен коректността, ефективността на криптирането е много важен фактор за всяко приложение, което изисква защитени данни. Това минава от мениджъри на пароли (като моя собствен pkhub.io) до уеб сървъри, използващи Https, микро услуги със защитена комуникация (всичко https/tls, gRPC), проксита, обратни проксита, dbs с криптиране на диска и т.н. .

Колкото повече време на процесора е изразходвано за криптиране или декриптиране, толкова по-бавна е услугата ви и толкова повече сървъри имате нужда. За някои програми, като просто изтегляне на файл от s3, никакъв хардуер няма да направи изтеглянето на файла по-бързо, вижте този проблем³.

Go е много гореща тема в наши дни и особено ако пишете микро услуги (или просто софтуер) в Kubernetes. Затова реших да разгледам производителността на AES криптиране на Go, използвайки JCE на Java като моя базова линия.

Резултати от сравнителен анализ

Изпълних тези показатели на моя Macbook Pro 2018, „go версия go1.12.5 darwin/amd64“. А кодът може да бъде намерен тук⁵.

Ако сравните тези резултати с Java², те са доста ниски и изненадващо Java може да направи 40–50K (и GCM › 70K) op/s. Мисля, че основният проблем (и не мога да намеря сигурни препратки към това) е, че Go не прилага AES-NI¹.

Ако сравните non AES-NI⁴, числата изглеждат по-добри за Go AES CBC-HMAC, но за AES GCM, който трябва да е по-бърз, пак е ужасен. Това става още по-лошо, като се има предвид, че всички примери за криптиране на Go, които мога да намеря в мрежата, винаги сочат към използването на AES GCM. Не можах да намеря никакви ресурси, сочещи към AES CBC-HMAC, което е друг срам, защото AES-CBC и HMAC винаги трябва да се използват заедно и с лошото GCM представяне на Go е по-ефективна алтернатива (отново, imho: това е изненадващо, защото GCM трябва да е по-бързо).

Резюме

Харесвам Go за много неща. Сред тях са бързите времена за стартиране и ниските режийни разходи. Очаквах наистина добри числа за тези сравнителни резултати. За съжаление ефективността на криптиране на Go не е това, което трябва да бъде.

Въпреки това, множество услуги се разработват в Go и те използват криптиране пряко или непряко (напр. gRPC⁶ използва http²⁷, който в повечето случаи използва TLS⁸). Тези услуги работят чудесно и хората са доволни.

Алтернатива е да използвате Go без TLS и sidecar с производително прокси за обработка на TLS или други изисквания за криптиране, но това просто изглежда противоречи на фокуса, ориентиран към сигурността на Go досега.

Така че съветът е: Използвайте Go, но използвайте друга платформа/език за криптиране? :(

Бих се радвал екипът на Go наистина да направи високоефективна AES реализация, която използва AES-NI (или други хардуерни оптимизации), когато е налице. Това би било от полза за всички във и извън екосистемата Go. Особено като се има предвид, че много услуги и проксита като Kubernetes и Traefik са написани на Go и тяхната производителност със сигурност не е това, което може да бъде в мащаб, поради бавната крипто производителност на Go.

Препратки

[1] https://www.intel.com/content/www/us/en/architecture-and-technology/advanced-encryption-standard-aes/data-protection-aes-general-technology.html

[2] https://medium.com/@gerritjvv/aes-java-encryption-performance-benchmarks-3c2cb19a40e9?source=friends_link&sk=37a8cebe0b14c03db759e0d31874e74e

[3] https://github.com/goamz/goamz/issues/81

[4] https://github.com/gerritjvv/crypto/tree/master/crypto-perf

[5] https://github.com/gerritjvv/crypto/tree/master/crypto2

[6] https://github.com/grpc/grpc-go

[7] https://httpwg.org/specs/rfc7540.html

[8] https://github.com/containous/traefik/issues/2139