Android Anahtar Deposu sistemi, şifreleme anahtarlarını cihazdan çıkarmayı zorlaştırmak için container'da depolamanıza olanak tanır. Anahtarlar, anahtar deposuna eklendikten sonra bunları şifreleme işlemleri için kullanabilirsiniz. Anahtar materyali dışa aktarılamaz. Ayrıca anahtar deposu sistemi, anahtarların ne zaman ve nasıl kullanılacağını kısıtlamanıza da olanak tanır. Örneğin, anahtar kullanımı için kullanıcı kimlik doğrulaması isteyebilir veya anahtarların yalnızca belirli şifreleme modlarında kullanılmasını sağlayabilirsiniz. Daha fazla bilgi için Güvenlik Özellikleri bölümüne bakın.
Anahtar deposu sistemi, Android 4.0'da kullanıma sunulan KeyChain
API (API düzeyi 14), Android 4.3'te kullanıma sunulan Android Anahtar Deposu sağlayıcı özelliği (API düzeyi 18) ve Jetpack kapsamında sunulan Güvenlik kitaplığı tarafından kullanılır. Bu dokümanda, Android Anahtar Deposu sisteminin ne zaman ve nasıl kullanılacağı açıklanmaktadır.
Güvenlik özellikleri
Android Anahtar Deposu sistemi, anahtar materyalini yetkisiz kullanıma karşı iki şekilde korur. Öncelikle anahtar materyalinin uygulama işlemlerinden ve tamamen Android cihazdan çıkarılmasını engelleyerek anahtar materyalinin Android cihazın dışından yetkisiz şekilde kullanılması riskini azaltır. İkinci olarak, anahtar deposu sistemi uygulamaların Android cihaz içindeki anahtar materyalinin yetkisiz kullanım riskini azaltır. Bunun için uygulamaların, anahtarlarının yetkilendirilmiş kullanımlarını belirtmesini sağlar ve ardından bu kısıtlamaları uygulamaların işlemleri dışında da uygular.
Çıkarmayı önleme
Android Anahtar Deposu anahtarlarının anahtar materyali, iki güvenlik önlemi kullanılarak çıkarmaya karşı korunur:
- Anahtar materyali hiçbir zaman başvuru sürecine girmez. Bir uygulama Android anahtar deposu anahtarı kullanarak kriptografik işlemler gerçekleştirdiğinde, arka planda şifrelenmemiş metin, şifrelenmiş metin ve imzalanacak ya da doğrulanacak mesajlar, şifreleme işlemlerini gerçekleştiren bir sistem işlemine aktarılır. Uygulama işleminin güvenliği ihlal edilirse saldırgan uygulamanın anahtarlarını kullanabilir ancak anahtar materyalini çıkaramaz (örneğin, Android cihazın dışında kullanılmak üzere).
- Anahtar materyali, Android cihazın Trusted Execution Environment (TEE) veya Güvenlik Unsuru (SE) gibi güvenli donanımına bağlanabilir. Bu özellik bir anahtar için etkinleştirildiğinde anahtar materyali hiçbir zaman güvenli donanımın dışında açığa çıkarılmaz. Android OS'in güvenliği ihlal edilirse veya bir saldırgan cihazın dahili depolama alanını okuyabilirse saldırgan, Android cihazda herhangi bir uygulamanın Android Anahtar Deposu anahtarlarını kullanabilir, ancak bunları cihazdan çıkaramaz. Bu özellik yalnızca cihazın güvenli donanımı; anahtar algoritması, engelleme modları, dolgu şemaları ve özetlerden oluşan belirli bir kombinasyonu destekliyorsa etkinleştirilir.
Özelliğin bir anahtar için etkinleştirilip etkinleştirilmediğini kontrol etmek üzere anahtarla ilgili bir
KeyInfo
edinin. Bir sonraki adım, uygulamanızın hedef SDK sürümüne bağlıdır:- Uygulamanız Android 10 (API düzeyi 29) veya sonraki bir sürümü hedefliyorsa
getSecurityLevel()
döndüren değerini inceleyin.KeyProperties.SecurityLevelEnum.TRUSTED_ENVIRONMENT
veyaKeyProperties.SecurityLevelEnum.STRONGBOX
ile eşleşen döndürme değerleri, anahtarın güvenli donanımda bulunduğunu belirtir. - Uygulamanız Android 9 (API düzeyi 28) veya önceki sürümleri hedefliyorsa
KeyInfo.isInsideSecurityHardware()
boole döndürme değerini inceleyin.
- Uygulamanız Android 10 (API düzeyi 29) veya sonraki bir sürümü hedefliyorsa
Donanım güvenlik modülü
Android 9 (API düzeyi 28) veya sonraki sürümleri çalıştıran desteklenen cihazlarda, donanım güvenlik modülü benzeri bir güvenlik unsurunda bulunan Keymaster veya Keymint HAL'nin bir uygulaması olan StrongBox Keymaster bulunabilir. Donanım güvenlik modülleri, Linux çekirdeği güvenliğinin ihlal edilmesinin açığa çıkmayacağı birçok farklı anahtar depolama uygulamasına (ör. TEE) işaret edebilir. StrongBox ise yerleşik Secure Elements (eSE) veya SoC üzerinde güvenli işleme birimleri (iSE) gibi cihazlara açıkça atıfta bulunur.
Modül şunları içerir:
- Kendi CPU'su
- Güvenli depolama
- Gerçek bir rastgele sayı oluşturma aracı
- Paketin izinsiz olarak değiştirilmesine ve uygulamaların yetkisiz bir şekilde başka cihazdan yüklenmesine karşı koymak için ek mekanizmalar
- Güvenli zamanlayıcı
- Genel amaçlı giriş/çıkış (GPIO) gibi bir yeniden başlatma bildirim PIN'i (veya eşdeğeri)
Düşük güç gerektiren StrongBox uygulamalarını desteklemek için algoritmalardan ve anahtar boyutlarından oluşan bir alt küme desteklenir:
- RSA 2048
- AES 128 ve 256
- ECDSA, ECDH P-256
- HMAC-SHA256 (8 ile 64 bayt arasında (ikisi de dahil) anahtar boyutlarını destekler)
- Üçlü DES
- Uzun Süreli APDU'lar
- Anahtar Onayı
- Yükseltme için Değişiklik H desteği
KeyStore
sınıfını kullanarak anahtar oluştururken veya içe aktarırken true
yöntemini setIsStrongBoxBacked()
yöntemine geçirerek anahtarı StrongBox Keymaster'da depolamayı tercih ettiğinizi belirtirsiniz.
StrongBox, TEE'ye kıyasla biraz daha yavaş ve kaynak kısıtlamalı (yani daha az eşzamanlı işlemi destekler) olsa da StrongBox, fiziksel ve yan kanal saldırılarına karşı daha iyi güvenlik garantisi sunar. Uygulama kaynağı verimliliğinden daha yüksek güvenlik garantilerine öncelik vermek istiyorsanız StrongBox'ı kullanıma sunulduğu cihazlarda kullanmanızı öneririz. StrongBox kullanılamadığında, uygulamanız önemli malzemeleri depolamak için her zaman TEE'ye geri dönebilir.
Anahtar kullanım yetkilendirmeleri
Android Anahtar Deposu, Android cihazda anahtarların yetkisiz kullanımını önlemek için uygulamaların, anahtarları oluştururken veya içe aktarırken anahtarlarının yetkilendirilmiş kullanımlarını belirtmesine olanak tanır. Anahtar oluşturulduktan veya içe aktarıldıktan sonra yetkilendirmeleri değiştirilemez. Yetkilendirmeler daha sonra anahtar her kullanıldığında Android Anahtar Deposu tarafından zorunlu kılınır. Bu, yalnızca gereksinimleriniz, anahtar oluşturma/içe aktarma işleminden sonra (ancak bu işlemden önce veya sonra değil) uygulama sürecinizde yaşanabilecek bir güvenlik ihlalinin, anahtarın yetkisiz bir şekilde kullanılmasına yol açamayacağı durumlarda genellikle faydalı olan gelişmiş bir güvenlik özelliğidir.
Desteklenen anahtar kullanımı yetkilendirmeleri aşağıdaki kategorilere girer:
- Kriptografi: Anahtar yalnızca yetkilendirilmiş anahtar algoritmaları, işlemler veya amaçlarla (şifreleme, şifre çözme, imzalama, doğrulama), dolgu şemaları, blok modları veya özetlerle kullanılabilir.
- Geçici geçerlilik aralığı: Anahtara yalnızca tanımlanmış bir zaman aralığı boyunca kullanım için izin verilir.
- Kullanıcı kimlik doğrulaması: Anahtar, yalnızca kullanıcının kimliği yeterince kısa bir süre önce doğrulanmışsa kullanılabilir. Anahtar kullanımı için kullanıcı kimlik doğrulamasını zorunlu kılma başlıklı makaleyi inceleyin.
Anahtar materyali güvenli donanımın içinde olan anahtarlar için ek bir güvenlik önlemi olarak (bkz. KeyInfo.isInsideSecurityHardware()
veya Android 10 (API düzeyi 29) veya sonraki sürümleri hedefleyen uygulamalarda
KeyInfo.getSecurityLevel()
) bazı anahtar kullanımı yetkilendirmeleri, Android cihaza bağlı olarak güvenli donanım tarafından
zorunlu kılınabilir.
Güvenli donanım, normalde şifreleme ve kullanıcı kimlik doğrulaması yetkilendirmelerini zorunlu kılar. Ancak, güvenli donanım normalde bağımsız ve güvenli bir gerçek zamanlı saate sahip olmadığından genellikle zamansal geçerlilik aralığı yetkilendirmelerini zorunlu kılmaz.
KeyInfo.isUserAuthenticationRequirementEnforcedBySecureHardware()
kullanarak bir anahtarın kullanıcı kimlik doğrulaması yetkilendirmesinin güvenli donanım tarafından zorunlu kılınıp kılınmadığını sorgulayabilirsiniz.
Bir anahtar zinciri ile Android Anahtar Deposu sağlayıcısı arasından seçim yapın
Sistem genelinde kimlik bilgileri almak istediğinizde KeyChain
API'yi kullanın. Bir uygulama KeyChain
API üzerinden herhangi bir kimlik bilgisi kullanmak istediğinde, kullanıcılar sistem tarafından sağlanan bir kullanıcı arayüzü aracılığıyla uygulamanın yüklü kimlik bilgilerinden hangisine erişebileceğini seçebilir. Bu, birkaç uygulamanın kullanıcı izniyle aynı kimlik bilgisi grubunu kullanmasına olanak tanır.
Belirli bir uygulamanın, yalnızca söz konusu uygulamanın erişebileceği kendi kimlik bilgilerini depolamasına izin vermek için Android Anahtar Deposu sağlayıcısını kullanın.
Bu sayede uygulamalar, yalnızca kendi kullanabilecekleri kimlik bilgilerini yönetebilir ve KeyChain
API'nin sistem genelinde geçerli kimlik bilgileri için sağladığı güvenlik avantajlarının aynılarını sağlayabilir.
Bu yöntemde kullanıcının kimlik bilgilerini seçmesi gerekmez.
Android Anahtar Deposu sağlayıcısını kullan
Bu özelliği kullanmak için Android 4.3 (API düzeyi 18) sürümünde kullanıma sunulan AndroidKeyStore
sağlayıcısıyla birlikte standart KeyStore
ve KeyPairGenerator
veya KeyGenerator
sınıflarını kullanırsınız.
AndroidKeyStore
, KeyStore.getInstance(type)
yöntemiyle kullanılmak üzere KeyStore
türü ve KeyPairGenerator.getInstance(algorithm, provider)
ile KeyGenerator.getInstance(algorithm, provider)
yöntemleriyle kullanım için sağlayıcı olarak kaydedildi.
Yeni bir özel veya gizli anahtar oluşturma
PrivateKey
ve SecretKey
içeren yeni bir KeyPair
oluşturmak için kendinden imzalı sertifikanın ilk X.509 özelliklerini belirtmeniz gerekir.
Güvenlik kitaplığı, aşağıdaki snippet'te gösterildiği gibi geçerli bir simetrik anahtar oluşturmak için varsayılan bir uygulama sağlar:
Kotlin
// Although you can define your own key generation parameter specification, it's // recommended that you use the value specified here. val mainKey = MasterKey.Builder(applicationContext) .setKeyScheme(MasterKey.KeyScheme.AES256_GCM) .build()
Java
// Although you can define your own key generation parameter specification, it's // recommended that you use the value specified here. Context context = getApplicationContext(); MasterKey mainKey = new MasterKey.Builder(context) .setKeyScheme(MasterKey.KeyScheme.AES256_GCM) .build();
Alternatif olarak, sertifikayı daha sonra bir sertifika yetkilisi (CA) tarafından imzalanan bir sertifikayla değiştirmek için KeyStore.setKeyEntry()
kullanabilirsiniz.
Anahtar çiftini oluşturmak için KeyGenParameterSpec
ile bir KeyPairGenerator
kullanın:
Kotlin
/* * Generate a new EC key pair entry in the Android Keystore by * using the KeyPairGenerator API. The private key can only be * used for signing or verification and only with SHA-256 or * SHA-512 as the message digest. */ val kpg: KeyPairGenerator = KeyPairGenerator.getInstance( KeyProperties.KEY_ALGORITHM_EC, "AndroidKeyStore" ) val parameterSpec: KeyGenParameterSpec = KeyGenParameterSpec.Builder( alias, KeyProperties.PURPOSE_SIGN or KeyProperties.PURPOSE_VERIFY ).run { setDigests(KeyProperties.DIGEST_SHA256, KeyProperties.DIGEST_SHA512) build() } kpg.initialize(parameterSpec) val kp = kpg.generateKeyPair()
Java
/* * Generate a new EC key pair entry in the Android Keystore by * using the KeyPairGenerator API. The private key can only be * used for signing or verification and only with SHA-256 or * SHA-512 as the message digest. */ KeyPairGenerator kpg = KeyPairGenerator.getInstance( KeyProperties.KEY_ALGORITHM_EC, "AndroidKeyStore"); kpg.initialize(new KeyGenParameterSpec.Builder( alias, KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY) .setDigests(KeyProperties.DIGEST_SHA256, KeyProperties.DIGEST_SHA512) .build()); KeyPair kp = kpg.generateKeyPair();
Şifrelenmiş anahtarları güvenli donanıma aktarın
Android 9 (API düzeyi 28) ve sonraki sürümler, şifrelenmiş anahtarları ASN.1 olarak kodlanmış bir anahtar biçimi kullanarak anahtar deposuna güvenli bir şekilde içe aktarmanıza olanak tanır. Daha sonra Keymaster, anahtar deposundaki anahtarların şifresini çözer. Böylece anahtarların içeriği, cihazın ana makine belleğinde hiçbir zaman düz metin olarak görünmez. Bu işlem ek anahtar şifre çözme güvenliği sağlar.
Şifrelenmiş anahtarların anahtar deposuna güvenli bir şekilde aktarılmasını desteklemek için aşağıdaki adımları tamamlayın:
PURPOSE_WRAP_KEY
amacını kullanan bir anahtar çifti oluşturun. Bu anahtar çiftine de onay eklemenizi öneririz.Güvendiğiniz bir sunucuda veya makinede
SecureKeyWrapper
için ASN.1 mesajını oluşturun.Sarmalayıcı aşağıdaki şemayı içerir:
KeyDescription ::= SEQUENCE { keyFormat INTEGER, authorizationList AuthorizationList } SecureKeyWrapper ::= SEQUENCE { wrapperFormatVersion INTEGER, encryptedTransportKey OCTET_STRING, initializationVector OCTET_STRING, keyDescription KeyDescription, secureKey OCTET_STRING, tag OCTET_STRING }
ASN.1 mesajını bayt dizisi olarak ileten bir
WrappedKeyEntry
nesnesi oluşturun.Bu
WrappedKeyEntry
nesnesini, birKeystore.Entry
nesnesini kabul edensetEntry()
öğesinin aşırı yüklenmesine geçirin.
Anahtar deposu girişleriyle çalışma
AndroidKeyStore
sağlayıcısına tüm standart KeyStore
API'leri aracılığıyla erişebilirsiniz.
Girişleri listeleme
aliases()
yöntemini çağırarak anahtar deposundaki girişleri listeleyin:
Kotlin
/* * Load the Android KeyStore instance using the * AndroidKeyStore provider to list the currently stored entries. */ val ks: KeyStore = KeyStore.getInstance("AndroidKeyStore").apply { load(null) } val aliases: Enumeration<String> = ks.aliases()
Java
/* * Load the Android KeyStore instance using the * AndroidKeyStore provider to list the currently stored entries. */ KeyStore ks = KeyStore.getInstance("AndroidKeyStore"); ks.load(null); Enumeration<String> aliases = ks.aliases();
Verileri imzalayın ve doğrulayın
Anahtar deposundan KeyStore.Entry
öğesini getirip sign()
gibi Signature
API'lerini kullanarak verileri imzalayın:
Kotlin
/* * Use a PrivateKey in the KeyStore to create a signature over * some data. */ val ks: KeyStore = KeyStore.getInstance("AndroidKeyStore").apply { load(null) } val entry: KeyStore.Entry = ks.getEntry(alias, null) if (entry !is KeyStore.PrivateKeyEntry) { Log.w(TAG, "Not an instance of a PrivateKeyEntry") return null } val signature: ByteArray = Signature.getInstance("SHA256withECDSA").run { initSign(entry.privateKey) update(data) sign() }
Java
/* * Use a PrivateKey in the KeyStore to create a signature over * some data. */ KeyStore ks = KeyStore.getInstance("AndroidKeyStore"); ks.load(null); KeyStore.Entry entry = ks.getEntry(alias, null); if (!(entry instanceof PrivateKeyEntry)) { Log.w(TAG, "Not an instance of a PrivateKeyEntry"); return null; } Signature s = Signature.getInstance("SHA256withECDSA"); s.initSign(((PrivateKeyEntry) entry).getPrivateKey()); s.update(data); byte[] signature = s.sign();
Benzer şekilde, verileri verify(byte[])
yöntemiyle doğrulayın:
Kotlin
/* * Verify a signature previously made by a private key in the * KeyStore. This uses the X.509 certificate attached to the * private key in the KeyStore to validate a previously * generated signature. */ val ks = KeyStore.getInstance("AndroidKeyStore").apply { load(null) } val entry = ks.getEntry(alias, null) as? KeyStore.PrivateKeyEntry if (entry == null) { Log.w(TAG, "Not an instance of a PrivateKeyEntry") return false } val valid: Boolean = Signature.getInstance("SHA256withECDSA").run { initVerify(entry.certificate) update(data) verify(signature) }
Java
/* * Verify a signature previously made by a private key in the * KeyStore. This uses the X.509 certificate attached to the * private key in the KeyStore to validate a previously * generated signature. */ KeyStore ks = KeyStore.getInstance("AndroidKeyStore"); ks.load(null); KeyStore.Entry entry = ks.getEntry(alias, null); if (!(entry instanceof PrivateKeyEntry)) { Log.w(TAG, "Not an instance of a PrivateKeyEntry"); return false; } Signature s = Signature.getInstance("SHA256withECDSA"); s.initVerify(((PrivateKeyEntry) entry).getCertificate()); s.update(data); boolean valid = s.verify(signature);
Anahtar kullanımı için kullanıcı kimlik doğrulamasını zorunlu kıl
Bir anahtarı oluştururken veya AndroidKeyStore
içine aktarırken, anahtarın yalnızca kullanıcının kimliği doğrulanırsa kullanılmak üzere yetkilendirileceğini belirtebilirsiniz. Kullanıcının kimliği, güvenli kilit ekranı kimlik bilgilerinin (desen/PIN/şifre, biyometrik kimlik bilgileri) bir alt kümesi kullanılarak doğrulanır.
Bu, genellikle yalnızca, uygulama sürecinizde anahtar oluşturma/içe aktarma işlemi sonrasında (ancak bu işlem öncesinde veya sırasında değil) güvenlik ihlalinin, kullanıcının anahtarı kullanmak için kimliğinin doğrulanması şartını atlayamayacağı durumlarda faydalı olan gelişmiş bir güvenlik özelliğidir.
Bir anahtar yalnızca kullanıcının kimliği doğrulandığında kullanılmak üzere yetkilendirildiğinde, anahtarı aşağıdaki modlardan birinde çalışacak şekilde yapılandırmak için setUserAuthenticationParameters()
işlevini çağırabilirsiniz:
- Belirli bir süre için izin ver
- Kullanıcı, belirtilen kimlik bilgilerinden birini kullanarak kimlik doğrulaması yaptığında tüm anahtarlar kullanım için yetkilendirilir.
- Belirli bir kriptografik işlem süresince yetki ver
Belirli bir anahtarı içeren her işlem, kullanıcı tarafından ayrı ayrı yetkilendirilmelidir.
Uygulamanız bu süreci bir
BiometricPrompt
örneğindeauthenticate()
çağırarak başlatır.
Oluşturduğunuz her anahtar için güçlü bir biyometrik kimlik bilgisi, kilit ekranı kimlik bilgisi veya her iki kimlik bilgisi türünü desteklemeyi seçebilirsiniz. Kullanıcının, uygulama anahtarının temel aldığı kimlik bilgilerini ayarlayıp ayarlamadığını belirlemek için canAuthenticate()
çağrısı yapın.
Bir anahtar yalnızca biyometrik kimlik bilgilerini destekliyorsa yeni biyometrik kayıtlar eklendiğinde anahtar varsayılan olarak geçersiz kılınır. Yeni biyometrik kayıtlar eklendiğinde anahtarı geçerli durumda kalacak şekilde yapılandırabilirsiniz. Bunu yapmak için false
öğesini setInvalidatedByBiometricEnrollment()
hesabına iletin.
Biyometrik kimlik doğrulama iletişim kutusunu gösterme de dahil olmak üzere uygulamanıza biyometrik kimlik doğrulama özellikleri ekleme hakkında daha fazla bilgi edinin.
Desteklenen algoritmalar
Cipher
KeyGenerator
KeyFactory
KeyStore
(KeyGenerator
veKeyPairGenerator
ile aynı anahtar türlerini destekler)KeyPairGenerator
Mac
Signature
SecretKeyFactory
Blog makaleleri
ICS'de Anahtar Deposu Erişimini Birleştirme konulu blog girişini inceleyin.