KeyStore (Android): kluczowe pojęcia, API i działanie magazynu kryptograficznego

Autor: IT Sectr Opublikowano: 2026-03-14 Czas czytania: 10 min

KeyStore (Android) — to implementacja dostawcy kryptograficznego Java Cryptography Architecture (JCA) zintegrowana z Androidem do bezpiecznego przechowywania kluczy z możliwością izolacji sprzętowej. Od Androida 4.3 (API 18) KeyStore obsługuje klucze sprzętowe przez Keymaster HAL, a od Androida 9 (API 28) — StrongBox Keymaster dla kluczy w wydzielonym Secure Element. Według Android Security Documentation, dostawca „AndroidKeyStore” zastępuje standardowe Bouncy Castle lub OpenSSL KeyStore, zapewniając systemową ochronę przed nieautoryzowanym wydobyciem kluczy.

Najważniejsze

  • Android KeyStore — dostawca JCA do przechowywania kluczy z obsługą TEE, StrongBox i ochrony biometrycznej
  • KeyGenParameterSpec określa algorytm, przeznaczenie, digest, padding i biometrię przy tworzeniu klucza
  • Keymaster HAL realizuje sprzętowe operacje kryptograficzne na poziomach Software, TEE i StrongBox
  • Key Attestation (API 28+) pozwala serwerowi sprawdzić, że klucz został utworzony w sprzętowym środowisku Android KeyStore
  • Alias klucza — ciąg znaków, po którym aplikacja odwołuje się do klucza w Keystore; jeden alias odpowiada jednemu kluczowi

Czym jest KeyStore w Androidzie?

KeyStore w Androidzie — to nie osobna aplikacja ani plik, lecz dostawca kryptograficzny implementujący interfejs java.security.KeyStore. Zapewnia on jednolity interfejs API do przechowywania i używania kluczy prywatnych, kluczy symetrycznych i certyfikatów zaufanych centrów (CA). Dostawca jest rejestrowany pod nazwą „AndroidKeyStore” i dostępny przez standardowe KeyStore.getInstance().

Ewolucja Android KeyStore

Przed Androidem 4.3 operacje kryptograficzne były wykonywane programowo przez Bouncy Castle. Od Androida 4.3 pojawił się Keymaster HAL 1.0, umożliwiający korzystanie z TEE na ARM TrustZone. Android 6.0 (API 23) dodał Keymaster 2.0 z obsługą sprzętowej autoryzacji za pomocą odcisku palca. Android 9 (API 28) wprowadził Keymaster 4.0 i StrongBox Keymaster dla wydzielonego Secure Element.

Każda wersja Keymaster dodaje nowe możliwości i poprawia izolację kluczy. Nowoczesne urządzenia (2022+) muszą obsługiwać Keymaster 4.0 do certyfikacji Google Mobile Services, co gwarantuje obecność TEE dla wszystkich aplikacji Android.

Architektura i komponenty

Android KeyStore składa się z trzech poziomów: Java API (KeyStore, KeyPairGenerator), systemowy proces keystore (C++, działa jako system service) i Keymaster HAL (biblioteka w TEE lub Secure Element). Aplikacja wywołuje API, usługa keystore kieruje żądanie do Keymaster, a operacja jest wykonywana w chronionym środowisku.

Wszystkie prywatne klucze są przechowywane w TEE i nie mogą być odczytane z przestrzeni użytkownika. Nawet systemowa usługa keystore nie ma dostępu do surowych kluczy — tylko do uchwytów wskazujących na klucze wewnątrz Keymaster.

Jak działa KeyStore jako dostawca kryptograficzny?

Android KeyStore implementuje standardowy interfejs dostawcy usług JCA. Gdy aplikacja wywołuje Cipher.getInstance(„RSA/ECB/PKCS1Padding”, „AndroidKeyStore”), Android Security Provider deleguje operację do Keymaster przez łańcuch: Java → JNI → keystore service → Keymaster HAL.

Rejestracja dostawcy

Dostawca AndroidKeyStore jest rejestrowany automatycznie przy uruchomieniu procesu. Jego priorytet jest wyższy niż Bouncy Castle czy Conscrypt. Dlatego przy wywołaniu KeyStore.getInstance() bez określania dostawcy w większości przypadków zwracany jest AndroidKeyStore. Do jawnego wywołania użyj KeyStore.getInstance(„AndroidKeyStore”).

Każda aplikacja Android ma izolowany kontener w KeyStore. Aplikacje z tym samym UID (shared userId) mogą mieć wspólny dostęp do określonych kluczy, ale standardowa konfiguracja gwarantuje, że aplikacja A nie może odczytać kluczy aplikacji B.

