Keystore (Android): що це, архітектура та принципи роботи

Автор: IT Sectr Опубліковано: 2026-03-14 Час читання: 10 хв

Android Keystore — це системний механізм Android для безпечного зберігання криптографічних ключів в апаратній ізоляції. Система використовує Trusted Execution Environment (TEE) на пристроях з ARM TrustZone або виділений Secure Element для захисту ключів на рівні чипа. Згідно з Android Open Source Project, Keystore підтримує алгоритми RSA, EC, AES та HMAC з генерацією ключів безпосередньо в захищеному середовищі.

Головне

  • Android Keystore — провайдер KeyStore, що ізолює криптографічні ключі від простору користувача Android
  • Ключі генеруються всередині TEE або Secure Element і ніколи не залишають захищене середовище у відкритому вигляді
  • Android 9+ додає KeyGenParameterSpec.Builder з параметрами: purpose, digest, padding, userAuthenticationRequired
  • Біометричний захист ключів вимагає підтвердження користувача через BiometricPrompt перед кожною операцією
  • Keymaster HAL — апаратний рівень абстракції, що реалізує криптографічні операції в TEE або Secure Element

Що таке Android Keystore?

Android Keystore — це криптографічний провайдер, реалізований в Android починаючи з API 1 (Android 1.0), але повноцінна апаратна підтримка з'явилася з Android 4.3 (API 18). Keystore вирішує задачу безпечного зберігання закритих ключів таким чином, щоб навіть при компрометації операційної системи зловмисник не міг витягти ключі у відкритому вигляді.

Архітектура KeyStore на Android

Архітектура Android Keystore складається з трьох рівнів: прикладний API (java.security.KeyStore), системний сервіс (keystore daemon) та апаратний рівень (Keymaster HAL). Додаток звертається через стандартний API Java Cryptography Architecture (JCA), а системний сервіс маршрутизує запити до Keymaster, що працює в TEE.

Всі криптографічні операції з ключами (підпис, розшифрування) виконуються всередині TEE або Secure Element. Ключі ніколи не залишають захищене середовище — додаток отримує тільки хендл (псевдонім) для звернення до ключа. Це фундаментальна відмінність від програмних KeyStore, де ключі потенційно доступні в пам'яті процесу.

Відмінність від Java KeyStore

Стандартний JKS (Java KeyStore) або BKS (Bouncy Castle) зберігають ключі у файлах, захищених паролем. Android Keystore зберігає ключі в апаратній ізоляції, де вони захищені навіть від root-користувача. JKS вразливий при прямому доступі до файлової системи, Android Keystore — ні.

Інша відмінність: в Android Keystore ключі мають строгі параметри використання (purpose — тільки sign/verify/encrypt/decrypt), що задаються при генерації. Їх не можна змінити згодом, що запобігає неправильному використанню ключа.

Як працює Android Keystore?

При створенні нового ключа додаток викликає KeyPairGenerator або KeyGenerator з KeyGenParameterSpec, який містить всі параметри майбутнього ключа. Система передає запит до Keymaster HAL, який генерує ключ всередині TEE і повертає хендл.

Процес генерації ключа

Метод KeyGenParameterSpec.Builder приймає обов'язкові параметри: ім'я ключа в Keystore, призначення (PURPOSE_SIGN, PURPOSE_ENCRYPT), алгоритм (RSA, EC, AES). Додатково: digest (SHA-256), padding (PKCS7), userAuthenticationRequired (біометрія), keyValidityStart/End (часові обмеження).

Після завдання параметрів KeyPairGenerator.generateKeyPair() повертає KeyPair, де PrivateKey — це об'єкт, що делегує операції Keymaster. Відкритий ключ може бути витягнутий, закритий — ні. Він існує тільки всередині TEE.

kotlin
import java.security.KeyPairGenerator
import android.security.keystore.KeyGenParameterSpec
import android.security.keystore.KeyProperties

fun generateKey(alias: String) {
    val spec = KeyGenParameterSpec.Builder(alias,
        KeyProperties.PURPOSE_SIGN or KeyProperties.PURPOSE_VERIFY
    ).setDigests(KeyProperties.DIGEST_SHA256)
     .setSignaturePaddings(KeyProperties.SIGN_PADDING_RSA_PKCS1)
     .setUserAuthenticationRequired(true)
     .build()

    val kpGen = KeyPairGenerator.getInstance(
        KeyProperties.KEY_ALGORITHM_RSA,
        "AndroidKeyStore"
    )
    kpGen.initialize(spec)
    kpGen.generateKeyPair()
}

