Чтобы помочь вам подтвердить намерения пользователей, когда они инициируют конфиденциальную транзакцию, например совершение платежа, поддерживаемые устройства под управлением Android 9 (уровень API 28) или выше позволяют использовать Android Protected Confirmation. При использовании этого рабочего процесса ваше приложение отображает пользователю запрос на одобрение короткого заявления, подтверждающего его намерение завершить конфиденциальную транзакцию.
Если пользователь принимает утверждение, ваше приложение может использовать ключ из хранилища ключей Android для подписи сообщения, отображаемого в диалоговом окне. Подпись с очень высокой степенью достоверности указывает на то, что пользователь ознакомился с заявлением и согласился с ним.
Внимание: Android Protected Confirmation не обеспечивает безопасный канал передачи информации для пользователя. Ваше приложение не может принимать на себя никаких гарантий конфиденциальности, кроме тех, которые предлагает платформа Android. В частности, не используйте этот рабочий процесс для отображения конфиденциальной информации, которую вы обычно не показываете на устройстве пользователя.
После того как пользователь подтвердит сообщение, целостность сообщения гарантируется, но ваше приложение все равно должно использовать шифрование передаваемых данных для защиты конфиденциальности подписанного сообщения.
Чтобы обеспечить поддержку высоконадежного подтверждения пользователя в вашем приложении, выполните следующие действия:
Создайте асимметричный ключ подписи с помощью класса
KeyGenParameterSpec.Builder
. При создании ключа передайтеtrue
вsetUserConfirmationRequired()
. Кроме того, вызовитеsetAttestationChallenge()
, передав подходящее значение запроса, предоставленное проверяющей стороной.Зарегистрируйте вновь созданный ключ и сертификат подтверждения ключа у соответствующей проверяющей стороны.
Отправьте сведения о транзакции на свой сервер, чтобы он сгенерировал и вернул большой двоичный объект (BLOB) дополнительных данных . Дополнительные данные могут включать данные, подлежащие подтверждению, или подсказки по синтаксическому анализу, например языковой стандарт строки приглашения.
Для более безопасной реализации BLOB должен содержать криптографический одноразовый номер для защиты от атак воспроизведения и устранения неоднозначности транзакций.
Настройте объект
ConfirmationCallback
, который информирует ваше приложение, когда пользователь принял приглашение, отображаемое в диалоговом окне подтверждения:Котлин
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. } }
Если пользователь одобряет диалог, вызывается обратный вызов
onConfirmed()
.dataThatWasConfirmed
BLOB — это структура данных CBOR , которая содержит, помимо прочего, текст приглашения, который видел пользователь, а также дополнительные данные, которые вы передали в построительConfirmationPrompt
. Используйте ранее созданный ключ для подписи BLOB-объектаdataThatWasConfirmed
, а затем передайте этот BLOB-объект вместе с подписью и сведениями о транзакции обратно проверяющей стороне.Чтобы в полной мере использовать гарантии безопасности, предлагаемые Android Protected Confirmation, проверяющая сторона должна выполнить следующие шаги после получения подписанного сообщения:
- Проверьте подпись сообщения, а также цепочку сертификатов подтверждения ключа подписи.
- Убедитесь, что в сертификате аттестации установлен флаг
TRUSTED_CONFIRMATION_REQUIRED
, который указывает, что ключ подписи требует подтверждения доверенного пользователя. Если ключ подписи является ключом RSA, убедитесь, что он не имеет свойстваPURPOSE_ENCRYPT
илиPURPOSE_DECRYPT
. - Проверьте
extraData
, чтобы убедиться, что это сообщение с подтверждением относится к новому запросу и еще не обработано. Этот шаг защищает от атак повторного воспроизведения. - Проанализируйте
promptText
для получения информации о подтвержденном действии или запросе. Помните, чтоpromptText
— единственная часть сообщения, которую фактически подтвердил пользователь. Проверяющая сторона никогда не должна предполагать, что данные, подлежащие подтверждению, включенные вextraData
соответствуютpromptText
.
Добавьте логику, аналогичную показанной в следующем фрагменте кода, чтобы отобразить само диалоговое окно:
Котлин
// 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);
Дополнительные ресурсы
Для получения дополнительной информации о подтверждении защиты Android обратитесь к следующим ресурсам.
Блоги
,Чтобы помочь вам подтвердить намерения пользователей, когда они инициируют конфиденциальную транзакцию, например совершение платежа, поддерживаемые устройства под управлением Android 9 (уровень API 28) или выше позволяют использовать Android Protected Confirmation. При использовании этого рабочего процесса ваше приложение отображает пользователю запрос на одобрение короткого заявления, подтверждающего его намерение завершить конфиденциальную транзакцию.
Если пользователь принимает утверждение, ваше приложение может использовать ключ из хранилища ключей Android для подписи сообщения, отображаемого в диалоговом окне. Подпись с очень высокой степенью достоверности указывает на то, что пользователь ознакомился с заявлением и согласился с ним.
Внимание: Android Protected Confirmation не обеспечивает безопасный канал передачи информации для пользователя. Ваше приложение не может принимать на себя никаких гарантий конфиденциальности, кроме тех, которые предлагает платформа Android. В частности, не используйте этот рабочий процесс для отображения конфиденциальной информации, которую вы обычно не показываете на устройстве пользователя.
После того как пользователь подтвердит сообщение, целостность сообщения гарантируется, но ваше приложение все равно должно использовать шифрование передаваемых данных для защиты конфиденциальности подписанного сообщения.
Чтобы обеспечить поддержку высоконадежного подтверждения пользователя в вашем приложении, выполните следующие действия:
Создайте асимметричный ключ подписи с помощью класса
KeyGenParameterSpec.Builder
. При создании ключа передайтеtrue
вsetUserConfirmationRequired()
. Кроме того, вызовитеsetAttestationChallenge()
, передав подходящее значение запроса, предоставленное проверяющей стороной.Зарегистрируйте вновь созданный ключ и сертификат подтверждения ключа у соответствующей проверяющей стороны.
Отправьте сведения о транзакции на свой сервер, чтобы он сгенерировал и вернул большой двоичный объект (BLOB) дополнительных данных . Дополнительные данные могут включать данные, подлежащие подтверждению, или подсказки по синтаксическому анализу, например языковой стандарт строки приглашения.
Для более безопасной реализации BLOB должен содержать криптографический одноразовый номер для защиты от атак воспроизведения и устранения неоднозначности транзакций.
Настройте объект
ConfirmationCallback
, который информирует ваше приложение, когда пользователь принял приглашение, отображаемое в диалоговом окне подтверждения:Котлин
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. } }
Если пользователь одобряет диалог, вызывается обратный вызов
onConfirmed()
.dataThatWasConfirmed
BLOB — это структура данных CBOR , которая содержит, помимо прочего, текст приглашения, который видел пользователь, а также дополнительные данные, которые вы передали в построительConfirmationPrompt
. Используйте ранее созданный ключ для подписи BLOB-объектаdataThatWasConfirmed
, а затем передайте этот BLOB-объект вместе с подписью и сведениями о транзакции обратно проверяющей стороне.Чтобы в полной мере использовать гарантии безопасности, предлагаемые Android Protected Confirmation, проверяющая сторона должна выполнить следующие шаги после получения подписанного сообщения:
- Проверьте подпись сообщения, а также цепочку сертификатов подтверждения ключа подписи.
- Убедитесь, что в сертификате аттестации установлен флаг
TRUSTED_CONFIRMATION_REQUIRED
, который указывает, что ключ подписи требует подтверждения доверенного пользователя. Если ключ подписи является ключом RSA, убедитесь, что он не имеет свойстваPURPOSE_ENCRYPT
илиPURPOSE_DECRYPT
. - Проверьте
extraData
, чтобы убедиться, что это сообщение с подтверждением относится к новому запросу и еще не обработано. Этот шаг защищает от атак повторного воспроизведения. - Проанализируйте
promptText
для получения информации о подтвержденном действии или запросе. Помните, чтоpromptText
— это единственная часть сообщения, которую фактически подтвердил пользователь. Проверяющая сторона никогда не должна предполагать, что данные, подлежащие подтверждению, включенные вextraData
соответствуютpromptText
.
Добавьте логику, аналогичную показанной в следующем фрагменте кода, чтобы отобразить само диалоговое окно:
Котлин
// 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);
Дополнительные ресурсы
Для получения дополнительной информации о подтверждении защиты Android обратитесь к следующим ресурсам.