Bu belgede, Android'in kriptografik özelliklerinin doğru şekilde kullanılması açıklanmakta ve bu özelliklerin kullanımına ilişkin bazı örnekler verilmektedir. Uygulamanız için daha fazla anahtar güvenliği gerekiyorsa Android Anahtar Deposu sistemini kullanın.
Yalnızca Android Anahtar Deposu sistemiyle sağlayıcı belirtme
Android Anahtar Deposu sistemini kullanıyorsanız bir sağlayıcı belirtmeniz gerekir.
Ancak Android, belirli bir algoritma için belirli bir sağlayıcıyı garanti etmez. Android Keystore sistemini kullanmadan bir sağlayıcı belirtmek, sonraki sürümlerde uyumluluk sorunlarına neden olabilir.
Önerilen bir algoritma seçin
Hangi algoritmayı kullanacağınızı seçme özgürlüğüne sahip olduğunuzda (ör. üçüncü taraf bir sistemle uyumluluğu gerektirmediğinizde) aşağıdaki algoritmaları kullanmanızı öneririz:
Sınıf | Öneri |
---|---|
Cipher | 256 bit anahtarlarla (AES/GCM/NoPadding gibi) CBC veya GCM modunda AES |
MessageDigest | SHA-2 ailesi (SHA-256 gibi) |
Mac | SHA-2 ailesi HMAC'si (HMACSHA256 gibi) |
İmza | ECDSA ile SHA-2 ailesi (SHA256withECDSA gibi) |
Yaygın kriptografik işlemleri gerçekleştirme
Aşağıdaki bölümlerde, uygulamanızda yaygın kriptografik işlemleri nasıl tamamlayabileceğinizi gösteren snippet'ler bulunmaktadır.
İleti şifreleme
Kotlin
val plaintext: ByteArray = ... val keygen = KeyGenerator.getInstance("AES") keygen.init(256) val key: SecretKey = keygen.generateKey() val cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING") cipher.init(Cipher.ENCRYPT_MODE, key) val ciphertext: ByteArray = cipher.doFinal(plaintext) val iv: ByteArray = cipher.iv
Java
byte[] plaintext = ...; KeyGenerator keygen = KeyGenerator.getInstance("AES"); keygen.init(256); SecretKey key = keygen.generateKey(); Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING"); cipher.init(Cipher.ENCRYPT_MODE, key); byte[] ciphertext = cipher.doFinal(plaintext); byte[] iv = cipher.getIV();
Mesaj özeti oluşturma
Kotlin
val message: ByteArray = ... val md = MessageDigest.getInstance("SHA-256") val digest: ByteArray = md.digest(message)
Java
byte[] message = ...; MessageDigest md = MessageDigest.getInstance("SHA-256"); byte[] digest = md.digest(message);
Dijital imza oluşturma
Çalışma zamanında oluşturabileceğiniz, uygulamanızla birlikte paketlenmiş bir dosyadan okuyabileceğiniz veya ihtiyaçlarınıza bağlı olarak başka bir kaynaktan alabileceğiniz imzalama anahtarını içeren bir PrivateKey
nesnenizin olması gerekir.
Kotlin
val message: ByteArray = ... val key: PrivateKey = ... val s = Signature.getInstance("SHA256withECDSA") .apply { initSign(key) update(message) } val signature: ByteArray = s.sign()
Java
byte[] message = ...; PrivateKey key = ...; Signature s = Signature.getInstance("SHA256withECDSA"); s.initSign(key); s.update(message); byte[] signature = s.sign();
Dijital imzayı doğrulama
İmzalayanın ortak anahtarını içeren bir PublicKey
nesnenize ihtiyacınız vardır. Bu nesneyi uygulamanızla birlikte paketlenmiş bir dosyadan okuyabilir, sertifikadan ayıklayabilir veya ihtiyaçlarınıza bağlı olarak başka bir kaynaktan edinebilirsiniz.
Kotlin
val message: ByteArray = ... val signature: ByteArray = ... val key: PublicKey = ... val s = Signature.getInstance("SHA256withECDSA") .apply { initVerify(key) update(message) } val valid: Boolean = s.verify(signature)
Java
byte[] message = ...; byte[] signature = ...; PublicKey key = ...; Signature s = Signature.getInstance("SHA256withECDSA"); s.initVerify(key); s.update(message); boolean valid = s.verify(signature);
Uygulamanın karmaşıklığı
Android kriptografi uygulamasında, alışılmadık görünen ancak uyumluluk endişeleri nedeniyle mevcut olan bazı ayrıntılar vardır. Bu bölümde, büyük olasılıkla karşılaşacağınız sorunlar ele alınmaktadır.
OAEP MGF1 mesaj özeti
RSA OAEP şifreleri iki farklı ileti özetiyle parametrelendirilir: "ana" özet ve MGF1 özeti. Ana özeti belirten ve MGF1 özetini belirtilmemiş durumda bırakan Cipher.getInstance("RSA/ECB/OAEPwithSHA-256andMGF1Padding")
gibi özet adlarını içeren Cipher
tanımlayıcılar vardır. Android Keystore için MGF1 karması SHA-1 kullanılırken diğer Android kriptografi sağlayıcıları için iki karma aynıdır.
Uygulamanızın kullandığı özetler üzerinde daha fazla kontrole sahip olmak için Cipher.getInstance("RSA/ECB/OAEPPadding")
'te olduğu gibi OAEPPadding ile şifre isteyin ve her iki özeti de açıkça seçmek için OAEPParameterSpec
ile init()
arasında bir değer sağlayın.
Bu durum aşağıdaki kodda gösterilmektedir:
Kotlin
val key: Key = ... val cipher = Cipher.getInstance("RSA/ECB/OAEPPadding") .apply { // To use SHA-256 the main digest and SHA-1 as the MGF1 digest init(Cipher.ENCRYPT_MODE, key, OAEPParameterSpec("SHA-256", "MGF1", MGF1ParameterSpec.SHA1, PSource.PSpecified.DEFAULT)) // To use SHA-256 for both digests init(Cipher.ENCRYPT_MODE, key, OAEPParameterSpec("SHA-256", "MGF1", MGF1ParameterSpec.SHA256, PSource.PSpecified.DEFAULT)) }
Java
Key key = ...; Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPPadding"); // To use SHA-256 the main digest and SHA-1 as the MGF1 digest cipher.init(Cipher.ENCRYPT_MODE, key, new OAEPParameterSpec("SHA-256", "MGF1", MGF1ParameterSpec.SHA1, PSource.PSpecified.DEFAULT)); // To use SHA-256 for both digests cipher.init(Cipher.ENCRYPT_MODE, key, new OAEPParameterSpec("SHA-256", "MGF1", MGF1ParameterSpec.SHA256, PSource.PSpecified.DEFAULT));
Desteği sonlandırılan işlevler
Aşağıdaki bölümlerde desteği sonlandırılan işlevler açıklanmaktadır. Uygulamanızda kullanmayın.
Bouncy Castle algoritmaları
Birçok algoritmanın Bouncy Castle uygulamaları desteklenmiyor. Bu durum yalnızca aşağıdaki örnekte gösterildiği gibi Bouncy Castle sağlayıcısını açıkça istediğiniz durumları etkiler:
Kotlin
Cipher.getInstance("AES/CBC/PKCS7PADDING", "BC") // OR Cipher.getInstance("AES/CBC/PKCS7PADDING", Security.getProvider("BC"))
Java
Cipher.getInstance("AES/CBC/PKCS7PADDING", "BC"); // OR Cipher.getInstance("AES/CBC/PKCS7PADDING", Security.getProvider("BC"));
Yalnızca Android Anahtar Deposu sistemiyle sağlayıcı belirtme hakkındaki bölümde belirtildiği gibi, belirli bir sağlayıcı istemek önerilmez. Bu kurala uyuyorsanız bu desteğin sonlandırılması sizi etkilemez.
Başlatma vektörü olmayan şifre tabanlı şifreleme anahtarları
Başlatma vektörü (IV) gerektiren şifre tabanlı şifreleme (PBE) şifreleri, uygun şekilde oluşturulmuşsa anahtardan veya açıkça iletilen bir IV'den bu vektörü alabilir. IV içermeyen bir PBE anahtarı ve açık bir IV iletmezseniz Android'deki PBE şifreleri şu anda sıfır IV olduğunu varsayar.
PBE şifrelerini kullanırken aşağıdaki kod snippet'inde gösterildiği gibi her zaman açık bir IV iletin:
Kotlin
val key: SecretKey = ... val cipher = Cipher.getInstance("PBEWITHSHA256AND256BITAES-CBC-BC") val iv = ByteArray(16) SecureRandom().nextBytes(iv) cipher.init(Cipher.ENCRYPT_MODE, key, IvParameterSpec(iv))
Java
SecretKey key = ...; Cipher cipher = Cipher.getInstance("PBEWITHSHA256AND256BITAES-CBC-BC"); byte[] iv = new byte[16]; new SecureRandom().nextBytes(iv); cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(iv));
Kripto para sağlayıcı
Android 9 (API düzeyi 28) itibarıyla Crypto Java Cryptography Architecture (JCA) sağlayıcısı kaldırıldı. Uygulamanız, aşağıdaki yöntemi çağırarak kripto sağlayıcı örneği talep ederse NoSuchProviderException
meydana gelir.
Kotlin
SecureRandom.getInstance("SHA1PRNG", "Crypto")
Java
SecureRandom.getInstance("SHA1PRNG", "Crypto");
Jetpack Security şifreleme kitaplığı
Jetpack Security şifreleme kitaplığının desteği sonlandırıldı. Bu durum yalnızca uygulama modülünüzün build.gradle
dosyasında aşağıdaki bağımlılıklara sahip olduğunuz durumları etkiler:
Groovy
dependencies { implementation "androidx.security:security-crypto:1.0.0" }
Kotlin
dependencies { implementation("androidx.security:security-crypto:1.0.0") }
Desteklenen algoritmalar
Android'de desteklenen JCA algoritma tanımlayıcıları şunlardır:
AlgorithmParameterGenerator
AlgorithmParameters
CertPathBuilder
CertPathValidator
CertStore
CertificateFactory
Cipher
KeyAgreement
KeyFactory
KeyGenerator
KeyManagerFactory
KeyPairGenerator
KeyStore
Mac
MessageDigest
SSLContext
SSLEngine.Supported
SSLSocket.Supported
SecretKeyFactory
SecureRandom
Signature
TrustManagerFactory