Metody KeyStore i ich cechy

load(null) — inicjalizacja KeyStore. Parametr zawsze null dla AndroidKeyStore. setEntry — zapis klucza z określeniem KeyProtection (purposes, digest, padding). getEntry — pobranie KeyStore.PrivateKeyEntry, SecretKeyEntry lub TrustedCertificateEntry. containsAlias — sprawdzenie istnienia klucza. deleteEntry — usunięcie klucza (nieodwracalnie).

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()
    }
}

Obsługiwane algorytmy i typy kluczy

Android KeyStore obsługuje szeroki zestaw algorytmów kryptograficznych, różniący się w zależności od wersji Keymaster HAL na urządzeniu. Deweloper może uzyskać listę obsługiwanych algorytmów przez KeyGenParameterSpec.Builder przy próbie generacji — niezgodne parametry powodują InvalidAlgorithmParameterException.

Algorytmy asymetryczne

RSA (1024–4096 bitów) — do podpisu (PKCS1, PSS z SHA-1/SHA-256/SHA-384/SHA-512) i szyfrowania (OAEP z SHA-1/SHA-256). EC (P-224, P-256, P-384, P-521) — do podpisu ECDSA i uzgadniania kluczy ECDH. X25519 i Ed25519 — od Androida 12 (API 31) do nowoczesnych protokołów kryptograficznych.

Dla kluczy asymetrycznych Zawsze generuj wewnątrz Keymaster, NIGDY nie importuj kluczy prywatnych. Zaimportowane klucze prywatne nie są chronione sprzętowo — są przechowywane w warstwie programowej i podatne na ataki przy kompromitacji AP.

Algorytmy symetryczne

AES (128, 256 bitów) — do szyfrowania symetrycznego w trybach CBC, CTR, GCM. HMAC (SHA-1, SHA-256, SHA-512) — do uwierzytelniania wiadomości. ChaCha20 (Android 12+) — do wydajnego szyfrowania strumieniowego z uwierzytelnianiem Poly1305.

AlgorytmKeymasterPrzeznaczenieAPI
RSAKM 1.0+Podpis, szyfrowanie18+
ECKM 1.0+ECDSA, ECDH18+
AESKM 2.0+Szyfrowanie symetryczne23+
HMACKM 2.0+Kod uwierzytelniania23+
ChaCha20KM 3.0+Szyfrowanie strumieniowe31+
X25519/E25519KM 3.0+Wymiana kluczy31+

Typy kluczy i ich serializacja

KeyStore.PrivateKeyEntry — zawiera klucz prywatny (nieeksportowalny) i łańcuch certyfikatów. KeyStore.SecretKeyEntry — dla kluczy symetrycznych. KeyStore.TrustedCertificateEntry — dla zaufanych certyfikatów CA. Klucze publiczne są dostępne do eksportu przez keyStore.getCertificate(alias).publicKey.

Przykład generacji i użycia kluczy

Rozpatrzmy pełny scenariusz: generacja klucza AES do szyfrowania danych i generacja klucza EC do podpisu z ochroną biometryczną. Oba klucze są tworzone wewnątrz Android KeyStore z obsługą sprzętową.

Generacja klucza AES do szyfrowania

Klucz AES jest tworzony przez KeyGenerator z KeyGenParameterSpec. Parametry: PURPOSE_ENCRYPT + PURPOSE_DECRYPT, BLOCK_MODE_GCM (zalecany tryb z uwierzytelnianiem), ENCRYPTION_PADDING_NONE (dla GCM padding nie jest potrzebny).

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)
}

Podpis z ochroną biometryczną

Klucz EC z userAuthenticationRequired=true wymaga uwierzytelnienia użytkownika przed każdą operacją podpisu. W tym celu używa się BiometricPrompt z CryptoObject zawierającym obiekt Signature. Po pomyślnej biometrii Keymaster zezwala na operację.

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 a bezpieczeństwo na urządzeniu

Android KeyStore zapewnia sprzętowe gwarancje bezpieczeństwa, których programowe KeyStore (JKS, BKS) nie mogą zapewnić. Klucze są chronione na poziomie SoC, a nawet pełna kontrola nad przestrzenią użytkownika Androida nie pozwala na wydobycie klucza prywatnego.

Key Attestation (Android 8.1+)

Key Attestation — mechanizm umożliwiający aplikacji (i serwerowi) sprawdzenie, w jakim środowisku został utworzony klucz. Android Keystore podpisuje certyfikat zawierający listę charakterystyk klucza: algorytm, rozmiar, purges, hardware-backed (True/False), origin (GENERATED, IMPORTED). Serwer weryfikuje łańcuch certyfikatów aż do certyfikatu głównego Google.

