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



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


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


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


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

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


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


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


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


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


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


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


    security-crypto



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


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


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

    Redmadrobot
    127,23
    №1 в разработке цифровых решений для бизнеса
    Поделиться публикацией

    Комментарии 11

      0
      for Android 6.0+
      Google в очередной раз решил пойти навстречу разработчикам и упростить их жизнь

      Что-то не сходится…
        0

        @minSdkVersion больше года назад твитнул про 21. На 21+22 в сумме сидит меньше 15% юзеров, неизвестно, сколько из них ещё платежеспособных(читай — целевая аудитория). Так что 23 не за горами. А в новых проектах и вовсе уже кое у кого стоит. А если это старый Легаси проект, то там джетапак не спасет: либо там нету нужды использовать security пакет, либо он давным давно самописан, о чем и пишет автор.

          0
          Это всё хорошо, но 15% юзеров мало кому захочется терять. Возможно, даже зря, могли бы подстегнуть юзеров перейти на новые аппараты, но вою в поддержке будет очень много.
          Недавно мы перешли с 16 на 21, и уже есть пара недовольных юзеров.
        +1
        в моём проекте minsdk по прежнему 16, ибо до сих пор пользователи есть. Поэтому жаль что в этот раз Google прокинул пользователей старых девайсов
          0
          Когда дело касается вопросов безопасности, отказ от поддержки старых устройств — вполне логичный шаг. На 16 api сидит 1.2% пользователей, усложнять ради них библиотеку было бы нелогично.
            0
            я в первую очередь смотрю на количество пользователей своего приложения. Когда на 4.1 — 4.4 сидят по меньшей мере 400 клиентов, то вряд ли компания будет от них отказываться ради улучшения комфорта разработчиков
              0
              Зависит от. Потому что если запиливание нормальной безопасности с учетом всех костылей под ранние версии (если вообще получится качественно), обойдется в эдак +50 часов работы не самого дешевого специалиста, а дохода эти 400 клиентов приносят минимум (на 4.1 вряд ли самая платежеспособная аудитория сидит) то нужно считать.
              А ведь кроме безопасности еще какие нибудь аспекты всплывут заставляющие под старые версии костылить.
                0
                50+ часов это очень оптимистичная оценка. Особенно если речь идет о проекте, которому уже 3-4 года.
                  0
                  Ну я исхожу из предположений что это не очень большое приложение и не нужно городить защиту как в форт ноксе. Впрочем да, эти факторы так же можно обозвать как «зависит от»)
                –1
                Речь не о комфорте разработчиков, а о безопасности тех самых 400 клиентов. Ну и о репутационных потерях компании если что-то пойдет не так.
                  0
                  менеджмент решил что вероятные проблемы с безопасностью на старых версиях андроид — проблемы самих пользователей, которые возможно осознают что пользуются старой ОС. А альтернатива библиотеке из статьи — всякие securepreferences libraries, которых тонны на github-e. Ну и про 50+ часов вы загнули. Максимум 2-3 дня

          Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

          Самое читаемое