Untuk membantu Anda mengonfirmasi niat pengguna saat mereka memulai transaksi sensitif, seperti melakukan pembayaran, perangkat yang didukung dan menjalankan Android 9 (level API 28) atau yang lebih tinggi memungkinkan Anda menggunakan Konfirmasi Dilindungi oleh Android. Saat menggunakan alur kerja ini, aplikasi Anda akan menampilkan prompt kepada pengguna untuk meminta mereka menyetujui pernyataan singkat yang menegaskan kembali niat mereka untuk menyelesaikan transaksi sensitif.
Jika pengguna menyetujui pernyataan tersebut, aplikasi Anda dapat menggunakan kunci dari Android Keystore untuk menandatangani pesan yang ditampilkan dalam dialog. Tanda tangan tersebut menunjukkan, dengan keyakinan sangat tinggi, bahwa pengguna telah melihat pernyataan tersebut dan telah menyetujuinya.
Perhatian: Konfirmasi Dilindungi oleh Android tidak menyediakan saluran informasi yang aman bagi pengguna. Aplikasi Anda tidak dapat mengasumsikan adanya jaminan kerahasiaan selain yang ditawarkan platform Android. Secara khusus, jangan gunakan alur kerja ini untuk menampilkan informasi sensitif yang biasanya tidak akan Anda tampilkan di perangkat pengguna.
Setelah pengguna mengonfirmasi pesan, integritas pesan akan terjamin, tetapi aplikasi Anda tetap harus menggunakan enkripsi data dalam pengiriman untuk melindungi kerahasiaan pesan yang ditandatangani.
Untuk memberikan dukungan konfirmasi pengguna dengan kepastian tinggi di aplikasi Anda, selesaikan langkah-langkah berikut:
Buat kunci penandatanganan asimetris menggunakan class
KeyGenParameterSpec.Builder
. Saat membuat kunci, teruskantrue
kesetUserConfirmationRequired()
. Selain itu, panggilsetAttestationChallenge()
dengan meneruskan nilai tantangan yang sesuai dan disediakan oleh pihak tepercaya.Daftarkan kunci yang baru dibuat dan sertifikat pengesahan kunci Anda dengan pihak tepercaya yang sesuai.
Kirim detail transaksi ke server Anda dan minta server tersebut membuat serta menampilkan objek besar biner (BLOB) dari data tambahan. Data tambahan mungkin termasuk data yang akan dikonfirmasi atau petunjuk penguraian, seperti lokalitas string prompt.
Untuk implementasi yang lebih aman, BLOB harus berisi nonce kriptografis untuk perlindungan terhadap serangan replay dan untuk menghilangkan kerancuan transaksi.
Siapkan objek
ConfirmationCallback
yang memberi tahu aplikasi Anda saat pengguna telah menyetujui prompt yang ditampilkan pada dialog konfirmasi:Kotlin
class MyConfirmationCallback : ConfirmationCallback() { override fun onConfirmed(dataThatWasConfirmed: ByteArray?) { super.onConfirmed(dataThatWasConfirmed) // Sign dataThatWasConfirmed using your generated signing key. // By completing this process, you generate a signed statement. } override fun onDismissed() { super.onDismissed() // Handle case where user declined the prompt in the // confirmation dialog. } override fun onCanceled() { super.onCanceled() // Handle case where your app closed the dialog before the user // responded to the prompt. } override fun onError(e: Exception?) { super.onError(e) // Handle the exception that the callback captured. } }
Java
public class MyConfirmationCallback extends ConfirmationCallback { @Override public void onConfirmed(@NonNull byte[] dataThatWasConfirmed) { super.onConfirmed(dataThatWasConfirmed); // Sign dataThatWasConfirmed using your generated signing key. // By completing this process, you generate a signed statement. } @Override public void onDismissed() { super.onDismissed(); // Handle case where user declined the prompt in the // confirmation dialog. } @Override public void onCanceled() { super.onCanceled(); // Handle case where your app closed the dialog before the user // responded to the prompt. } @Override public void onError(Throwable e) { super.onError(e); // Handle the exception that the callback captured. } }
Jika pengguna menyetujui dialog tersebut, callback
onConfirmed()
akan dipanggil. BLOBdataThatWasConfirmed
adalah struktur data CBOR yang berisi, di antara detail lainnya, teks prompt yang dilihat pengguna serta data tambahan yang Anda teruskan ke builderConfirmationPrompt
. Gunakan kunci yang dibuat sebelumnya untuk menandatangani BLOBdataThatWasConfirmed
, lalu teruskan BLOB ini, bersama dengan detail tanda tangan dan transaksi, kembali ke pihak tepercaya.Untuk sepenuhnya menggunakan jaminan keamanan yang ditawarkan Konfirmasi Dilindungi oleh Android, pihak tepercaya harus melakukan langkah-langkah berikut setelah menerima pesan yang ditandatangani:
- Periksa tanda tangan pada pesan serta rantai sertifikat pengesahan dari kunci penandatanganan.
- Periksa apakah sertifikat pengesahan menetapkan
flag
TRUSTED_CONFIRMATION_REQUIRED
, yang menunjukkan bahwa kunci penandatanganan memerlukan konfirmasi pengguna tepercaya. Jika kunci penandatanganan adalah kunci RSA, periksa apakah kunci tersebut tidak memiliki propertiPURPOSE_ENCRYPT
atauPURPOSE_DECRYPT
. - Periksa
extraData
untuk memastikan bahwa pesan konfirmasi ini milik permintaan baru dan belum diproses. Langkah ini melindungi terhadap serangan replay. - Uraikan
promptText
untuk mendapatkan informasi tentang tindakan atau permintaan yang dikonfirmasi. Ingatlah bahwapromptText
adalah satu-satunya bagian dari pesan yang benar-benar dikonfirmasikan oleh pengguna. Pihak tepercaya tidak boleh berasumsi bahwa data yang harus dikonfirmasi disertakan dalamextraData
sesuai denganpromptText
.
Tambahkan logika serupa dengan yang ditampilkan dalam cuplikan kode berikut untuk menampilkan dialog itu sendiri:
Kotlin
// This data structure varies by app type. This is an example. data class ConfirmationPromptData(val sender: String, val receiver: String, val amount: String) val myExtraData: ByteArray = byteArrayOf() val myDialogData = ConfirmationPromptData("Ashlyn", "Jordan", "$500") val threadReceivingCallback = Executor { runnable -> runnable.run() } val callback = MyConfirmationCallback() val dialog = ConfirmationPrompt.Builder(context) .setPromptText("${myDialogData.sender}, send ${myDialogData.amount} to ${myDialogData.receiver}?") .setExtraData(myExtraData) .build() dialog.presentPrompt(threadReceivingCallback, callback)
Java
// This data structure varies by app type. This is an example. class ConfirmationPromptData { String sender, receiver, amount; ConfirmationPromptData(String sender, String receiver, String amount) { this.sender = sender; this.receiver = receiver; this.amount = amount; } }; final int MY_EXTRA_DATA_LENGTH = 100; byte[] myExtraData = new byte[MY_EXTRA_DATA_LENGTH]; ConfirmationPromptData myDialogData = new ConfirmationPromptData("Ashlyn", "Jordan", "$500"); Executor threadReceivingCallback = Runnable::run; MyConfirmationCallback callback = new MyConfirmationCallback(); ConfirmationPrompt dialog = (new ConfirmationPrompt.Builder(getApplicationContext())) .setPromptText("${myDialogData.sender}, send ${myDialogData.amount} to ${myDialogData.receiver}?") .setExtraData(myExtraData) .build(); dialog.presentPrompt(threadReceivingCallback, callback);
Referensi lainnya
Untuk mengetahui informasi selengkapnya tentang Konfirmasi Dilindungi oleh Android, lihat referensi berikut.