Jest to krytyczne dla aplikacji finansowych: serwer może wymagać, aby klucz został utworzony w środowisku sprzętowym (Hardware-Backed = True), i odrzucać klucze utworzone w programowym Keystore. Key Attestation zapobiega atakom, w których osoba atakująca podstawia Keystore na emulator.

Unieważnianie kluczy przy zmianie biometrii

setInvalidatedByBiometricEnrollment(true) oznacza, że klucz zostanie automatycznie usunięty przez Keymaster przy zmianie lub usunięciu szablonów biometrycznych użytkownika. Jest to ochrona przed atakami, w których osoba atakująca dodaje swój odcisk palca do istniejącego konta. Po dodaniu nowego odcisku stare klucze stają się niedostępne.

Licznik nieudanych prób uwierzytelnienia biometrycznego jest również zarządzany przez Keymaster. Po maxBiometricAttempt (ustawiana przez producenta, zwykle 5) Keymaster blokuje wszystkie operacje z kluczami biometrycznymi na 30 sekund. Po 10 nieudanych próbach — do czasu wprowadzenia hasła urządzenia (sekretny PIN).

Często zadawane pytania

Jaka jest różnica między Android KeyStore a Bouncy Castle KeyStore?

Bouncy Castle (BKS) — programowy KeyStore przechowujący klucze w pliku chronionym hasłem. Android KeyStore używa sprzętowej izolacji TEE/StrongBox. Klucze BKS można wydobyć przy dostępie root, klucze Android KeyStore — nie. BKS nadaje się do certyfikatów CA, Android KeyStore — do kluczy prywatnych.

Czy można używać jednego klucza do szyfrowania i podpisu?

Tak, jeśli przy generacji określisz PURPOSE_ENCRYPT or PURPOSE_DECRYPT or PURPOSE_SIGN or PURPOSE_VERIFY. Jednak najlepszą praktyką jest tworzenie oddzielnych kluczy dla różnych operacji. Ogranicza to szkody w przypadku kompromitacji jednego z kluczy i jest zgodne z zasadą najmniejszych uprawnień.

Jak sprawdzić, czy klucz w Android KeyStore jest sprzętowy?

Użyj KeyStore.getKeyCharacteristics(alias), dostępnego przez android.security.keystore. Metoda zwraca zestaw flag: FLAG_HARDWARE — klucz w TEE, FLAG_SECURE_ELEMENT — klucz w StrongBox. Jeśli brak flag — klucz jest programowy.

Co się stanie po usunięciu wszystkich szablonów biometrycznych?

Wszystkie klucze utworzone z setInvalidatedByBiometricEnrollment(true) zostaną automatycznie unieważnione przez Keymaster. Przy próbie użycia aplikacja otrzyma KeyPermanentlyInvalidatedException. Dane zaszyfrowane tymi kluczami zostaną bezpowrotnie utracone.

Czy Android KeyStore obsługuje tworzenie kopii zapasowych kluczy?

Klucze sprzętowe (w TEE/StrongBox) nie obsługują kopii zapasowych — są powiązane z konkretnym urządzeniem. Klucze programowe mogą być uwzględnione w kopii zapasowej Google Drive. Do przenoszenia danych między urządzeniami szyfruj dane na serwerze i odszyfrowuj na nowym urządzeniu.

Podsumowanie

  • Android KeyStore — dostawca JCA do sprzętowo izolowanego przechowywania kluczy przez Keymaster HAL w TEE/StrongBox
  • KeyGenParameterSpec konfiguruje algorytm, rozmiar, purges, digest, biometrię i ograniczenia czasowe klucza
  • RSA (KM 1.0+), EC (KM 1.0+), AES (KM 2.0+), ChaCha20 (KM 3.0+) — obsługiwane algorytmy z różnym poziomem Keymaster
  • Key Attestation (API 28+) pozwala stronie serwerowej sprawdzić sprzętowe pochodzenie klucza
  • Ochrona biometryczna kluczy przez setUserAuthenticationRequired + BiometricPrompt z CryptoObject
  • Unieważnianie kluczy przy zmianie biometrii zapobiega nieautoryzowanemu użyciu dodanych odcisków
  • Używaj Android KeyStore do generacji i przechowywania kluczy kryptograficznych z ochroną sprzętową w aplikacjach Android

Opracujemy aplikację mobilną pod klucz

IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.

Omów projekt

Przeczytaj również