Zabezpieczone potwierdzenie w Androidzie

Aby pomóc Ci potwierdzić intencje użytkowników podczas inicjowania transakcji poufnych, takich jak dokonywanie płatności, obsługiwane urządzenia z Androidem 9 (poziom interfejsu API 28) lub nowszym umożliwiają korzystanie z funkcji Zabezpieczone potwierdzenie w Androidzie. Jeśli używasz tej metody aplikacja wyświetla użytkownikowi prośbę o zatwierdzenie oświadczenie potwierdzające zamiar zrealizowania transakcji poufnej.

Jeśli użytkownik zaakceptuje oświadczenie, aplikacja może użyć klucza z Keystore Androida do podpisania wiadomości wyświetlanej w oknie dialogowym. Podpis z bardzo dużym prawdopodobieństwem wskazuje, że użytkownik zapoznał się z oświadczeniem i z nim zgodził.

Uwaga: potwierdzenie chronione przez Androida nie zapewnia użytkownikowi bezpiecznego kanału informacji. Aplikacja nie może przyjąć żadnych gwarancje poufności wykraczające poza te zapewniane przez platformę Android. W szczególności nie używaj tego procesu do wyświetlania poufnych informacji, których nie wyświetlasz zwykle na urządzeniu użytkownika.

Gdy użytkownik potwierdzi wiadomość, jest pewna jej integralność. ale aplikacja nadal musi używać szyfrowania danych podczas przesyłania, poufność podpisanej wiadomości.

Aby zapewnić w aplikacji obsługę potwierdzenia tożsamości użytkownika o wysokim poziomie zabezpieczeń:

  1. Generowanie asymetrycznego klucza podpisywania za pomocą KeyGenParameterSpec.Builder zajęcia. Podczas tworzenia klucza przekaż true do setUserConfirmationRequired() Ponadto wywołaj funkcję setAttestationChallenge(), podając odpowiednią wartość wyzwania dostarczoną przez stronę pobierającą.

  2. Zarejestruj nowo wygenerowany klucz i certyfikat uwierzytelnienia klucza w odpowiedniej stronie ufającej.

  3. Wyślij szczegóły transakcji na serwer, który wygeneruje i zwróci duży obiekt binarny (BLOB) z dodatkowymi danymi. Dodatkowe dane mogą obejmować dane do potwierdzenia lub wskazówki dotyczące analizowania, takie jak ustawienia regionalne ciągu prompt.

    Aby zapewnić bezpieczniejszą implementację, BLOB musi zawierać kod kryptograficzny liczba jednorazowa dla ochrony przed ataki typu replay oraz różnicowanie transakcji.

  4. Skonfiguruj obiekt ConfirmationCallback, który informuje aplikację, gdy użytkownik zaakceptuje prompt wyświetlany w oknie potwierdzenia:

    KotlinJava
    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.
      }
    }

    Jeśli użytkownik zatwierdzi okno, wywołanie zwrotne onConfirmed() będzie . BLOB dataThatWasConfirmed to struktura danych CBOR, która zawiera m.in. tekst promptu wyświetlany użytkownikowi oraz dodatkowe dane przekazane do funkcji tworzenia ConfirmationPrompt. Użyj utworzonego wcześniej klucza, aby podpisać BLOB dataThatWasConfirmed, a następnie prześlij ten BLOB wraz z podpisem i szczegółami transakcji do strony ufającej.

    Aby w pełni korzystać z zabezpieczeń zapewnianych przez Androida po otrzymaniu potwierdzenia, strona uzależniona musi wykonać następujące czynności po odbieranie podpisanej wiadomości:

    1. Sprawdź podpis nad wiadomością oraz łańcuch certyfikatów poświadczenia klucza podpisywania.
    2. Sprawdź, czy certyfikat atestacji ma ustawiony flagę TRUSTED_CONFIRMATION_REQUIRED, która wskazuje, że klucz podpisywania wymaga potwierdzenia przez zaufanego użytkownika. Jeśli kluczem podpisywania jest klucz RSA, sprawdź, czy nie ma PURPOSE_ENCRYPT lub PURPOSE_DECRYPT usłudze.
    3. Sprawdź domenę extraData, aby upewnić się, że ta wiadomość z potwierdzeniem należy do użytkownika nową prośbę i nie została jeszcze przetworzona. Ten krok chroni przed ataki typu replay.
    4. Przeanalizuj odpowiedź promptText, aby uzyskać informacje o potwierdzonym działaniu lub żądaniu. Pamiętaj, że promptText to jedyna część wiadomości, którą użytkownik faktycznie potwierdził. Użytkownik nie może zakładać, że dane do potwierdzenia zawarte w extraData odpowiadają promptText.
  5. Aby wyświetlić sam dialog, dodaj logikę podobną do tej w następującym fragmencie kodu:

    KotlinJava
    // 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);

Dodatkowe materiały

Więcej informacji o funkcji Potwierdzenie chronione na Androida znajdziesz w tych materiałach.

Blogi