Баг
После подключения gema я задейсвовал его функциональность в новой фиче и, просто на всякий случай, написал пару тестов для него — для расшифровки с правильным паролем и для ошибки расшифровки с неверным паролем. Во втором тесте я просто заменил первую букву пароля при расшифровке. Я рассчитывал получить ошибку расшифровки, что являлось бы в данном случае корректно пройденным тестом. И… мой тест провалился! Я не только не получил ошибку декодирования, я даже получил верно расшифрованные данные неверным паролем! Ну ничего себе! Возможно, я случайно попал на тот самый редчайший, один на миллиарды, случай, когда мне подошел и другой пароль? Что-то типа коллизии хэш-функций или вроде того. Следующей попыткой я изменил уже два символа в пароле: И опять-таки получил успешно расшифрованное сообщение! Ну, оставалось лишь одно. Я попробовал совершенно другой пароль: Это уже выглядело кричащей дырой в безопасности, так что я решил разобраться, что же здесь происходит.
Отладка
Проблема возникала из-за следующей строки в коде gema: Прежде всего давайте объясним, что делает unpack. В данном случае она разделяет входную строку на массив из 32 строк (см. ): Далее, для каждой из полученных строк вызывается метод #hex. в Ruby конвертирует строки, содержащие hex-числа в целые числа (а если конвертация не удаётся, то в число 0). Таким образом, любая строка, не содержащая в себе корректное hex-число, будет трансформирована в массив из 32 нулей. То есть мы практически всегда можем расшифровать любое зашифрованное сообщение любым паролем. Я думаю, автор подразумевал, что входным параметром функции шифрования всегда будет hex-число (и в этом случае gem сработал бы надёжно). Однако интерфейс gem'а не предполагает никаких ошибок при шифровании с обычной строкой, что приводит к ложному ощущению надёжности шифрования при его полном фактическом отсутствии.
Выводы
aes — не очень распространённый gem. На момент написания статьи у него на GitHub'е вcего 45 звёзд и 13 форков. Но проблема в том, что Google выдаёт его первым результатом по запросам «aes gem» или «ruby aes gem», а мы часто верим в то, что топовые результаты поисковых запросов ведут на качественные и популярные библиотеки. Часто программисты вообще не задумываются над проверкой и написанием тестов для подключаемых в проект внешних библиотек. Как вы видите из этого примера — такое поведение несёт в себе опасность.
Технические детали:
— Gem:
— Версия с данной ошибкой: 0.5.0 / 12c3648