Tetap teratur dengan koleksi
Simpan dan kategorikan konten berdasarkan preferensi Anda.
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:
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
classMyConfirmationCallback:ConfirmationCallback(){overridefunonConfirmed(dataThatWasConfirmed:ByteArray?){super.onConfirmed(dataThatWasConfirmed)// Sign dataThatWasConfirmed using your generated signing key.// By completing this process, you generate a signed statement.}overridefunonDismissed(){super.onDismissed()// Handle case where user declined the prompt in the// confirmation dialog.}overridefunonCanceled(){super.onCanceled()// Handle case where your app closed the dialog before the user// responded to the prompt.}overridefunonError(e:Exception?){super.onError(e)// Handle the exception that the callback captured.}}
Java
publicclassMyConfirmationCallbackextendsConfirmationCallback{@OverridepublicvoidonConfirmed(@NonNullbyte[]dataThatWasConfirmed){super.onConfirmed(dataThatWasConfirmed);// Sign dataThatWasConfirmed using your generated signing key.// By completing this process, you generate a signed statement.}@OverridepublicvoidonDismissed(){super.onDismissed();// Handle case where user declined the prompt in the// confirmation dialog.}@OverridepublicvoidonCanceled(){super.onCanceled();// Handle case where your app closed the dialog before the user// responded to the prompt.}@OverridepublicvoidonError(Throwablee){super.onError(e);// Handle the exception that the callback captured.}}
Jika pengguna menyetujui dialog tersebut, callback onConfirmed() akan
dipanggil. BLOB dataThatWasConfirmed adalah
struktur data CBOR yang berisi,
di antara detail lainnya, teks prompt yang dilihat pengguna serta data
tambahan yang Anda teruskan ke
builder
ConfirmationPrompt. Gunakan kunci yang dibuat sebelumnya untuk menandatangani
BLOB dataThatWasConfirmed, 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
properti
PURPOSE_ENCRYPT
atau PURPOSE_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 bahwa promptText adalah satu-satunya bagian dari pesan yang
benar-benar dikonfirmasikan oleh pengguna. Pihak tepercaya tidak boleh berasumsi bahwa data
yang harus dikonfirmasi disertakan dalam extraData sesuai dengan promptText.
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.dataclassConfirmationPromptData(valsender:String,valreceiver:String,valamount:String)valmyExtraData:ByteArray=byteArrayOf()valmyDialogData=ConfirmationPromptData("Ashlyn","Jordan","$500")valthreadReceivingCallback=Executor{runnable->runnable.run()}valcallback=MyConfirmationCallback()valdialog=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.classConfirmationPromptData{Stringsender,receiver,amount;ConfirmationPromptData(Stringsender,Stringreceiver,Stringamount){this.sender=sender;this.receiver=receiver;this.amount=amount;}};finalintMY_EXTRA_DATA_LENGTH=100;byte[]myExtraData=newbyte[MY_EXTRA_DATA_LENGTH];ConfirmationPromptDatamyDialogData=newConfirmationPromptData("Ashlyn","Jordan","$500");ExecutorthreadReceivingCallback=Runnable::run;MyConfirmationCallbackcallback=newMyConfirmationCallback();ConfirmationPromptdialog=(newConfirmationPrompt.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.
Konten dan contoh kode di halaman ini tunduk kepada lisensi yang dijelaskan dalam Lisensi Konten. Java dan OpenJDK adalah merek dagang atau merek dagang terdaftar dari Oracle dan/atau afiliasinya.
Terakhir diperbarui pada 2023-12-18 UTC.
[null,null,["Terakhir diperbarui pada 2023-12-18 UTC."],[],[],null,["# Android Protected Confirmation\n\nTo help you confirm users' intentions when they initiate a sensitive\ntransaction, such as making a payment, supported devices that run Android 9 (API\nlevel 28) or higher let you use Android Protected Confirmation. When using this\nworkflow, your app displays a prompt to the user, asking them to approve a short\nstatement that reaffirms their intent to complete the sensitive transaction.\n\nIf the user accepts the statement, your app can use a key from Android Keystore\nto sign the message shown in the dialog. The signature indicates, with very high\nconfidence, that the user has seen the statement and has agreed to it. \n**Caution:**Android Protected Confirmation doesn't provide a\nsecure information channel for the user. Your app can't assume any\nconfidentiality guarantees beyond those that the Android platform offers. In\nparticular, don't use this workflow to display sensitive information that you\nwouldn't ordinarily show on the user's device.\n\nAfter the user confirms the message, the message's integrity is assured,\nbut your app must still use data-in-transit encryption to protect the\nconfidentiality of the signed message.\n\nTo provide support for high-assurance user confirmation in your app, complete\nthe following steps:\n\n1. [Generate an asymmetric signing key](/training/articles/keystore#GeneratingANewPrivateKey)\n using the\n [`KeyGenParameterSpec.Builder`](/reference/android/security/keystore/KeyGenParameterSpec.Builder)\n class. When creating the key, pass `true` into\n [`setUserConfirmationRequired()`](/reference/android/security/keystore/KeyGenParameterSpec.Builder#setUserConfirmationRequired(boolean)).\n Also, call [`setAttestationChallenge()`](/reference/android/security/keystore/KeyGenParameterSpec.Builder#setAttestationChallenge(byte%5B%5D)),\n passing a suitable challenge value provided by the relying party.\n\n2. Enroll the newly generated key and your key's attestation certificate with\n the appropriate relying party.\n\n3. Send transaction details to your server and have it generate and return a\n binary large object (BLOB) of *extra data*. Extra data might include the\n to-be-confirmed data or parsing hints, such as the locale of the prompt string.\n\n For a more secure implementation, the BLOB must contain a cryptographic\n nonce for protection against\n [replay attacks](https://www.pcmag.com/encyclopedia/term/50439/replay-attack)\n and to disambiguate transactions.\n | **Caution:** If the extra data field includes to-be-confirmed data, the relying party must verify the equivalent data that's sent with the prompt string. Android Protected Confirmation doesn't render the extra data, so your app can't assume that the user confirmed this data.\n4. Set up the\n [`ConfirmationCallback`](/reference/android/security/ConfirmationCallback)\n object that informs your app when the user has accepted the prompt shown in a\n confirmation dialog:\n\n ### Kotlin\n\n ```kotlin\n class MyConfirmationCallback : ConfirmationCallback() {\n\n override fun onConfirmed(dataThatWasConfirmed: ByteArray?) {\n super.onConfirmed(dataThatWasConfirmed)\n // Sign dataThatWasConfirmed using your generated signing key.\n // By completing this process, you generate a signed statement.\n }\n\n override fun onDismissed() {\n super.onDismissed()\n // Handle case where user declined the prompt in the\n // confirmation dialog.\n }\n\n override fun onCanceled() {\n super.onCanceled()\n // Handle case where your app closed the dialog before the user\n // responded to the prompt.\n }\n\n override fun onError(e: Exception?) {\n super.onError(e)\n // Handle the exception that the callback captured.\n }\n }\n ```\n\n ### Java\n\n ```java\n public class MyConfirmationCallback extends ConfirmationCallback {\n\n @Override\n public void onConfirmed(@NonNull byte[] dataThatWasConfirmed) {\n super.onConfirmed(dataThatWasConfirmed);\n // Sign dataThatWasConfirmed using your generated signing key.\n // By completing this process, you generate a signed statement.\n }\n\n @Override\n public void onDismissed() {\n super.onDismissed();\n // Handle case where user declined the prompt in the\n // confirmation dialog.\n }\n\n @Override\n public void onCanceled() {\n super.onCanceled();\n // Handle case where your app closed the dialog before the user\n // responded to the prompt.\n }\n\n @Override\n public void onError(Throwable e) {\n super.onError(e);\n // Handle the exception that the callback captured.\n }\n }\n ```\n\n If the user approves the dialog, the `onConfirmed()` callback is\n called. The `dataThatWasConfirmed` BLOB is a\n [CBOR data structure](http://cbor.io/) that contains,\n among other details, the prompt text that the user saw as well as the extra\n data that you passed into the\n [`ConfirmationPrompt`](/reference/android/security/ConfirmationPrompt)\n builder. Use the previously created key to sign the\n `dataThatWasConfirmed` BLOB, then pass this BLOB, along with the\n signature and transaction details, back to the relying party.\n | **Note:** Because the key was created using [`setUserConfirmationRequired()`](/reference/android/security/keystore/KeyGenParameterSpec.Builder#setUserConfirmationRequired(boolean)), it can only be used to sign data that's returned in the `dataThatWasConfirmed` parameter. Attempting to sign any other kind of data fails.\n\n To make full use of the security assurance that Android Protected\n Confirmation offers, the relying party must perform the following steps upon\n receiving a signed message:\n 1. Check the signature over the message as well as the attestation certificate chain of the signing key.\n 2. Check that the attestation certificate has the `TRUSTED_CONFIRMATION_REQUIRED` flag set, which indicates that the signing key requires trusted user confirmation. If the signing key is an RSA key, check that it doesn't have the [`PURPOSE_ENCRYPT`](/reference/android/security/keystore/KeyProperties#PURPOSE_ENCRYPT) or [`PURPOSE_DECRYPT`](/reference/android/security/keystore/KeyProperties#PURPOSE_DECRYPT) property.\n 3. Check `extraData` to make sure that this confirmation message belongs to a new request and hasn't been processed yet. This step protects against replay attacks.\n 4. Parse the `promptText` for information about the confirmed action or request. Remember that the `promptText` is the only part of the message that the user actually confirmed. The relying party must never assume that to-be confirmed data included in `extraData` corresponds to the `promptText`.\n5. Add logic similar to that shown in the following code snippet to display the\n dialog itself:\n\n ### Kotlin\n\n ```kotlin\n // This data structure varies by app type. This is an example.\n data class ConfirmationPromptData(val sender: String,\n val receiver: String, val amount: String)\n\n val myExtraData: ByteArray = byteArrayOf()\n val myDialogData = ConfirmationPromptData(\"Ashlyn\", \"Jordan\", \"$500\")\n val threadReceivingCallback = Executor { runnable -\u003e runnable.run() }\n val callback = MyConfirmationCallback()\n\n val dialog = ConfirmationPrompt.Builder(context)\n .setPromptText(\"${myDialogData.sender}, send\n ${myDialogData.amount} to\n ${myDialogData.receiver}?\")\n .setExtraData(myExtraData)\n .build()\n dialog.presentPrompt(threadReceivingCallback, callback)\n ```\n\n ### Java\n\n ```java\n // This data structure varies by app type. This is an example.\n class ConfirmationPromptData {\n String sender, receiver, amount;\n ConfirmationPromptData(String sender, String receiver, String amount) {\n this.sender = sender;\n this.receiver = receiver;\n this.amount = amount;\n }\n };\n final int MY_EXTRA_DATA_LENGTH = 100;\n byte[] myExtraData = new byte[MY_EXTRA_DATA_LENGTH];\n ConfirmationPromptData myDialogData = new ConfirmationPromptData(\"Ashlyn\", \"Jordan\", \"$500\");\n Executor threadReceivingCallback = Runnable::run;\n MyConfirmationCallback callback = new MyConfirmationCallback();\n ConfirmationPrompt dialog = (new ConfirmationPrompt.Builder(getApplicationContext()))\n .setPromptText(\"${myDialogData.sender}, send ${myDialogData.amount} to ${myDialogData.receiver}?\")\n .setExtraData(myExtraData)\n .build();\n dialog.presentPrompt(threadReceivingCallback, callback);\n ```\n | **Note:** The confirmation prompt UI, which consists of a full-screen dialog, isn't customizable. However, the framework takes care of localizing button text for you.\n\nAdditional resources\n--------------------\n\nFor more information about Android Protected Confirmation, consult the following\nresources.\n\n### Blogs\n\n- [Android Protected Confirmation: Taking transaction security to the next\n level](https://android-developers.googleblog.com/2018/10/android-protected-confirmation.html)"]]