Хабрахабр

Безопасность со вкусом Google

Так как я интересуюсь безопасностью мобильных приложений, то в первую очередь обратил внимание на новую библиотеку в семействе JetPack — security-crypto. Отгремел Google I/O 2019 и пришла пора переписывать проекты на новую архитектуру изучать новинки. Библиотека помогает правильно организовывать шифрование данных и при этом ограждает разработчиков от всех нюансов, которые сопровождают этот процесс.

Историческая справка

Какой алгоритм выбрать? Шифрование данных в Android всегда порождало много дискуссий. Что такое padding? Какой режим шифрования использовать? Для обычного разработчика изучать всё это и поддерживать знания в актуальном состоянии может быть трудно. Где хранить ключи? Поэтому история чаще всего заканчивалась одним из трех сценариев:

  • копипаст первого попавшегося решения со stackoverflow
  • поиск «подходящего мануала» с последующей имплементацией и сбором граблей
  • активация протокола «И так сойдет!»

Качество этих решений было очень разным: из всего этого многообразия я могу выделить только java-aes-crypto, которую мы и использовали в Redmadrobot. По мере развития сообщества android-разработчиков начали появляться библиотеки, помогающие решать эту задачу. Довольно качественная имплементация, но с ней была пара проблем.

Само по себе это не плохо, но ведь эти строки нужно где-то хранить, в БД или SharedPreferences. Во-первых, это было просто шифрование строк. Но это код, который нужно поддерживать, таскать из проекта в проект или оформлять в библиотеку для удобства использования. А значит, нужно писать обертку над источником данных, чтобы все шифровалось на лету (что мы когда-то и делали). В конечном итоге это тоже было сделано, но это не принесло успокоения пытливым умам.

Их можно было сгенерить, но вот хранение полностью ложилось на плечи разработчика. Во-вторых, это решение ничего не предлагало для решения проблемы управления ключами. Со всеми приседаниями вокруг AndroidKeystore на разных версиях ОС и устройствах, пришедших с Mainland China.

Этому городу нужен новый герой

Она достаточно проста в освоении и ограждает разработчика от огромного количества нюансов, касающихся криптографии. Все шло своим чередом, пока летом 2018-го я не обнаружил, что есть такая замечательная библиотека от Google как Tink. Более того, Tink полностью берет на себя управление ключами и абстрагирует все операции с AndroidKeystore от разработчика. Используя эту библиотеку, практически невозможно сделать что-то неправильно.

И тут очень удачно подвернулась Binary Preferences — библиотека от отечественного производителя, на которую давно хотелось посмотреть. Но это все еще было просто шифрование строк. Она позволяет шифровать все сохраняемые данные любых алгоритмов — для этого было достаточно написать реализацию двух интерфейсов, KeyEncryption и ValueEncryption (для ключей и значений соответственно).

В итоге мы стали применять две этих библиотеки в связке и были счастливы, что наш код стал чище и проще для понимания.

security-crypto

Была анонсирована еще одна JetPack библиотека, которая призвана с этим помочь. Теперь Google в очередной раз решил пойти навстречу разработчикам и упростить их жизнь в области шифрования сохраняемых данных. Нашел только javadoc-и по входящим в состав библиотеки классам, но и на том спасибо. Мне стало интересно, что же они такого революционного там написали, и я полез искать документацию (спойлер: ее нет). Оказалось, что возможностей там негусто: шифрование файлов, SharedPreferences и работа с ключами.

Для проверки работоспособности библиотеки написал пару снипетов:

Шифрование файлов

val file = File(filesDir, "super_secure_file")
val encryptedFile = EncryptedFile.Builder(file, this, "my_secret_key", EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB) .setKeysetAlias("my_test_keyset_alias") .setKeysetPrefName("keyset_pref_file") .build() val outputStream = encryptedFile.openFileOutput() outputStream.use { it.write("secret info".toByteArray())
}

Шифрование SharedPreferences

val encryptedPreferences = EncryptedSharedPreferences.create( "super_secret_preferences", "prefrences_master_key", this, EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV, EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
) encryptedPreferences.edit().putString("secret", "super secret token")

Провалившись в исходники, я увидел, что это фактически обертка вокруг уже известной нам библиотеки Tink, а написанный код почти один в один как мы написали для шифрованных BinaryPreferences. К моему великому удивлению, все заработало с первого раза, и я полез смотреть, что за код они написали для этой библиотеки.

Будем надеяться, что пришедший в JetPack пакет security не ограничится только этой библиотекой, а будет развиваться дальше. Меня очень обрадовало, что Google в этот раз не стал изобретать веломопед, а использовал свои же хорошо зарекомендовавшие себя наработки.

Демонстрация работы связки BinaryPreferences + Tink
Исходный код библиотеки security-crypto
Демонстрация работы security-crypto

Показать больше

Похожие публикации

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»