KeyStore (Android): ключові поняття, API та робота криптографічного сховища

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

KeyStore (Android) — це реалізація криптографічного провайдера Java Cryptography Architecture (JCA), інтегрована в Android для безпечного зберігання ключів з можливістю апаратної ізоляції. З Android 4.3 (API 18) KeyStore підтримує апаратні ключі через Keymaster HAL, а починаючи з Android 9 (API 28) — StrongBox Keymaster для ключів у виділеному Secure Element. Згідно з Документацією безпеки Android, провайдер «AndroidKeyStore» замінює стандартні Bouncy Castle або OpenSSL KeyStore, надаючи системний захист від несанкціонованого вилучення ключів.

Головне

  • Android KeyStore — JCA-провайдер для зберігання ключів з підтримкою TEE, StrongBox та біометричного захисту
  • KeyGenParameterSpec задає алгоритм, призначення, digest, padding та біометрію при створенні ключа
  • Keymaster HAL реалізує апаратні криптографічні операції на рівнях Software, TEE та StrongBox
  • Key Attestation (API 28+) дозволяє серверу перевірити, що ключ створено в апаратному середовищі Android KeyStore
  • Аліас ключа — рядок, за яким застосунок звертається до ключа в Keystore; один аліас відповідає одному ключу

Що таке KeyStore в Android?

KeyStore в Android — це не окремий застосунок або файл, а криптографічний провайдер, що реалізує інтерфейс java.security.KeyStore. Він надає єдиний API для зберігання та використання закритих ключів, симетричних ключів і сертифікатів довірених центрів (CA). Провайдер реєструється під іменем «AndroidKeyStore» і доступний через стандартний KeyStore.getInstance().

Еволюція Android KeyStore

До Android 4.3 криптографічні операції виконувалися програмно через Bouncy Castle. З Android 4.3 з'явився Keymaster HAL 1.0, що дозволив використовувати TEE на ARM TrustZone. Android 6.0 (API 23) додав Keymaster 2.0 з підтримкою апаратної автентифікації за відбитком пальця. Android 9 (API 28) представив Keymaster 4.0 та StrongBox Keymaster для виділеного Secure Element.

Кожна версія Keymaster додає нові можливості та покращує ізоляцію ключів. Сучасні пристрої (2022+) зобов'язані підтримувати Keymaster 4.0 для сертифікації Google Mobile Services, що гарантує наявність TEE для всіх Android-застосунків.

Архітектура та компоненти

Android KeyStore складається з трьох рівнів: Java API (KeyStore, KeyPairGenerator), системний процес keystore (C++, працює як system service) та Keymaster HAL (бібліотека в TEE або Secure Element). Застосунок викликає API, keystore-сервіс маршрутизує запит до Keymaster, операція виконується в захищеному середовищі.

Всі закриті ключі зберігаються в TEE і не можуть бути прочитані з простору користувача. Навіть системний keystore-сервіс не має доступу до raw-ключів — тільки до хендлів, що вказують на ключі всередині Keymaster.

Як працює KeyStore як криптопровайдер?

Android KeyStore реалізує стандартний інтерфейс постачальника послуг JCA. Коли застосунок викликає Cipher.getInstance(“RSA/ECB/PKCS1Padding”, “AndroidKeyStore”), Android Security Provider делегує операцію Keymaster через ланцюжок: Java → JNI → keystore service → Keymaster HAL.

Реєстрація провайдера

Провайдер AndroidKeyStore реєструється автоматично при запуску процесу. Його пріоритет вищий, ніж у Bouncy Castle або Conscrypt. Тому при виклику KeyStore.getInstance() без зазначення провайдера в більшості випадків повертається AndroidKeyStore. Для явного виклику використовуйте KeyStore.getInstance(“AndroidKeyStore”).

Кожен Android-застосунок має ізольований контейнер в KeyStore. Застосунки з однаковим UID (shared userId) можуть мати спільний доступ до певних ключів, але стандартна установка гарантує, що застосунок A не може прочитати ключі застосунку B.

Методи KeyStore та їх особливості

load(null) — ініціалізація KeyStore. Параметр завжди null для AndroidKeyStore. setEntry — збереження ключа із зазначенням KeyProtection (purposes, digest, padding). getEntry — отримання KeyStore.PrivateKeyEntry, SecretKeyEntry або TrustedCertificateEntry. containsAlias — перевірка існування ключа. deleteEntry — видалення ключа (безповоротно).

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

object KeyStoreManager {
    private val keyStore by lazy {
        KeyStore.getInstance("AndroidKeyStore").apply { load(null) }
    }

