Bestätigung für Android Protected

Um die Absichten von Nutzern zu bestätigen, wenn sie eine sensible Transaktion wie eine Zahlung initiieren, können Sie auf unterstützten Geräten mit Android 9 (API-Level 28) oder höher die Funktion „Android geschützte Nutzereingabe“ verwenden. Wenn Sie diesen Workflow verwenden, wird der Nutzer in Ihrer App aufgefordert, eine kurze Erklärung zu genehmigen, in der er seine Absicht bestätigt, die sensible 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 geschützte Bestätigung von Android 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:

  1. Erstellen Sie einen asymmetrischen Signaturschlüssel mit der Klasse KeyGenParameterSpec.Builder. Geben Sie beim Erstellen des Schlüssels true an setUserConfirmationRequired() weiter. Rufen Sie außerdem setAttestationChallenge() auf und übergeben Sie einen geeigneten Bestätigungswert, der von der vertrauenden Partei bereitgestellt wird.

  2. Registrieren Sie den neu generierten Schlüssel und das Attestierungszertifikat Ihres Schlüssels bei der entsprechenden vertrauenden Partei.

  3. 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.

  4. 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. Der dataThatWasConfirmed-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 den ConfirmationPrompt-Builder übergeben haben. Unterschreiben Sie den dataThatWasConfirmed-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:

    1. Prüfen Sie die Signatur der Nachricht sowie die Attestierungszertifikatskette des Signaturschlüssels.
    2. 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 Attribut PURPOSE_ENCRYPT oder PURPOSE_DECRYPT hat.
    3. 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.
    4. Parse die promptText nach Informationen zur bestätigten Aktion oder Anfrage. Denken Sie daran, dass promptText der einzige Teil der Nachricht ist, den der Nutzer tatsächlich bestätigt hat. Die vertrauende Partei darf niemals davon ausgehen, dass die in extraData enthaltenen zu bestätigenden Daten den promptText entsprechen.
  5. 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.

Blogs