Damit du die Absichten der Nutzer überprüfen kannst, wenn sie eine vertrauliche Transaktion initiieren, z. B. eine Zahlung ausführen, kannst du auf unterstützten Geräten mit Android 9 (API-Level 28) oder höher die Android Protected Confirmation verwenden. Bei Verwendung dieses Workflows zeigt Ihre App dem Nutzer eine Aufforderung an, in der er aufgefordert wird, eine kurze Anweisung zu genehmigen, die seine Absicht bekräftigt, die vertrauliche Transaktion abzuschließen.
Wenn der Nutzer die Erklärung akzeptiert, kann Ihre App einen Schlüssel aus dem Android-Schlüsselspeicher verwenden, um die im Dialogfeld angezeigte Nachricht zu signieren. Die Unterschrift gibt mit sehr hoher Wahrscheinlichkeit an, dass der Nutzer die Erklärung gelesen und ihr zugestimmt hat.
Achtung : Die Android Protected Confirmation bietet keinen sicheren Informationskanal für den Nutzer. Ihre App kann keine Vertraulichkeitsgarantien übernehmen, die über die der Android-Plattform hinausgehen. Verwenden Sie diesen Workflow insbesondere nicht, um vertrauliche Daten anzuzeigen, die Sie normalerweise nicht auf dem Gerät des Nutzers anzeigen würden.
Nachdem der Nutzer die Nachricht bestätigt hat, ist ihre Integrität gewährleistet. Ihre App muss jedoch weiterhin die Verschlüsselung während der Übertragung verwenden, um die Vertraulichkeit der signierten Nachricht zu schützen.
So unterstützen Sie die Bestätigung mit hoher Sicherheit in Ihrer App:
Erstellen Sie einen asymmetrischen Signaturschlüssel mit der Klasse
KeyGenParameterSpec.Builder
. Geben Sie beim Erstellen des Schlüsselstrue
ansetUserConfirmationRequired()
weiter. Rufen Sie außerdemsetAttestationChallenge()
auf und übergeben Sie einen geeigneten von der vertrauenden Partei bereitgestellten Bestätigungswert.Registrieren Sie den neu generierten Schlüssel und das Attestierungszertifikat Ihres Schlüssels bei der entsprechenden vertrauenden Partei.
Senden Sie Transaktionsdetails an Ihren Server und lassen Sie dort ein Binary Large Object (BLOB) mit zusätzlichen Daten generieren und zurückgeben. Zu den zusätzlichen Daten können die zu bestätigenden Daten oder Parsing-Hinweise wie die Sprache des Prompt-Strings gehören.
Für eine sicherere Implementierung muss der BLOB ein kryptografisches Nonce zum Schutz vor Replay-Angriffen und zur Unterscheidung von Transaktionen enthalten.
Richten Sie das Objekt
ConfirmationCallback
ein, das Ihre App darüber informiert, dass der Nutzer die Aufforderung in einem Bestätigungsdialogfeld akzeptiert hat: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. } }
Wenn der Nutzer das Dialogfeld genehmigt, wird der
onConfirmed()
-Callback aufgerufen. DerdataThatWasConfirmed
-BLOB ist eine CBOR-Datenstruktur, die unter anderem den Prompttext enthält, den der Nutzer gesehen hat, sowie die zusätzlichen Daten, die Sie an denConfirmationPrompt
-Builder übergeben haben. Signieren Sie dendataThatWasConfirmed
-BLOB mit dem zuvor erstellten Schlüssel und geben Sie diesen BLOB zusammen mit der Signatur und den Transaktionsdetails an die vertrauende Partei zurück.Um die Sicherheitsvorkehrungen von Android Protected Confirmation vollumfänglich zu nutzen, muss die vertrauende Partei nach Erhalt einer signierten Nachricht die folgenden Schritte ausführen:
- Prüfen Sie die Signatur der Nachricht sowie die Attestierungszertifikatskette des Signaturschlüssels.
- Prüfen Sie, ob für das Attestierungszertifikat das Flag
TRUSTED_CONFIRMATION_REQUIRED
gesetzt ist. Dies bedeutet, dass für den Signaturschlüssel die Bestätigung eines vertrauenswürdigen Nutzers erforderlich ist. Wenn der Signaturschlüssel ein RSA-Schlüssel ist, prüfen Sie, ob er nicht das AttributPURPOSE_ENCRYPT
oderPURPOSE_DECRYPT
hat. - Prüfe unter
extraData
, ob diese Bestätigungsnachricht zu einer neuen Anfrage gehört und noch nicht verarbeitet wurde. Dieser Schritt schützt vor Replay-Angriffen. - Parst
promptText
, um Informationen zur bestätigten Aktion oder Anfrage zu erhalten. Denken Sie daran, dasspromptText
der einzige Teil der Nachricht ist, den der Nutzer tatsächlich bestätigt hat. Die vertrauende Partei darf niemals davon ausgehen, dass die inextraData
enthaltenen Daten, die noch bestätigt werden müssen, dempromptText
entsprechen.
Fügen Sie eine Logik hinzu, die der im folgenden Code-Snippet gezeigten ähnelt, um den Dialogfeld selbst anzuzeigen:
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);
Weitere Informationen
Weitere Informationen zur geschützten Bestätigung von Android finden Sie in den folgenden Ressourcen.