Android anahtar deposu sistemi

Android Anahtar Deposu sistemi, kriptografik anahtarların cihazdan çıkarılmasını zorlaştırmak için bunları bir kapsayıcıda saklamanıza olanak tanır. Anahtarlar anahtar deposuna eklendikten sonra bunları kriptografik işlemler için kullanabilirsiniz. Anahtar materyali ise dışa aktarılamaz durumda kalır. Anahtar mağazası sistemi, anahtarların ne zaman ve nasıl kullanılabileceğini kısıtlamanıza da olanak tanır. Örneğin, anahtar kullanımı için kullanıcı kimlik doğrulaması zorunlu kılabilir veya anahtarları yalnızca belirli kriptografik modlarda kullanılacak şekilde kısıtlayabilirsiniz. Daha fazla bilgi için Güvenlik Özellikleri bölümüne bakın.

Anahtar deposu sistemi, Android 4.0'ta (API düzeyi 14) kullanıma sunulan KeyChain API'nin yanı sıra Android 4.3'te (API düzeyi 18) kullanıma sunulan Android Keystore sağlayıcı özelliği tarafından kullanılır. Bu belgede, Android Anahtar Deposu sisteminin ne zaman ve nasıl kullanılacağı ele alınmaktadır.

Güvenlik özellikleri

Android Keystore sistemi, anahtar materyalini yetkisiz kullanıma karşı iki şekilde korur. Öncelikle, anahtar materyalinin uygulama işlemlerinden ve Android cihazın tamamından çıkarılmasını engelleyerek anahtar materyalinin Android cihazın dışarısından yetkisiz kullanımı riskini azaltır. İkinci olarak, anahtar mağazası sistemi, uygulamaların anahtarlarının yetkili kullanımlarını belirtmesini sağlayıp bu kısıtlamaları uygulamaların işlemlerinin dışında uygulayarak Android cihazda anahtar materyalinin yetkisiz kullanımı riskini azaltır.

Ayıklamanın önlenmesi

Android Keystore anahtarlarının anahtar materyali, iki güvenlik önlemi kullanılarak ayıklamaya karşı korunur:

  • Anahtar materyali hiçbir zaman başvuru sürecine dahil edilmez. Bir uygulama, Android Anahtar Deposu anahtarı kullanarak kriptografik işlemler gerçekleştirdiğinde, arka planda açık metin, şifrelenmiş metin ve imzalanacak veya doğrulanacak mesajlar, kriptografik işlemleri yürüten bir sistem işlemine beslenir. Uygulamanın işleminin güvenliği ihlal edilirse saldırgan uygulamanın anahtarlarını kullanabilir ancak anahtar materyalini ayıklayamaz (ör. Android cihazın dışında kullanılmak üzere).
  • Anahtar materyali, Android cihazın güvenli donanımına (ör. Güvenilir Yürütme Ortamı (TEE) veya Güvenli Öğe (SE)) bağlanabilir. Bir anahtar için bu özellik etkinleştirildiğinde anahtar materyali hiçbir zaman güvenli donanımın dışında gösterilmez. Android OS'nin güvenliği ihlal edilirse veya saldırgan cihazın dahili depolama alanını okuyabilirse Android cihazdaki herhangi bir uygulamanın Android Keystore anahtarlarını kullanabilir ancak bunları cihazdan çıkaramaz. Bu özellik yalnızca cihazın güvenli donanımı, anahtarın kullanılmasına izin verilen anahtar algoritması, blok modları, dolgu şemaları ve özetlerin belirli bir kombinasyonunu destekliyorsa etkinleştirilir.

    Özelliğin bir anahtar için etkin olup olmadığını kontrol etmek üzere KeyInfo anahtarını edinin. Sonraki adım, uygulamanızın hedeflediği SDK sürümüne bağlıdır:

    • Uygulamanız Android 10 (API düzeyi 29) veya sonraki sürümleri hedefliyorsa getSecurityLevel() değerinin döndürülen değerini inceleyin. KeyProperties.SecurityLevelEnum.TRUSTED_ENVIRONMENT veya KeyProperties.SecurityLevelEnum.STRONGBOX ile eşleşen döndürülen değerler, anahtarın güvenli donanımda olduğunu gösterir.
    • Uygulamanız Android 9'u (API düzeyi 28) veya daha eski sürümleri hedefliyorsa KeyInfo.isInsideSecurityHardware() işlevinin döndürdüğü boole değerini inceleyin.

