Android Keystore — криптографический провайдер, который генерирует и хранит ключи шифрования в изолированной среде выполнения (TEE), недоступной даже для операционной системы. По данным AOSP Security Documentation (2025), Keystore используется более чем в 80% Android-приложений из топ-100 Google Play для защиты токенов и шифрования данных. Понимание Android Keystore критически важно для безопасного хранения ключей на Android.
Главное
Android Keystore — системный компонент платформы Android, который предоставляет API для генерации, хранения и использования криптографических ключей в защищённой среде. В отличие от программных криптографических библиотек (Bouncy Castle, Conscrypt), Keystore гарантирует, что приватные ключи никогда не покидают изолированную область выполнения.
Keystore появился в Android 4.3 (API 18) как программный провайдер с поддержкой RSA. Начиная с Android 6.0 (API 23), Keystore получил аппаратную поддержку через Keymaster Hardware Abstraction Layer (HAL), которая делегирует криптографические операции Trusted Execution Environment (TEE) на совместимых устройствах. По данным Android Compatibility Definition Document (2025), все устройства с Android 9+ обязаны поддерживать аппаратный Keystore через TEE или StrongBox.
Ключи в Keystore идентифицируются по псевдониму (alias) — строке, которая передаётся при создании или загрузке ключа. Keystore не позволяет получить сырой материал ключа: методы getEncoded() возвращают null для ключей, созданных в Keystore. Это фундаментальное отличие от программных ключей — злоумышленник не может извлечь приватный ключ даже при полном контроле над устройством.
Keystore интегрирован с другими механизмами безопасности Android: биометрической аутентификацией (BiometricPrompt), шифрованием на уровне файлов (File-Based Encryption) и verification-функциями SafetyNet / Play Integrity. Ключи могут быть настроены на автоматическое удаление при определённых условиях: при снятии код-пароля, при добавлении нового отпечатка пальца или по истечении срока.
Архитектура Android Keystore включает три уровня реализации, отличающихся степенью аппаратной защиты. Уровень зависит от возможностей аппаратного обеспечения устройства.
TEE (Trusted Execution Environment) — изолированная область, работающая параллельно с основной ОС на том же процессоре. TEE использует ARM TrustZone технологию, которая разделяет физическое ядро процессора на два виртуальных: Normal World (Android) и Secure World (TEE). Код в Secure World имеет доступ к памяти и периферии, недоступным из Normal World.
Когда приложение вызывает криптографическую операцию через Keystore, запрос передаётся через Keymaster HAL в TEE, где операция выполняется аппаратно. Результат возвращается в приложение, но приватный ключ остаётся в защищённой памяти TEE. TEE сертифицирован на соответствие GlobalPlatform TEE Protection Profile и является обязательным требованием для Android 9+ на устройствах с процессорами, поддерживающими TrustZone.
TEE поддерживает алгоритмы AES/GCM (128, 256 бит), RSA (2048, 4096 бит), EC (P-256, P-384, P-521) и HMAC-SHA256. Производительность TEE ниже, чем программной криптографии (на 20–40%), но для типовых операций (подпись JWT, расшифровка ключа сессии) задержка не превышает 10–50 мс.
StrongBox — выделенный чип безопасности, физически отдельный от основного процессора. В отличие от TEE, который разделяет процессорное время с Android, StrongBox имеет собственный CPU, оперативную память, True Random Number Generator (TRNG) и защищённое хранилище (One-Time Programmable memory). StrongBox сертифицирован на Common Criteria EAL 4+ и Secure IC Protection Profile.
StrongBox доступен на устройствах с Android 9+ при условии наличия соответствующего чипа (например, Titan M на Google Pixel, Knox на Samsung Galaxy). Разработчик включает StrongBox через флаг setIsStrongBoxBacked(true) в KeyGenParameterSpec. При отсутствии аппаратной поддержки флаг игнорируется, и Keystore переключается на TEE.
Ограничения StrongBox: поддерживает ограниченный набор алгоритмов (AES-256, EC P-256, HMAC-SHA256), очередь операций — не более одной одновременно, количество операций — ограничено ресурсами чипа. StrongBox не предназначен для высоконагруженных сценариев — используйте TEE для частых операций и StrongBox только для критических ключей (мастер-ключи шифрования, ключи подписи).
Software-based Keystore — программная реализация, использующаяся на устройствах без аппаратной поддержки TEE или StrongBox. Ключи хранятся в зашифрованном виде в файловой системе, но приватный ключ может быть временно расшифрован в оперативной памяти. Программный Keystore менее безопасен — злоумышленник с root-доступом может перехватить ключ в памяти.
Начиная с Android 12 (API 31), Google требует аппаратной поддержки Keystore для всех новых устройств. Устройства с Android 9–11 могут иметь программный Keystore на бюджетных моделях. Разработчик может проверить уровень защиты через KeyStore.getKeyCharacteristics() — атрибут SECURITY_LEVEL_TRUSTED_ENVIRONMENT или SECURITY_LEVEL_STRONGBOX подтверждает аппаратную защиту.
Android Keystore поддерживает широкий набор криптографических алгоритмов, разделённых на категории в зависимости от типа ключа. Выбор алгоритма влияет на производительность, совместимость и уровень безопасности.
AES (Advanced Encryption Standard) — симметричное шифрование для защиты данных на устройстве. Рекомендуемый режим: AES/GCM/NoPadding (256 бит). GCM обеспечивает аутентифицированное шифрование (AEAD) — проверку целостности зашифрованных данных. Размер IV (Initialization Vector): 12 байт для GCM. Не используйте AES/ECB — он не обеспечивает должной защиты.
RSA (Rivest–Shamir–Adleman) — асимметричное шифрование для защиты ключей сессии и цифровой подписи. Рекомендуемый размер: 2048 или 4096 бит. Режимы: RSA/ECB/PKCS1Padding (шифрование) и RSA/ECB/PKCS1Sign (подпись). RSA 1024 считается устаревшим и не рекомендуется для новых приложений (NIST SP 800-131A Rev. 2).
EC (Elliptic Curve) — асимметричная криптография на эллиптических кривых для подписи и обмена ключами. Поддерживаемые кривые: secp256r1 (P-256, обязательная), secp384r1 (P-384) и secp521r1 (P-521). EC обеспечивает сравнимую с RSA безопасность при значительно меньшем размере ключа. P-256 рекомендуется для большинства сценариев: он поддерживается всеми устройствами и обеспечивает 128-битный уровень безопасности.
HMAC (Hash-based Message Authentication Code) — симметричная аутентификация сообщений. Поддерживаемые хеш-функции: SHA-256, SHA-384, SHA-512. HMAC используется для проверки целостности и аутентичности данных, например, для верификации webhook-запросов или проверки целостности конфигурации.
Все алгоритмы могут быть привязаны к биометрической аутентификации через KeyGenParameterSpec.Builder.setUserAuthenticationRequired(true). На Android 11+ доступен флаг setUserAuthenticationParameters() с указанием таймаута (в секундах), в течение которого ключ доступен после биометрической аутентификации, без повторного запроса.
Рассмотрим практические примеры работы с Android Keystore на Kotlin: генерация ключа AES, шифрование данных и создание асимметричной пары для подписи.
Пример создаёт 256-битный AES/GCM ключ с привязкой к биометрической аутентификации. Ключ недоступен для экспорта через getEncoded().
import android.security.keystore.KeyGenParameterSpec
import android.security.keystore.KeyProperties
import java.security.KeyStore
private val keyStore = KeyStore.getInstance("AndroidKeyStore").apply { load(null) }
fun generateAesKey(alias: String) {
val spec = KeyGenParameterSpec.Builder(
alias,
KeyProperties.PURPOSE_ENCRYPT or
KeyProperties.PURPOSE_DECRYPT
)
.setKeySize(256)
.setBlockModes(KeyProperties.KEY_BLOCK_MODE_GCM)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
.setUserAuthenticationRequired(true)
.setInvalidatedByBiometricEnrollment(true)
.build()
val generator = KeyGenerator.getInstance(
KeyProperties.KEY_ALGORITHM_AES,
"AndroidKeyStore"
)
generator.init(spec)
generator.generateKey()
}
Пример шифрует данные с использованием ключа из Android Keystore. Cipher получает ключ по алиасу, инициализирует AES/GCM шифрование и возвращает зашифрованные данные вместе с IV.
fun encryptData(alias: String, plaintext: ByteArray): ByteArray {
val cipher = Cipher.getInstance("AES/GCM/NoPadding")
val secretKey = keyStore.getKey(alias, null) as SecretKey
cipher.init(Cipher.ENCRYPT_MODE, secretKey)
val iv = cipher.getIV()
val encrypted = cipher.doFinal(plaintext)
// IV + криптирани данни
return iv + encrypted
}
fun decryptData(alias: String, ciphertextWithIv: ByteArray): ByteArray {
val iv = ciphertextWithIv.copyOfRange(0, 12)
val encrypted = ciphertextWithIv.copyOfRange(12, ciphertextWithIv.size)
val cipher = Cipher.getInstance("AES/GCM/NoPadding")
val secretKey = keyStore.getKey(alias, null) as SecretKey
val spec = GCMParameterSpec(128, iv)
cipher.init(Cipher.DECRYPT_MODE, secretKey, spec)
return cipher.doFinal(encrypted)
}
Пример создаёт пару RSA-2048 ключей в Keystore с привязкой к StrongBox. Приватный ключ используется для подписи, публичный — может быть экспортирован через getEncoded().
fun generateRsaKeyPair(alias: String) {
val spec = KeyGenParameterSpec.Builder(
alias,
KeyProperties.PURPOSE_SIGN or
KeyProperties.PURPOSE_VERIFY
)
.setKeySize(2048)
.setSignaturePaddings(
KeyProperties.SIGNATURE_PADDING_RSA_PKCS1
)
.setDigests(KeyProperties.DIGEST_SHA256)
.setIsStrongBoxBacked(true)
.build()
val pair = KeyPairGenerator.getInstance(
KeyProperties.KEY_ALGORITHM_RSA,
"AndroidKeyStore"
).apply { init(spec) }
.generateKeyPair()
// Публичният ключ може да бъде експортиран
val publicKey = pair.public // X509EncodedKeySpec
}
Эффективное использование Android Keystore требует соблюдения правил, которые обеспечивают максимальную защиту при сохранении производительности.
Используйте KeyGenParameterSpec с минимально необходимыми параметрами: указывайте только те purpose, block modes и paddings, которые реально используются. Избыточные параметры (например, PURPOSE_ENCRYPT для ключа, который используется только для подписи) создают лишние векторы атаки. Android рекомендует явно указывать digest для подписи — SHA256 минимальный допустимый уровень (SHA1 устарел).
Привязывайте ключи к биометрии для критических операций: setUserAuthenticationRequired(true) гарантирует, что ключ можно использовать только после биометрической аутентификации. На Android 11+ используйте setUserAuthenticationParameters() с таймаутом (рекомендуется 30–60 секунд), чтобы не запрашивать биометрию на каждую операцию в рамках одной сессии. setInvalidatedByBiometricEnrollment(true) автоматически удаляет ключ при добавлении нового отпечатка или лица — это предотвращает доступ по старым биометрическим данным.
Проверяйте уровень безопасности на этапе инициализации: используйте KeyStore.getKeyCharacteristics() для определения SECURITY_LEVEL. Если устройство поддерживает только программный Keystore (SECURITY_LEVEL_SOFTWARE), примите решение: либо отказаться от функционала, либо использовать дополнительное шифрование (например, обёртку ключа через пароль пользователя). Не полагайтесь на StrongBox, если он не гарантирован — всегда указывайте флаг setIsStrongBoxBacked(true) и проверяйте результат через getKeyCharacteristics.
Обновляйте ключи по расписанию: криптографические ключи имеют рекомендованный срок жизни. NIST SP 800-57 рекомендует менять AES ключи каждые 1–2 года, RSA/EC пары — каждые 2–3 года. Реализуйте механизм ротации ключей: при запуске приложения проверяйте дату создания ключа (KeyGenParameterSpec.Builder.setKeyValidityStart/End) и генерируйте новый ключ при истечении срока. Старые данные, зашифрованные старым ключом, должны быть расшифрованы и перезашифрованы новым.
Не используйте Keystore для больших данных: Keystore предназначен для хранения ключей (несколько сотен байт), а не для шифрования больших файлов. Для шифрования данных используйте схему: сгенерируйте случайный AES ключ (DEK — Data Encryption Key), зашифруйте данные этим ключом, а DEK зашифруйте Keystore-ключом (KEK — Key Encryption Key). Android EncryptedSharedPreferences использует именно эту схему: мастер-ключ в Keystore, данные — AES-256 GCM.
Часто задаваемые вопросы
Нет, Android Keystore спроектирован так, чтобы приватный ключ никогда не покидал TEE или StrongBox. Метод getEncoded() возвращает null для ключей, созданных в Keystore. Ключ можно использовать только через Cipher, Signature или Mac API — сырой материал недоступен.
TEE (TrustZone) — виртуальная изоляция на том же процессоре, использует разделение по времени. StrongBox — отдельный чип с собственным CPU и памятью. StrongBox безопаснее (Common Criteria EAL 4+), но медленнее и поддерживает меньше алгоритмов. TEE подходит для частых операций, StrongBox — для критических ключей.
Используйте KeyStore.getKeyCharacteristics() после генерации ключа с флагом setIsStrongBoxBacked(true). Атрибут SECURITY_LEVEL_STRONGBOX подтверждает аппаратную поддержку. Если устройство не поддерживает StrongBox, Keystore переключается на TEE без ошибки — необходимо явно проверять уровень безопасности.
Ключи в Keystore удаляются автоматически при удалении приложения с устройства. На Android 10+ ключи могут сохраняться, если приложение имеет флаг allowBackup=true в манифесте, но они будут недоступны после переустановки. Рекомендуется генерировать ключи заново при чистой установке.
Нет, Android Keystore привязан к аппаратному обеспечению конкретного устройства. Ключ, сгенерированный в TEE одного устройства, невозможно передать на другое. Для кроссплатформенного шифрования используйте схему: Keystore защищает ключ на устройстве, а ключи сессии передаются через защищённый API с использованием асимметричного шифрования.
Итоги
Ще разработим мобилно приложение под ключ
IT Sectr създава iOS и Android приложения за стартъпи и бизнеси от 2017 г. Ще ви консултираме и ще предложим най-доброто решение.
Прочетете също