Dokumen ini menjelaskan cara yang tepat untuk menggunakan fasilitas kriptografi Android dan menyertakan beberapa contoh penggunaannya. Jika aplikasi Anda membutuhkan keamanan kunci yang lebih ketat, gunakan sistem Android Keystore.
Menetapkan penyedia hanya dengan sistem Android Keystore
Jika menggunakan sistem Android Keystore, Anda harus menetapkan satu penyedia.
Namun, dalam situasi lain, Android tidak menjamin penyedia khusus untuk algoritma tertentu. Menetapkan penyedia tanpa menggunakan sistem Android Keystore dapat menyebabkan masalah kompatibilitas pada rilis mendatang.
Memilih algoritma yang direkomendasikan
Jika Anda boleh memilih algoritma apa pun yang akan digunakan (misalnya jika Anda tidak memerlukan kompatibilitas dengan sistem pihak ketiga), sebaiknya gunakan algoritma berikut:
Class | Rekomendasi |
---|---|
Cipher | AES dalam mode CBC atau GCM dengan kunci 256-bit (seperti AES/GCM/NoPadding ) |
MessageDigest | Rangkaian SHA-2 (seperti SHA-256 ) |
Mac | HMAC rangkaian SHA-2 (seperti HMACSHA256 ) |
Tanda Tangan | Rangkaian SHA-2 dengan ECDSA (seperti SHA256withECDSA ) |
Melakukan operasi kriptografi umum
Bagian berikut menyertakan cuplikan yang menunjukkan bagaimana Anda dapat melakukan operasi kriptografi umum dalam aplikasi.
Mengenkripsi pesan
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();
Membuat ringkasan pesan
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);
Membuat tanda tangan digital
Anda harus memiliki objek PrivateKey
yang berisi kunci penandatanganan, yang dapat
dibuat pada runtime, dibaca dari file yang dipaketkan dengan aplikasi Anda, atau didapatkan dari
beberapa sumber lain menurut kebutuhan Anda.
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();
Memverifikasi tanda tangan digital
Anda harus memiliki objek PublicKey
yang berisi kunci publik penanda tangan,
yang dapat dibaca dari file yang dipaketkan dengan aplikasi Anda, diekstrak dari
sertifikat, atau
diperoleh dari beberapa sumber lain menurut kebutuhan Anda.
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);
Kompleksitas penerapan
Terdapat beberapa detail penerapan kriptografi Android yang tampak tidak biasa namun tetap disediakan karena pertimbangan kompatibilitas. Bagian ini membahas beberapa detail yang kemungkinan besar akan Anda jumpai.
Ringkasan pesan MGF1 OAEP
Cipher OAEP RSA dibuat menjadi parameter oleh dua ringkasan pesan yang berbeda: ringkasan “utama”
dan ringkasan MGF1. Ada ID Cipher
yang menyertakan nama
ringkasan, seperti Cipher.getInstance("RSA/ECB/OAEPwithSHA-256andMGF1Padding")
,
yang menentukan ringkasan utama dan membiarkan ringkasan MGF1 tidak ditentukan. Untuk Android
Keystore, SHA-1 digunakan untuk ringkasan MGF1, sedangkan untuk penyedia kriptografi
Android lainnya, kedua ringkasan tersebut sama.
Untuk kontrol yang lebih menyeluruh atas ringkasan yang digunakan oleh aplikasi, minta
cipher dengan OAEPPadding, seperti dalam Cipher.getInstance("RSA/ECB/OAEPPadding")
, dan
berikan OAEPParameterSpec
ke init()
untuk memilih kedua ringkasan secara eksplisit.
Hal ini ditunjukkan dalam kode berikut:
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));
Fungsi yang tidak digunakan lagi
Bagian berikut menjelaskan fungsi yang tidak digunakan lagi. Jangan gunakan di aplikasi Anda.
Algoritma Bouncy Castle
Penerapan Bouncy Castle untuk banyak algoritma kini sudah tidak digunakan lagi. Penerapan ini hanya efektif pada situasi ketika Anda meminta penyedia Bouncy Castle secara eksplisit, seperti dalam contoh berikut:
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"));
Seperti yang tercantum pada bagian tentang menentukan penyedia hanya dengan sistem Android Keystore, meminta penyedia tertentu tidak disarankan. Jika Anda mengikuti pedoman tersebut, penghentian ini tidak akan memengaruhi Anda.
Cipher enkripsi berbasis sandi tanpa vektor inisialisasi
Cipher enkripsi berbasis sandi (PBE) yang memerlukan vektor inisialisasi (IV) dapat memperolehnya dari kunci tersebut, jika disusun secara tepat, atau dari IV yang diteruskan secara eksplisit. Jika Anda meneruskan kunci PBE yang tidak berisi IV dan tidak meneruskan IV eksplisit, cipher PBE di Android saat ini mengasumsikan IV dengan nilai nol.
Saat menggunakan cipher PBE, selalu teruskan IV eksplisit seperti dalam cuplikan kode berikut:
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));
Penyedia kripto
Mulai dari Android 9 (API level 28), penyedia Java Cryptography Architecture (JCA)
Kripto telah dihapus. Jika aplikasi Anda meminta instance
penyedia Kripto tersebut, misalnya dengan memanggil metode berikut,
NoSuchProviderException
akan terjadi.
Kotlin
SecureRandom.getInstance("SHA1PRNG", "Crypto")
Java
SecureRandom.getInstance("SHA1PRNG", "Crypto");
Library kripto keamanan Jetpack
Library kripto keamanan Jetpack tidak digunakan lagi. Hal ini hanya memengaruhi kasus saat
Anda memiliki dependensi berikut dalam file build.gradle
modul aplikasi:
Groovy
dependencies { implementation "androidx.security:security-crypto:1.0.0" }
Kotlin
dependencies { implementation("androidx.security:security-crypto:1.0.0") }
Algoritma yang didukung
Ini adalah ID algoritma JCA yang didukung di Android:
AlgorithmParameterGenerator
AlgorithmParameters
CertPathBuilder
CertPathValidator
CertStore
CertificateFactory
Cipher
KeyAgreement
KeyFactory
KeyGenerator
KeyManagerFactory
KeyPairGenerator
KeyStore
Mac
MessageDigest
SSLContext
SSLEngine.Supported
SSLSocket.Supported
SecretKeyFactory
SecureRandom
Signature
TrustManagerFactory