StrongBox KeyMint güvenlik unsuru

Android 9 (API düzeyi 28) veya sonraki sürümleri çalıştıran cihazlarda StrongBox tarafından desteklenen KeyMint HAL'in bir uygulaması olan StrongBox KeyMint bulunabilir. Donanım güvenlik modülleri (HSM'ler) genel olarak Linux çekirdeğinin güvenliğinin ihlal edilmesine karşı dirençli güvenli anahtar depolama çözümlerini ifade ederken StrongBox, TEE'ye kıyasla daha güçlü izolasyon ve müdahaleye karşı direnç sağlayan, yerleşik SE'lerde veya entegre Secure Enclave'larda (iSE) uygulanan çözümleri ifade eder.

StrongBox KeyMint uygulaması aşağıdakileri içermelidir:

  • Kendi CPU'su
  • Güvenli depolama alanı
  • Gerçek bir rastgele sayı üreteci
  • Paket kurcalamasına ve uygulamaların yetkisiz olarak harici yüklenmesine karşı ek mekanizmalar
  • Güvenli bir zamanlayıcı
  • Genel amaçlı giriş/çıkış (GPIO) gibi bir yeniden başlatma bildirimi pini (veya eşdeğeri)

Düşük güçlü StrongBox uygulamalarını desteklemek için bir algoritma ve anahtar boyutu alt kümesi desteklenir:

  • RSA 2048
  • AES 128 ve 256
  • ECDSA, ECDH P-256
  • HMAC-SHA256 (8 ile 64 bayt arasında anahtar boyutlarını destekler)
  • Üçlü DES
  • Genişletilmiş uzunluk APDU'ları

StrongBox, anahtar onayı özelliğini de destekler.

StrongBox KeyMint'i kullanma

StrongBox'un bir cihazda kullanılıp kullanılamadığını kontrol etmek için FEATURE_STRONGBOX_KEYSTORE simgesini kullanın. StrongBox kullanılabiliyorsa true değerini aşağıdaki yöntemlere ileterek anahtarı StrongBox KeyMint'te depolama tercihinizi belirtebilirsiniz:

StrongBox KeyMint, belirtilen algoritmayı veya anahtar boyutunu desteklemiyorsa çerçeve bir StrongBoxUnavailableException hatası oluşturur. Bu durumda, setIsStrongBoxBacked(true)'ü aramadan anahtarı oluşturun veya içe aktarın.

Anahtar kullanımı yetkilendirmeleri

Android Keystore, Android cihazda anahtarların yetkisiz kullanımını önlemek için uygulamaların anahtarları oluştururken veya içe aktarırken anahtarlarının yetkili kullanımlarını belirtmesine olanak tanır. Oluşturulan veya içe aktarılan anahtarların yetkileri değiştirilemez. Ardından, anahtar her kullanıldığında Android Keystore tarafından yetkilendirmeler zorunlu kılınır. Bu, yalnızca anahtar oluşturma/içe aktarma işleminden sonra (ancak öncesinde veya sırasında değil) uygulama sürecinizin güvenliğinin ihlal edilmesi durumunda anahtarın yetkisiz kullanımına yol açılmaması şartıyla yararlı olan gelişmiş bir güvenlik özelliğidir.