Підписання та верифікація

Signature для ECDSA або RSA-PSS створюється через стандартний API: Signature.getInstance(algorithm).initSign(privateKey). Операція підписання виконується в TEE: додаток передає дані, Keymaster підписує їх апаратно і повертає підпис. Ключ і дані не змішуються в спільній пам'яті.

Для біометричного захисту необхідно перед підписанням автентифікувати користувача через BiometricPrompt. Без успішної автентифікації Keymaster не виконує операцію, повертаючи CryptoAuthenticationException.

kotlin
import java.security.KeyStore
import java.security.Signature
import androidx.biometric.BiometricPrompt

fun signWithBiometric(alias: String) {
    val ks = KeyStore.getInstance("AndroidKeyStore")
    ks.load(null)
    val entry = ks.getEntry(alias, null) as KeyStore.PrivateKeyEntry
    val signature = Signature.getInstance("SHA256withRSA")
    signature.initSign(entry.privateKey)
    // BiometricPrompt з CryptoObject(signature) запитує FaceID/PIN
}

Типи сховищ KeyStore

Android підтримує два режими зберігання ключів: програмний (на пристроях без TEE) та апаратний (на пристроях з TEE або Secure Element). Режим залежить від можливостей SoC та версії Android.

Програмний KeyStore (software-only)

На пристроях без Trusted Execution Environment (до Android 4.3 або бюджетні SoC) ключі зберігаються в зашифрованому вигляді з використанням майстер-ключа, отриманого з паролю екрану блокування. Цей режим менш безпечний — ключі доступні в пам'яті процесу при виконанні криптографічних операцій.

Рівень захисту заснований на шифруванні файлу KeyStore за допомогою AES-256-GCM. Ключ шифрування генерується на основі паролю користувача або PIN-коду через Scrypt (PBKDF2 з великою кількістю ітерацій).

Апаратний KeyMaster (TEE/Secure Element)

На сучасних пристроях використовується Keymaster 4.x в TEE (ARM TrustZone). Ключі генеруються, зберігаються та використовуються виключно всередині TrustZone. Навіть ядро Linux не має доступу до закритих ключів — тільки Keymaster HAL може виконувати операції.

Secure Element (наприклад, eSE в Samsung Knox або StrongBox в Google Pixel 3+) — це окремий чіп з власним процесором та пам'яттю. Він сертифікований Common Criteria EAL 4+ та забезпечує максимальний рівень захисту, включаючи захист від фізичного розкриття.

ТипМісце зберіганняРівень захистуДоступно з API
SoftwareФайл /data/misc/keystoreСередній (AES-256)API 1+
Keymaster 3TEE (TrustZone)ВисокийAPI 23+
Keymaster 4TEE + Secure I/OДуже високийAPI 28+
StrongBoxАпаратний Secure ElementМаксимальнийAPI 28+, опціонально

Робота з KeyStore API

Android Keystore інтегрований в Java Cryptography Architecture (JCA). Для доступу до провайдера використовується стандартний KeyStore.getInstance("AndroidKeyStore"). API доступний починаючи з API 18.

Створення та завантаження KeyStore

Метод KeyStore.load(null) завантажує контейнер KeyStore поточного додатка. Пароль не потрібен — Android використовує контекст додатка та його UID для розмежування доступу. Кожен додаток бачить тільки свої записи, якщо не використовується shared UID.

Методи setEntry та getEntry працюють з KeyStore.PrivateKeyEntry, SecretKeyEntry або TrustedCertificateEntry. Параметр ProtectionParameter — завжди null для Android Keystore (захист реалізований на рівні системи).

kotlin
import java.security.KeyStore
import java.security.cert.Certificate
import android.security.keystore.KeyProtection

fun storeSecretKey(alias: String, key: SecretKey) {
    val ks = KeyStore.getInstance("AndroidKeyStore")
    ks.load(null)
    val prot = KeyProtection.Builder(
        KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT
    ).setBlockModes(KeyProperties.BLOCK_MODE_GCM)
     .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
     .setUserAuthenticationRequired(true)
     .build()
    ks.setEntry(alias, KeyStore.SecretKeyEntry(key), prot)
}

Перевірка типу сховища

