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 — είναι ένας κρυπτογραφικός πάροχος (provider) που υλοποιήθηκε στο 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. Τα κλειδιά ποτέ δεν εγκαταλείπουν το ασφαλές περιβάλλον — η εφαρμογή λαμβάνει μόνο ένα ψευδώνυμο (alias) για αναφορά στο κλειδί. Αυτή είναι μια ουσιώδης διαφορά από τα λογισμικά 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 (μόνο λογισμικό)

Σε συσκευές χωρίς 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 για διαχωρισμό πρόσβασης. Κάθε εφαρμογή βλέπει μόνο τις δικές της εγγραφές, εκτός εάν χρησιμοποιείται κοινό 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 bit) — για υπογραφή (PKCS1, PSS) και κρυπτογράφηση (OAEP, PKCS1). EC (P-224, P-256, P-384, P-521) — για υπογραφή ECDSA και συμφωνία ECDH. AES (128, 256 bit) — για συμμετρική κρυπτογράφηση σε λειτουργίες CBC, CTR, GCM. HMAC (SHA1, SHA256, SHA512) — για ταυτοποίηση μηνυμάτων.

Για κάθε κλειδί καθορίζεται setPurposes, που περιορίζει τις δυνατές λειτουργίες. Ένα κλειδί RSA με PURPOSE_SIGN δεν μπορεί να χρησιμοποιηθεί για κρυπτογράφηση, ακόμα και αν ο επιτιθέμενος έχει πρόσβαση στο API. Αυτή είναι η επιβολή χρήσης κλειδιού σε επίπεδο υλικού.

Προστασία από διακυβή

Το Keymaster περιλαμβάνει απαριθμητή αποτυχημένων προσπαθειών βιομετρικής ταυτοποίησης. Μετά από έναν καθορισμένο αριθμό αποτυχημένων προσπαθειών (ρυθμίζεται μέσω setInvalidatedByBiometricEnrollment) το κλειδί καθίσταται μη προσβάσιμο και απαιτεί διαγραφή/αναγέννηση. Κατά τη διαγραφή όλων των βιομετρικών προτύπων, όλα τα κλειδιά με userAuthenticationRequired=true ακυρώνονται αυτόματα.

Επίσης υποστηρίζεται το Key Attestation (Android 8.1+): κατόπιν αιτήματος της εφαρμογής, το Keymaster υπογράφει ένα πιστοποιητικό με πληροφορίες σχετικά με τα χαρακτηριστικά του κλειδιού (υλικού/λογισμικού, αλγόριθμου, purges). Ο διακομιστής μπορεί να επαληθεύσει αυτό το πιστοποιητικό για να επιβεβαιώσει ότι το κλειδί δημιουργήθηκε σε αξιόπιστο περιβάλλον.

Συχνές Ερωτήσεις

Ποια είναι η διαφορά μεταξύ 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.

Περίληψη

  • 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. Θα σας συμβουλεύσουμε και θα προτείνουμε την καλύτερη λύση.

Συζήτηση έργου

Διαβάστε επίσης