為協助您確認使用者在進行機密交易 (例如付款) 時的意圖,搭載 Android 9 (API 級別 28) 以上版本的支援裝置,您可以使用 Android 保護確認機制。使用這個工作流程時,應用程式會向使用者顯示提示,請使用者核准簡短陳述式,要求他們核准重申完成機密交易的意圖。
如果使用者接受陳述式,應用程式就能使用 Android KeyStore 中的金鑰簽署對話方塊中顯示的訊息。簽章表示使用者已看過且同意該聲明,非常有信心。
注意: Android 保護確認不會為使用者提供安全資訊管道。除了 Android 平台提供的保證外,您的應用程式不得假設此類資訊。特別是,請勿利用此工作流程來顯示通常不會出現在使用者裝置上的機密資訊。
使用者確認訊息後,我們會確保訊息的完整性,但應用程式仍須使用傳輸中資料加密功能來保護已簽署訊息的機密性。
如要為應用程式提供優質的使用者確認支援功能,請完成下列步驟:
使用
KeyGenParameterSpec.Builder
類別產生非對稱式簽署金鑰。建立金鑰時,請將true
傳遞至setUserConfirmationRequired()
。此外,請呼叫setAttestationChallenge()
,並傳遞信賴方提供的適當驗證值。透過適當的依賴方註冊新產生的金鑰和金鑰的認證憑證。
將交易明細傳送至伺服器,讓伺服器產生並傳回額外資料的二進位大型物件 (BLOB)。其他資料可能包含待確認的資料或剖析提示,例如提示字串的語言代碼。
為提升實作的安全性,BLOB 必須包含密碼編譯 Nonce,藉此防範重播攻擊並區分交易。
設定
ConfirmationCallback
物件,在使用者接受確認對話方塊中顯示的提示時,通知應用程式: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. } }
如果使用者核准對話方塊,系統會呼叫
onConfirmed()
回呼。dataThatWasConfirmed
BLOB 是一種 CBOR 資料結構,其中包含使用者看到的提示文字,以及您傳入ConfirmationPrompt
建構工具的其他資料。使用先前建立的金鑰簽署dataThatWasConfirmed
BLOB,然後將這個 BLOB 以及簽名和交易詳細資料傳回給信賴方。為了充分運用 Android 保護確認提供的安全保證,信賴方必須在收到已簽署的訊息時執行下列步驟:
- 檢查訊息的簽名及簽署金鑰的認證憑證鏈。
- 請檢查認證憑證是否已設定
TRUSTED_CONFIRMATION_REQUIRED
標記,這表示簽署金鑰需要信任的使用者確認。如果簽署金鑰是 RSA 金鑰,請確認該金鑰沒有PURPOSE_ENCRYPT
或PURPOSE_DECRYPT
屬性。 - 檢查
extraData
,確認此確認訊息屬於新的要求,且尚未處理。這個步驟可以防範重送攻擊。 - 如要取得已確認的動作或要求相關資訊,請剖析
promptText
。請注意,promptText
是使用者實際確認訊息的唯一部分。依賴方不得假設extraData
中包含的已確認資料對應promptText
。
新增類似下列程式碼片段中的邏輯,以顯示對話方塊本身:
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);
其他資源
如要進一步瞭解 Android 保護確認,請參閱下列資源。