За допомогою KeyCharacteristics можна визначити, в якому середовищі зберігається ключ: програмному KeyStore, TEE або StrongBox. Метод getKeyCharacteristics() повертає набір флагів: FLAG_HARDWARE (keymaster), FLAG_SECURE_ELEMENT (StrongBox), FLAG_TRUSTED_USER_PRESENCE_REQUIRED (біометрія).

Алгоритми та безпека

Android Keystore підтримує широкий набір криптографічних алгоритмів, розділений на три категорії: асиметричні, симетричні та MAC. Підтримка конкретних алгоритмів залежить від версії Keymaster HAL.

Підтримувані алгоритми

RSA (1024–4096 біт) — для підпису (PKCS1, PSS) та шифрування (OAEP, PKCS1). EC (P-224, P-256, P-384, P-521) — для ECDSA-підпису та ECDH-узгодження. AES (128, 256 біт) — для симетричного шифрування в режимах CBC, CTR, GCM. HMAC (SHA1, SHA256, SHA512) — для автентифікації повідомлень.

Для кожного ключа задається setPurposes, що обмежує можливі операції. Ключ RSA з PURPOSE_SIGN не може бути використаний для шифрування, навіть якщо у зловмисника є доступ до API. Це key usage enforcement на апаратному рівні.

Захист від компрометації

Keymaster включає лічильник невдалих спроб біометричної автентифікації. Після заданої кількості невдач (налаштовується через setInvalidatedByBiometricEnrollment) ключ стає недоступним і вимагає видалення/перегенерації. При видаленні всіх біометричних шаблонів всі ключі з userAuthenticationRequired=true автоматично інвалідуються.

Також підтримується Key Attestation (Android 8.1+): за запитом додатка Keymaster підписує сертифікат з інформацією про характеристики ключа (апаратний/програмний, алгоритм, призначення). Сервер може перевірити цей сертифікат для підтвердження того, що ключ створений в надійному середовищі.

Часті запитання

Яка різниця між Android Keystore та KeyStore в Java?

Java KeyStore зберігає ключі у файлі, захищеному паролем (JKS, BKS). Android Keystore використовує апаратну ізоляцію TEE або Secure Element. Java KeyStore вразливий при root-доступі, Android Keystore — ні, оскільки закриті ключі ніколи не залишають захищене середовище.

Чи можна імпортувати існуючий ключ в Android Keystore?

Так, через KeyStore.setEntry з KeyProtection. Однак імпортований ключ не матиме апаратного захисту — він зберігатиметься в програмному Keystore, зашифрований майстер-ключем. Для максимальної безпеки завжди генеруйте ключі всередині Keystore.

Як перевірити, чи підтримує пристрій апаратний KeyStore?

Використовуйте KeyChain.isBoundKeyAlgorithm або перевірте KeyCharacteristics після генерації ключа. Наявність FLAG_HARDWARE в характеристиках означає, що ключ створено в TEE. Також можна перевірити android.security.keystore.isHardwareBacked().

Що відбувається з ключами при видаленні додатка?

При видаленні додатка Android видаляє всі його ключі з Keystore. Дані необоротно втрачаються. При повторній установці додаток повинен згенерувати нові ключі. Резервне копіювання ключів через TEE неможливе з архітектурних причин.

Як KeyStore захищає від атак через налагодження?

На заблокованому пристрої Keymaster не виконує жодних операцій. Ключі з userAuthenticationRequired=true вимагають біометричного підтвердження кожного разу. Навіть з root-доступом зловмисник не може викликати Keymaster безпосередньо — тільки через Android Keystore service.

Підсумки

  • Android Keystore — криптографічний провайдер JCA з апаратною ізоляцією ключів через TEE або Secure Element
  • Ключі генеруються всередині TrustZone і ніколи не залишають захищене середовище у відкритому вигляді
  • KeyGenParameterSpec задає параметри ключа: purpose, digest, padding, userAuthenticationRequired, keyValidity
  • Keymaster HAL реалізує три рівні: програмний (software), TEE (Keymaster 3/4) та StrongBox (апаратний Secure Element)
  • Біометричний захист ключів забезпечується setUserAuthenticationRequired та BiometricPrompt з CryptoObject
  • Key Attestation (API 28+) дозволяє перевірити на сервері, що ключ створений в апаратному середовищі
  • Використовуйте Android Keystore для зберігання закритих ключів підпису, шифрування та автентифікації в Android-додатках

Ми розробимо мобільний застосунок під ключ

IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.

Обговорити проект

Читайте також