Desteklenen anahtar kullanımı yetkilendirmeleri aşağıdaki kategorilere ayrılır:

  • Şifreleme: Anahtar yalnızca yetkili anahtar algoritmaları, işlemleri veya amaçları (şifreleme, şifre çözme, imzalama, doğrulama), dolgu şemaları, blok modları veya karma oluşturma işlemleriyle kullanılabilir.
  • Zamansal geçerlilik aralığı: Anahtar yalnızca tanımlanmış bir zaman aralığında kullanılmak üzere yetkilendirilir.
  • Kullanıcı kimlik doğrulaması: Anahtar yalnızca kullanıcının kimliği yakın zamanda doğrulanmışsa kullanılabilir. Anahtar kullanımı için kullanıcı kimlik doğrulaması zorunluluğu başlıklı makaleyi inceleyin.

Anahtar materyali güvenli donanımın içinde olan anahtarlar için ek bir güvenlik önlemi olarak (KeyInfo.isInsideSecurityHardware() veya Android 10 (API düzeyi 29) ve sonraki sürümleri hedefleyen uygulamalar için KeyInfo.getSecurityLevel() bölümüne bakın), bazı anahtar kullanımı yetkilendirmeleri Android cihaza bağlı olarak güvenli donanım tarafından zorunlu kılınabilir. Güvenli donanım genellikle kriptografik ve kullanıcı kimlik doğrulama yetkilendirmelerini zorunlu kılar. Ancak güvenli donanım genellikle bağımsız, güvenli bir gerçek zamanlı saate sahip olmadığından zaman geçerlilik aralığı yetkilendirmelerini zorunlu tutmaz.

KeyInfo.isUserAuthenticationRequirementEnforcedBySecureHardware() kullanarak bir anahtarın kullanıcı kimlik doğrulama yetkilendirmesinin güvenli donanım tarafından zorunlu kılınıp kılınmadığını sorgulayabilirsiniz.

Anahtar zinciri ile Android Anahtar Deposu sağlayıcısı arasında seçim yapma

Sistem genelinde kimlik bilgileri almak istediğinizde KeyChain API'yi kullanın. Bir uygulama, KeyChain API üzerinden herhangi bir kimlik bilgisinin kullanılmasını istediğinde kullanıcılar, sistemin sağladığı kullanıcı arayüzü üzerinden uygulamanın hangi yüklü kimlik bilgilerine erişebileceğini seçebilir. Bu, birden fazla uygulamanın kullanıcı izniyle aynı kimlik bilgisi grubunu kullanmasına olanak tanır.

Bir uygulamanın kendi kimlik bilgilerini depolamasına ve yalnızca bu uygulamanın bu bilgilere erişmesine izin vermek için Android Keystore sağlayıcısını kullanın. Bu sayede uygulamalar, yalnızca kendilerinin kullanabileceği kimlik bilgilerini yönetebilir ve KeyChain API'nin sistem genelindeki kimlik bilgileri için sağladığı güvenlik avantajlarından yararlanabilir. Bu yöntemde kullanıcının kimlik bilgilerini seçmesi gerekmez.

Android Keystore sağlayıcısını kullanma

Bu özelliği kullanmak için Android 4.3'te (API düzeyi 18) kullanıma sunulan AndroidKeyStore sağlayıcısıyla birlikte standart KeyStore ve KeyPairGenerator ya da KeyGenerator sınıflarını kullanırsınız.

AndroidKeyStore, KeyStore.getInstance(type) yöntemiyle kullanılmak üzere KeyStore türü olarak ve KeyPairGenerator.getInstance(algorithm, provider) ile KeyGenerator.getInstance(algorithm, provider) yöntemleriyle kullanılmak üzere sağlayıcı olarak kaydedilir.

Şifreleme işlemleri zaman alıcı olabileceğinden, uygulamaların kullanıcı arayüzünün duyarlı kalmasını sağlamak için ana iş parçacığında AndroidKeyStore kullanmaması gerekir. (StrictMode, bunun geçerli olmadığı yerleri bulmanıza yardımcı olabilir.)