    fun createRsaKey(alias: String) {
        val spec = KeyGenParameterSpec.Builder(alias,
            KeyProperties.PURPOSE_SIGN or KeyProperties.PURPOSE_VERIFY
        ).setKeySize(2048)
         .setDigests(KeyProperties.DIGEST_SHA256)
         .setSignaturePaddings(KeyProperties.SIGN_PADDING_RSA_PKCS1)
         .build()

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

Підтримувані алгоритми та типи ключів

Android KeyStore підтримує широкий набір криптографічних алгоритмів, який варіюється залежно від версії Keymaster HAL на пристрої. Розробник може отримати список підтримуваних алгоритмів через KeyGenParameterSpec.Builder при спробі генерації — несумісні параметри викликають InvalidAlgorithmParameterException.

Асиметричні алгоритми

RSA (1024–4096 біт) — для підпису (PKCS1, PSS з SHA-1/SHA-256/SHA-384/SHA-512) та шифрування (OAEP з SHA-1/SHA-256). EC (P-224, P-256, P-384, P-521) — для ECDSA-підпису та ECDH-узгодження ключів. X25519 та Ed25519 — з Android 12 (API 31) для сучасних криптографічних протоколів.

Для асиметричних ключів завжди генеруйте всередині Keymaster, НІКОЛИ не імпортуйте закриті ключі. Імпортовані закриті ключі не захищені апаратно — вони зберігаються в програмному шарі і вразливі при компрометації AP.

Симетричні алгоритми

AES (128, 256 біт) — для симетричного шифрування в режимах CBC, CTR, GCM. HMAC (SHA-1, SHA-256, SHA-512) — для автентифікації повідомлень. ChaCha20 (Android 12+) — для високопродуктивного потокового шифрування з автентифікацією Poly1305.

АлгоритмKeymasterПризначенняAPI
RSAKM 1.0+Підпис, шифрування18+
ECKM 1.0+ECDSA, ECDH18+
AESKM 2.0+Симетричне шифрування23+
HMACKM 2.0+Код автентифікації23+
ChaCha20KM 3.0+Потокове шифрування31+
X25519/Ed25519KM 3.0+Обмін ключами31+

Типи ключів та їх серіалізація

KeyStore.PrivateKeyEntry — містить закритий ключ (не експортований) та ланцюжок сертифікатів. KeyStore.SecretKeyEntry — для симетричних ключів. KeyStore.TrustedCertificateEntry — для довірених CA-сертифікатів. Відкриті ключі доступні для експорту через keyStore.getCertificate(alias).publicKey.

Приклади генерації та використання ключів

Розглянемо повний сценарій: генерація AES-ключа для шифрування даних і генерація EC-ключа для підпису з біометричним захистом. Обидва ключі створюються всередині Android KeyStore з апаратною підтримкою.

Генерація AES-ключа для шифрування

AES-ключ створюється через KeyGenerator з KeyGenParameterSpec. Параметри: PURPOSE_ENCRYPT + PURPOSE_DECRYPT, BLOCK_MODE_GCM (рекомендований режим з автентифікацією), ENCRYPTION_PADDING_NONE (для GCM padding не потрібен).

kotlin
import javax.crypto.KeyGenerator
import javax.crypto.Cipher
import javax.crypto.spec.GCMParameterSpec

fun generateAndEncrypt(alias: String, plainText: ByteArray): ByteArray {
    val spec = KeyGenParameterSpec.Builder(alias,
        KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT
    ).setBlockModes(KeyProperties.BLOCK_MODE_GCM)
     .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
     .setKeySize(256)
     .build()

    val kg = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore")
    kg.initialize(spec)
    kg.generateKey()

    val cipher = Cipher.getInstance("AES/GCM/NoPadding")
    cipher.init(Cipher.ENCRYPT_MODE, getKeyFromStore(alias))
    return cipher.doFinal(plainText)
}

Підпис з біометричним захистом

EC-ключ з userAuthenticationRequired=true вимагає автентифікації користувача перед кожною операцією підпису. Для цього використовується BiometricPrompt з CryptoObject, що містить об'єкт Signature. Після успішної біометрії Keymaster дозволяє операцію.

kotlin
fun createBiometricSignKey(alias: String) {
    val spec = KeyGenParameterSpec.Builder(alias,
        KeyProperties.PURPOSE_SIGN
    ).setAlgorithmParameterSpec(
        ECGenParameterSpec("secp256r1")
    ).setDigests(KeyProperties.DIGEST_SHA256)
     .setUserAuthenticationRequired(true)
     .setInvalidatedByBiometricEnrollment(true)
     .build()

    val kpg = KeyPairGenerator.getInstance(
        KeyProperties.KEY_ALGORITHM_EC,
        "AndroidKeyStore"
    )
    kpg.initialize(spec)
    kpg.generateKeyPair()
}

KeyStore та безпека на пристрої

Android KeyStore надає апаратні гарантії безпеки, які програмні KeyStore (JKS, BKS) не можуть забезпечити. Ключі захищені на рівні SoC, і навіть повний контроль над простором користувача Android не дозволяє вилучити закритий ключ.

Key Attestation (Android 8.1+)

Key Attestation — механізм, що дозволяє застосунку (і серверу) перевірити, в якому середовищі створено ключ. Android Keystore підписує сертифікат, що містить список характеристик ключа: алгоритм, розмір, призначення, hardware-backed (True/False), походження (GENERATED, IMPORTED). Сервер перевіряє ланцюжок сертифікатів до кореневого сертифіката Google.

Це критично важливо для фінансових застосунків: сервер може вимагати, щоб ключ було створено в апаратному середовищі (Hardware-Backed = True), і відхиляти ключі, створені в програмному Keystore. Key Attestation запобігає атакам, при яких зловмисник підміняє Keystore на емулятор.

Інвалідація ключів при зміні біометрії

setInvalidatedByBiometricEnrollment(true) означає, що ключ буде автоматично видалено Keymaster при зміні або видаленні біометричних шаблонів користувача. Це захист від атак, при яких зловмисник додає свій відбиток пальця в існуючий обліковий запис. Після додавання нового відбитка старі ключі стають недоступними.

Лічильник невдалих спроб біометричної автентифікації також керується Keymaster. Після maxBiometricAttempt (налаштовується виробником, зазвичай 5) Keymaster блокує всі операції з біометричними ключами на 30 секунд. Після 10 невдалих спроб — до введення пароля пристрою (секретний PIN).

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

У чому різниця між Android KeyStore та Bouncy Castle KeyStore?

Bouncy Castle (BKS) — програмний KeyStore, що зберігає ключі у файлі, захищеному паролем. Android KeyStore використовує апаратну ізоляцію TEE/StrongBox. Ключі BKS можна вилучити при root-доступі, ключі Android KeyStore — ні. BKS підходить для сертифікатів CA, Android KeyStore — для закритих ключів.

Чи можна використовувати один ключ для шифрування та підпису?

Так, якщо при генерації вказати PURPOSE_ENCRYPT or PURPOSE_DECRYPT or PURPOSE_SIGN or PURPOSE_VERIFY. Однак найкраща практика — створювати окремі ключі для різних операцій. Це обмежує збитки при компрометації одного з ключів і відповідає принципу найменших привілеїв.

Як дізнатися, чи є ключ апаратним в Android KeyStore?

Використовуйте KeyStore.getKeyCharacteristics(alias), доступний через android.security.keystore. Метод повертає набір прапорців: FLAG_HARDWARE — ключ в TEE, FLAG_SECURE_ELEMENT — ключ в StrongBox. Якщо прапорців немає — ключ програмний.

Що відбудеться при видаленні всіх біометричних шаблонів?

Всі ключі, створені з setInvalidatedByBiometricEnrollment(true), будуть автоматично інвалідовані Keymaster. При спробі використання застосунок отримає KeyPermanentlyInvalidatedException. Дані, зашифровані цими ключами, будуть безповоротно втрачені.

Чи підтримує Android KeyStore резервне копіювання ключів?

Апаратні ключі (в TEE/StrongBox) не підтримують резервне копіювання — вони прив'язані до конкретного пристрою. Програмні ключі можуть бути включені в бекап Google Drive. Для перенесення даних між пристроями шифруйте дані на сервері та розшифровуйте на новому пристрої.

Підсумки

  • Android KeyStore — JCA-провайдер для апаратно-ізольованого зберігання ключів через Keymaster HAL в TEE/StrongBox
  • KeyGenParameterSpec налаштовує алгоритм, розмір, призначення, digest, біометрію та часові обмеження ключа
  • RSA (KM 1.0+), EC (KM 1.0+), AES (KM 2.0+), ChaCha20 (KM 3.0+) — підтримувані алгоритми з різним рівнем Keymaster
  • Key Attestation (API 28+) дозволяє серверній стороні перевіряти апаратне походження ключа
  • Біометричний захист ключів через setUserAuthenticationRequired + BiometricPrompt з CryptoObject
  • Інвалідація ключів при зміні біометрії запобігає несанкціонованому використанню доданих відбитків
  • Використовуйте Android KeyStore для генерації та зберігання криптографічних ключів з апаратним захистом в Android-застосунках

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

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

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

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