KeyStore (Android) — είναι μια υλοποίηση του κρυπτογραφικού παρόχου Java Cryptography Architecture (JCA) που έχει ενσωματωθεί στο Android για ασφαλή αποθήκευση κλειδιών με δυνατότητα απομονώσεως υλικού. Από το Android 4.3 (API 18) το KeyStore υποστηρίζει υλικά κλειδιά μέσω Keymaster HAL, και από το Android 9 (API 28) — StrongBox Keymaster για κλειδιά σε αφιερωμένο Secure Element. Σύμφωνα με Android Security Documentation, ο παρόχος “AndroidKeyStore” αντικαθιστά τα τυπικά Bouncy Castle ή OpenSSL KeyStore, παρέχοντας συστημική προστασία από την μη εξουσιοδοτημένη εξαγωγή κλειδιών.
Βασικά σημεία
KeyStore στο Android — δεν είναι μια ξεχωριστή εφαρμογή ή αρχείο, αλλά ένας κρυπτογραφικός παρόχος που υλοποιεί τη διεπαφή java.security.KeyStore. Παρέχει ενιαίο API για την αποθήκευση και χρήση ιδιωτικών κλειδιών, συμμετρικών κλειδιών και πιστοποιητικών αρχών εμπιστεύσεων (CA). Ο παρόχος είναι εγγεγραμμένος με το όνομα “AndroidKeyStore” και είναι προσβάσιμος μέσω του τυπικού KeyStore.getInstance().
Πριν το 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 δεν έχει πρόσβαση σε αδρά κλειδιά — μόνο σε χειριστές που δείχνουν σε κλειδιά μέσα στο Keymaster.
Το 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.
load(null) — αρχικοποίηση KeyStore. Η παράμετρος είναι πάντα null για AndroidKeyStore. setEntry — αποθήκευση κλειδιού με καθορισμό KeyProtection (purposes, digest, padding). getEntry — λήψη KeyStore.PrivateKeyEntry, SecretKeyEntry ή TrustedCertificateEntry. containsAlias — έλεγχος ύπαρξης κλειδιού. deleteEntry — διαγραφή κλειδιού (μη αναστρέψιμη).
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 bit) — για υπογραφή (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 bit) — για συμμετρική κρυπτογράφηση σε λειτουργίες CBC, CTR, GCM. HMAC (SHA-1, SHA-256, SHA-512) — για ταυτοποίηση μηνυμάτων. ChaCha20 (Android 12+) — για κρυπτογράφηση ροής υψηλής απόδοσης με ταυτοποίηση Poly1305.
| Αλγόριθμος | Keymaster | Σκοπός | API |
|---|---|---|---|
| RSA | KM 1.0+ | Υπογραφή, κρυπτογράφηση | 18+ |
| EC | KM 1.0+ | ECDSA, ECDH | 18+ |
| AES | KM 2.0+ | Συμμετρική κρυπτογράφηση | 23+ |
| HMAC | KM 2.0+ | Κωδικός ταυτοποίησης | 23+ |
| ChaCha20 | KM 3.0+ | Κρυπτογράφηση ροής | 31+ |
| X25519/E25519 | KM 3.0+ | Ανταλλαγή κλειδιών | 31+ |
KeyStore.PrivateKeyEntry — περιέχει το ιδιωτικό κλειδί (μη δυνατός εξαγωγής) και την αλυσίδα πιστοποιητικών. KeyStore.SecretKeyEntry — για συμμετρικά κλειδιά. KeyStore.TrustedCertificateEntry — για αξιόπιστα πιστοποιητικά CA. Τα δημόσια κλειδιά είναι διαθέσιμα για εξαγωγή μέσω keyStore.getCertificate(alias).publicKey.
Ας εξετάσουμε ένα πλήρες σενάριο: δημιουργία AES κλειδιού για κρυπτογράφηση δεδομένων και δημιουργία EC κλειδιού για υπογραφή με βιομετρική προστασία. Και τα δύο κλειδιά δημιουργούνται εντός Android KeyStore με υλική υποστήριξη.
Το AES κλειδί δημιουργείται μέσω KeyGenerator με KeyGenParameterSpec. Παράμετροι: PURPOSE_ENCRYPT + PURPOSE_DECRYPT, BLOCK_MODE_GCM (συστηνώμενη λειτουργία με ταυτοποίηση), ENCRYPTION_PADDING_NONE (για GCM δεν χρειάζεται padding).
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 επιτρέπει τη λειτουργία.
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()
}
Το Android KeyStore παρέχει υλικές εγγυήσεις ασφαλείας που δεν μπορούν να παράσχουν οι KeyStore λογισμικού (JKS, BKS). Τα κλειδιά προστατεύονται σε επίπεδο SoC και ακόμη και ο πλήρης έλεγχος του χώρου χρήστη Android δεν επιτρέπει την εξαγωγή του ιδιωτικού κλειδιού.
Key Attestation — μηχανισμός που επιτρέπει στην εφαρμογή (και στον διακομιστή) να επαληθεύσει σε ποιο περιβάλλον δημιουργήθηκε το κλειδί. Το Android Keystore υπογράφει ένα πιστοποιητικό που περιέχει λίστα χαρακτηριστικών κλειδιού: αλγόριθμο, μέγεθος, purges, hardware-backed (True/False), origin (GENERATED, IMPORTED). Ο διακομιστής επαληθεύει την αλυσίδα πιστοποιητικών μέχρι το ριζικό πιστοποιητικό Google.
Αυτό είναι κρίσιμο για χρηματοοικονομικές εφαρμογές: ο διακομιστής μπορεί να απαιτεί το κλειδί να έχει δημιουργηθεί σε υλικό περιβάλλον (Hardware-Backed = True) και να απορρίπτει κλειδιά που δημιουργήθηκαν σε KeyStore λογισμικού. Το Key Attestation αποτρέπει επιθέσεις όπου ο επιτιθέμενος αντικαθιστά το Keystore με ενα εμπαιγνοτηή.
setInvalidatedByBiometricEnrollment(true) σημαίνει ότι το κλειδί θα διαγραφεί αυτόματα από το Keymaster κατά την αλλαγή ή διαγραφή των βιομετρικών προτύπων του χρήστη. Αυτό είναι προστασία από επιθέσεις όπου ο επιτιθέμενος προσθέτει το δικό του αποτύπωμα σε υπάρχοντα λογαριασμό. Μετά την προσθήκη νέου αποτυπώματος, τα παλιά κλειδιά καθίστανται μη προσβάσιμα.
Ο καταμετρητής των αποτυχημένων προσπαθειών βιομετρικής ταυτοποίησης διαχειρίζεται επίσης από το Keymaster. Μετά από maxBiometricAttempt (ρυθμίζεται από τον κατασκευαστή, συνήθως 5) το Keymaster αποκλείει όλες τις λειτουργίες με βιομετρικά κλειδιά για 30 δευτερόλεπτα. Μετά από 10 αποτυχημένες προσπάθειες — μέχρι την εισαγωγή κωδικού συσκευής (μυστικό PIN).
Συχνές Ερωτήσεις
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. Ωστόσο, η καλύτερη πρακτική είναι η δημιουργία ξεχωριστών κλειδιών για διαφορετικές λειτουργίες. Αυτό περιορίζει τη ζημιά σε περίπτωση συμβιβασμού ενός από τα κλειδιά και συμμορφώνεται με την αρχή του ελάχιστου δικαιώματος.
Χρησιμοποιήστε το KeyStore.getKeyCharacteristics(alias), διαθέσιμο μέσω android.security.keystore. Η μέθοδος επιστρέφει ένα σύνολο σημαιών: FLAG_HARDWARE — κλειδί σε TEE, FLAG_SECURE_ELEMENT — κλειδί σε StrongBox. Εάν δεν υπάρχουν σημαίες — το κλειδί είναι λογισμικού.
Όλα τα κλειδιέ που δημιουργήθηκαν με setInvalidatedByBiometricEnrollment(true) θα ακυρωθούν αυτόματα από το Keymaster. Κατά την προσπάθεια χρήσης, η εφαρμογή θα λάβει KeyPermanentlyInvalidatedException. Τα δεδομένα που κρυπτογραφήθηκαν με αυτά τα κλειδιά θα χαθούν ανεπανόρθωτα.
Τα υλικά κλειδιά (σε TEE/StrongBox) δεν υποστηρίζουν αντίγραφα ασφαλείας — είναι δεσμευμένα σε συγκεκριμένη συσκευή. Τα κλειδιά λογισμικού μπορούν να συμπεριληφθούν στο αντίγραφο Google Drive. Για μεταφορά δεδομένων μεταξύ συσκευών, κρυπτογραφήστε τα δεδομένα στον διακομιστή και αποκρυπτογραφήστε στη νέα συσκευή.
Συμπεράσματα
Θα αναπτύξουμε μια εφαρμογή για κινητά έτοιμη για χρήση
Η IT Sectr δημιουργεί εφαρμογές iOS και Android για νεοφυείς επιχειρήσεις και επιχειρήσεις από το 2017. Θα σας συμβουλεύσουμε και θα προτείνουμε την καλύτερη λύση.
Διαβάστε επίσης