Реализация защиты API-ключей в мобильном приложении

TRUETECH занимается разработкой, поддержкой и обслуживанием мобильных приложений iOS, Android, PWA. Имеем большой опыт и экспертизу для публикации мобильных приложений в популярные маркеты Google Play, App Store, Amazon, AppGallery и другие.
Разработка и поддержка любых видов мобильных приложений:
Информационные и развлекательные мобильные приложения
Новостные приложения, игры, справочники, онлайн-каталоги, погодные, фитнес и здоровье, туристические, образовательные, социальные сети и мессенджеры, квиз, блоги и подкасты, форумы, агрегаторы
Мобильные приложения электронной коммерции
Интернет-магазины, B2B-приложения, маркетплейсы, онлайн-обменники, кэшбэк-сервисы, биржи, дропшиппинг-платформы, программы лояльности, доставка еды и товаров, платежные системы
Мобильные приложения для управления бизнес-процессами
CRM-системы, ERP-системы, управление проектами, инструменты для команды продаж, учет финансов, управление производством, логистика и доставка, управление персоналом, системы мониторинга данных
Мобильные приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, платформы предоставления электронных услуг, платформы кешбека, видеохостинги, тематические порталы, платформы онлайн-бронирования и записи, платформы онлайн-торговли

Это лишь некоторые из типы мобильных приложений, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента.

Предлагаемые услуги
Показано 1 из 1 услугВсе 1735 услуг
Реализация защиты API-ключей в мобильном приложении
Средняя
~2-3 рабочих дня
Часто задаваемые вопросы
Наши компетенции:
Этапы разработки
Последние работы
  • image_mobile-applications_feedme_467_0.webp
    Разработка мобильного приложения для компании FEEDME
    756
  • image_mobile-applications_xoomer_471_0.webp
    Разработка мобильного приложения для компании XOOMER
    624
  • image_mobile-applications_rhl_428_0.webp
    Разработка мобильного приложения для компании RHL
    1052
  • image_mobile-applications_zippy_411_0.webp
    Разработка мобильного приложения для компании ZIPPY
    947
  • image_mobile-applications_affhome_429_0.webp
    Разработка мобильного приложения для компании Affhome
    862
  • image_mobile-applications_flavors_409_0.webp
    Разработка мобильного приложения для компании FLAVORS
    445

Реализация защиты API-ключей в мобильном приложении

strings app.apk | grep -i "key\|secret\|token" — первые 10 строк вывода уже дают что-то интересное в большинстве приложений без защиты. Google Maps API Key в AndroidManifest.xml, Firebase API Key в google-services.json, Stripe Publishable Key в коде — всё это читается из распакованного APK без единой строчки реверс-инжиниринга.

Почему нельзя хранить ключи в коде

Любой ключ в строковых ресурсах, константах классов или конфигурационных файлах приложения — публичный ключ. APK и IPA декомпилируются. Даже обфускация только усложняет поиск, но не делает его невозможным.

Частый аргумент: «Firebase API Key публичный, его можно засветить». Технически верно для apiKey в Firebase конфиге — он нужен только для идентификации проекта, а доступ контролируется Firebase Rules. Но Google Maps API Key, Stripe Secret Key, ключи к собственному бэкенду — другая история. Утечка Maps Key означает чужие запросы за ваш счёт.

Правильное хранение секретов на устройстве

Если ключ всё же должен быть на устройстве (например, после аутентификации сервер выдаёт токен) — только Keychain (iOS) или Android Keystore.

На Android:

val keyStore = KeyStore.getInstance("AndroidKeyStore")
keyStore.load(null)
// создаём ключ шифрования привязанный к KeyStore
val keyGen = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore")
keyGen.init(
    KeyGenParameterSpec.Builder("my_key_alias",
        KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT)
        .setBlockModes(KeyProperties.BLOCK_MODE_GCM)
        .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
        .build()
)
// шифруем токен, сохраняем зашифрованный blob в EncryptedSharedPreferences

EncryptedSharedPreferences из androidx.security:security-crypto — удобная обёртка, которая делает это под капотом. Под неё не нужно писать руками KeyStore код.

На iOS Keychain Services через SecItemAdd / SecItemCopyMatching. В Swift удобно через KeychainAccess или SwiftKeychainWrapper. Атрибут kSecAttrAccessible = kSecAttrAccessibleWhenUnlockedThisDeviceOnly — данные доступны только когда устройство разблокировано, не мигрируют при резервном копировании iCloud.

Ключи, которых не должно быть на клиенте

API ключи к внешним сервисам (платёжные шлюзы, SMS-провайдеры, AI API) — на сервере. Точка. Клиент делает запрос к своему бэкенду, бэкенд делает запрос к Stripe/Twilio/OpenAI со своим ключом. Клиент никогда не узнаёт этот ключ.

Паттерн для ключей с ограниченным использованием: клиент аутентифицируется, сервер выдаёт короткоживущий токен (JWT или HMAC-подписанный nonce) с конкретными permissions. Клиент использует этот токен для прямых запросов к сервису (например, загрузки файла напрямую в S3 через presigned URL). Основной ключ — никогда не покидает сервер.

NDK и нативное хранение

Если строка должна быть в приложении и нельзя запрашивать её с сервера — нативный код. JNI функция возвращает ключ, собранный из нескольких частей:

JNIEXPORT jstring JNICALL
Java_com_example_NativeKeys_getApiKey(JNIEnv *env, jobject obj) {
    // ключ разбит, части в разных местах
    const char part1[] = {0x41, 0x42, 0x43, 0x00};
    const char part2[] = {0x44, 0x45, 0x46, 0x00};
    // собираем + XOR расшифровка
    // ...
}

Это security through obscurity, не настоящая защита. Но нативный код сложнее хукать автоматическими инструментами, и порог атаки растёт.

Build-time защита

local.properties — файл вне репозитория, хранит переменные для сборки:

MAPS_API_KEY=AIzaSy...

В build.gradle:

manifestPlaceholders = [mapsApiKey: properties["MAPS_API_KEY"] ?: ""]

В AndroidManifest:

<meta-data android:name="com.google.android.geo.API_KEY" android:value="${mapsApiKey}"/>

Ключ не попадает в репозиторий, но попадает в APK — всё равно читается из манифеста. Для Maps Key это приемлемо с правильными ограничениями в Google Cloud Console (restrict by Android app package name + SHA-1). Для Secret Keys — нет.

Срок реализации полной схемы: аудит текущего положения ключей, миграция в Keystore/Keychain, вынос серверных ключей на бэкенд, настройка ограничений в Google Cloud/App Store Connect — 2–3 дня.