Yeni bir özel veya gizli anahtar oluşturma

PrivateKey içeren yeni bir KeyPair oluşturmak için sertifikanın ilk X.509 özelliklerini belirtmeniz gerekir. Sertifikayı daha sonra bir sertifika yetkilisi (CA) tarafından imzalanmış bir sertifikayla değiştirmek için KeyStore.setKeyEntry() simgesini kullanabilirsiniz.

Anahtar çiftini oluşturmak için KeyPairGenerator ile KeyGenParameterSpec 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 aktarma

Android 9 (API düzeyi 28) ve sonraki sürümler, ASN.1 kodlamalı bir anahtar biçimi kullanarak şifrelenmiş anahtarları anahtar deposuna güvenli bir şekilde içe aktarmanıza olanak tanır. Ardından anahtar yöneticisi, anahtar anahtarlığındaki anahtarların şifresini çözer. Böylece anahtarların içeriği hiçbir zaman cihazın ana belleğinde açık 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:

  1. PURPOSE_WRAP_KEY amacını kullanan bir anahtar çifti oluşturun. Bu anahtar çiftine de doğrulama eklemenizi öneririz.

  2. 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
       }
    
  3. ASN.1 mesajını bir bayt dizisi olarak ileterek bir WrappedKeyEntry nesnesi oluşturun.

  4. Bu WrappedKeyEntry nesnesini, Keystore.Entry nesnesini kabul eden setEntry() aşırı yüklemesine iletin.

Anahtar deposu girişleriyle çalışma

AndroidKeyStore sağlayıcısına tüm standart KeyStore API'leri üzerinden 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 imzalama ve doğrulama

Anahtar deposundan KeyStore.Entry'ü alarak ve 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ı zorunlu kılın

AndroidKeyStore içine bir anahtar oluştururken veya içe aktarırken anahtarın yalnızca kullanıcının kimliği doğrulanmışsa kullanılabileceğ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, yalnızca anahtar oluşturma/içe aktarma işleminden sonra (ancak öncesinde veya sırasında değil) uygulama sürecinizin güvenliğinin ihlal edilmesi durumunda kullanıcının anahtarı kullanabilmek için kimlik doğrulamasını tamamlaması şartının atlanamaması gibi durumlarda yararlı olan gelişmiş bir güvenlik özelliğidir.

Bir anahtarın yalnızca kullanıcının kimliği doğrulanmışsa kullanılmasına izin verildiğ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 yetkilendirme
Kullanıcı belirtilen kimlik bilgilerinden birini kullanarak kimliğini doğruladığı anda tüm anahtarlar kullanıma yetkili olur.
Belirli bir şifreleme işleminin süresi boyunca yetkilendirme

Belirli bir anahtarı içeren her işlem, kullanıcı tarafından ayrı ayrı yetkilendirilmelidir.

Uygulamanız, BiometricPrompt örneğinde authenticate() işlevini çağırarak bu süreci başlatır.

Oluşturduğunuz her anahtar için güçlü bir biyometri kimlik bilgisi, kilit ekranı kimlik bilgisi veya her iki kimlik bilgisi türünü de desteklemeyi seçebilirsiniz. Kullanıcının, uygulamanızın anahtarının kullandığı kimlik bilgilerini ayarlayıp ayarlamadığını belirlemek için canAuthenticate() işlevini çağırın.

Bir anahtar yalnızca biyometrik kimlik bilgilerini destekliyorsa yeni biyometrik kayıtlar eklendiğinde varsayılan olarak geçersiz kılınır. Anahtarı, yeni biyometri kayıtları eklendiğinde geçerli kalacak şekilde yapılandırabilirsiniz. Bunun için false öğesini setInvalidatedByBiometricEnrollment() öğesine 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

Sırada ne var?