Aby ułatwić Ci potwierdzanie zamiarów użytkowników, gdy inicjują oni transakcję związaną z poufnymi danymi, np. dokonują płatności, obsługiwane urządzenia z Androidem 9 (poziom API 28) lub nowszym umożliwiają korzystanie z zabezpieczonego potwierdzenia w Androidzie. Gdy korzystasz z tego procesu, aplikacja wyświetla użytkownikowi prośbę o zatwierdzenie krótkiego oświadczenia, które potwierdza jego zamiar dokonania transakcji związanej z poufnymi danymi.
Jeśli użytkownik zaakceptuje oświadczenie, aplikacja może użyć klucza z magazynu kluczy Androida, aby podpisać wiadomość wyświetlaną w oknie. Podpis wskazuje z bardzo dużym prawdopodobieństwem, że użytkownik zapoznał się z oświadczeniem i je zaakceptował.
Uwaga: zabezpieczone potwierdzenie w Androidzie nie zapewnia użytkownikowi bezpiecznego kanału informacyjnego. Aplikacja nie może zakładać żadnych gwarancji poufności poza tymi, które oferuje platforma Androida. W szczególności nie używaj tego procesu do wyświetlania informacji poufnych, które zwykle nie są widoczne na urządzeniu użytkownika.
Gdy użytkownik potwierdzi wiadomość, jej integralność jest zapewniona, ale aplikacja musi nadal używać szyfrowania danych w ruchu, aby chronić poufność podpisanej wiadomości.
Aby zapewnić w aplikacji obsługę potwierdzania przez użytkownika o wysokim poziomie pewności, wykonaj te czynności:
Wygeneruj asymetryczny klucz podpisywania za pomocą klasy
KeyGenParameterSpec.Builder. Podczas tworzenia klucza przekażtruedosetUserConfirmationRequired(). Wywołaj też metodęsetAttestationChallenge(), przekazując odpowiednią wartość wyzwania podaną przez stronę zależną.Zarejestruj nowo wygenerowany klucz i certyfikat atestu klucza u odpowiedniej strony zależnej.
Wyślij szczegóły transakcji na serwer i wygeneruj oraz zwróć duży obiekt binarny (BLOB) z dodatkowymi danymi. Dodatkowe dane mogą obejmować dane do potwierdzenia lub wskazówki dotyczące analizy, takie jak ustawienia regionalne ciągu znaków prompta.
Aby zapewnić większe bezpieczeństwo, obiekt BLOB musi zawierać kryptograficzną liczbę jednorazową, która chroni przed atakami typu replay i uściśla transakcje.
Skonfiguruj obiekt
ConfirmationCallback, który informuje aplikację, gdy użytkownik zaakceptuje prośbę wyświetloną w oknie potwierdzenia: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. } }
Jeśli użytkownik zatwierdzi okno, wywoływane jest wywołanie zwrotne
onConfirmed(). Obiekt BLOBdataThatWasConfirmedto struktura danych CBOR, która zawiera m.in. tekst promptu wyświetlony użytkownikowi oraz dodatkowe dane przekazane do kreatoraConfirmationPrompt. Użyj utworzonego wcześniej klucza, aby podpisać obiekt BLOBdataThatWasConfirmed, a następnie przekaż ten obiekt BLOB wraz z podpisem i szczegółami transakcji z powrotem do strony uzależnionej.Aby w pełni wykorzystać gwarancję bezpieczeństwa, jaką zapewnia zabezpieczone potwierdzenie w Androidzie, strona uzależniona musi po otrzymaniu podpisanej wiadomości wykonać te czynności:
- Sprawdź podpis wiadomości oraz łańcuch certyfikatów atestu klucza podpisywania.
- Sprawdź, czy certyfikat atestu ma ustawioną flagę
TRUSTED_CONFIRMATION_REQUIRED, która wskazuje, że klucz podpisu wymaga potwierdzenia przez zaufanego użytkownika. Jeśli klucz podpisywania jest kluczem RSA, sprawdź, czy nie ma właściwościPURPOSE_ENCRYPTaniPURPOSE_DECRYPT. - Sprawdź
extraData, aby upewnić się, że ta wiadomość z potwierdzeniem dotyczy nowej prośby i nie została jeszcze przetworzona. Ten krok chroni przed atakami typu replay. - Przeanalizuj
promptText, aby uzyskać informacje o potwierdzonym działaniu lub żądaniu. Pamiętaj, żepromptTextto jedyna część wiadomości, którą użytkownik faktycznie potwierdził. Strona uzależniona nie może zakładać, że dane do potwierdzenia zawarte wextraDataodpowiadająpromptText.
Aby wyświetlić okno, dodaj logikę podobną do tej pokazanej w tym fragmencie kodu:
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);
Dodatkowe materiały
Więcej informacji o Zabezpieczonym potwierdzeniu w Androidzie znajdziesz w tych materiałach.