Per aiutarti a confermare le intenzioni degli utenti quando avviano una transazione sensibile, ad esempio un pagamento, i dispositivi supportati con Android 9 (livello API 28) o versioni successive ti consentono di utilizzare Android Protected Confirmation. Quando utilizzi questa procedura, la tua app mostra all'utente una richiesta di approvazione di una breve dichiarazione che ribadisce la sua intenzione di completare la transazione sensibile.
Se l'utente accetta la dichiarazione, la tua app può usare una chiave dell'archivio chiavi Android per firmare il messaggio mostrato nella finestra di dialogo. La firma indica, con un livello di confidenza molto elevato, che l'utente ha letto l'informativa e l'ha accettata.
Attenzione : la conferma Android Protected non fornisce un canale sicuro per le informazioni. La tua app non può assumere alcun impegno di riservatezza oltre a quello offerto dalla piattaforma Android. In particolare, non utilizzare questo flusso di lavoro per visualizzare informazioni sensibili che normalmente non mostreresti sul dispositivo dell'utente.
Dopo che l'utente conferma il messaggio, ne viene garantita l'integrità. ma la tua app deve comunque usare la crittografia dei dati in transito per proteggere riservatezza del messaggio firmato.
Per supportare la conferma dell'utente ad alta attendibilità nella tua app, completa i seguenti passaggi:
Genera una chiave di firma asimmetrica utilizzando
KeyGenParameterSpec.Builder
: . Quando crei la chiave, passatrue
asetUserConfirmationRequired()
Inoltre, chiamasetAttestationChallenge()
, passando un valore di verifica idoneo fornito dalla parte che la utilizza.Registra la chiave appena generata e il certificato di attestazione della chiave con la parte appropriata.
Invia i dettagli della transazione al tuo server affinché generi e restituisca un binario di grandi dimensioni (BLOB) di dati aggiuntivi. I dati aggiuntivi potrebbero includere dati da confermare o suggerimenti di analisi, come le impostazioni internazionali della stringa del prompt.
Per un'implementazione più sicura, il BLOB deve contenere un nonce cryptographic per la protezione contro gli attacchi di replay e per distinguere le transazioni.
Configura l'oggetto
ConfirmationCallback
che informa la tua app quando l'utente ha accettato la richiesta visualizzata in una finestra di dialogo di conferma: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. } }
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. } }
Se l'utente approva la finestra di dialogo, il callback
onConfirmed()
viene chiamato. Il BLOBdataThatWasConfirmed
è una struttura di dati CBOR che contiene, tra gli altri dettagli, il testo della richiesta visualizzato dall'utente nonché i dati aggiuntivi che hai passato alConfirmationPrompt
generatore. Utilizza la chiave creata in precedenza per firmaredataThatWasConfirmed
BLOB, quindi passa questo BLOB, insieme al i dettagli della firma e della transazione, tornando alla parte coinvolta.Per utilizzare appieno la garanzia di sicurezza offerta da Android Protected Confirmation, la terza parte attendibile deve eseguire i seguenti passaggi al momento della ricezione di un messaggio firmato:
- Controlla la firma sul messaggio e l'attestazione della catena di certificati della chiave di firma.
- Verifica che nel certificato di attestazione sia impostato il flag
TRUSTED_CONFIRMATION_REQUIRED
, che indica che la chiave di firma richiede la conferma dell'utente attendibile. Se la chiave di firma è una chiave RSA, verifica che non abbiaPURPOSE_ENCRYPT
oppurePURPOSE_DECRYPT
proprietà. - Seleziona
extraData
per assicurarti che questo messaggio di conferma appartenga a una nuova richiesta e non sia ancora stato elaborato. Questo passaggio protegge dagli attacchi di replay. - Analizza
promptText
per informazioni sull'azione o sulla richiesta confermata. Ricorda chepromptText
è l'unica parte del messaggio che l'utente ha effettivamente confermato. La parte che si basa non deve mai presumere che i dati da confermare inclusi inextraData
corrispondano apromptText
.
Aggiungi una logica simile a quella mostrata nel seguente snippet di codice per visualizzare nella finestra di dialogo stessa:
// 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)
// 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);
Risorse aggiuntive
Per ulteriori informazioni sulla conferma Android Protected, consulta quanto segue Google Cloud.