Приём цифровых учетных данных лично (в офлайн-режиме)

В данном руководстве объясняется, как проверяющие стороны (RP) и разработчики считывателей могут реализовать личную (офлайн) проверку цифровых учетных данных, предоставленных из Google Wallet, в соответствии с международным стандартом ISO/IEC 18013-5 .

Цифровые учетные данные в Google Wallet можно безопасно проверять в физических условиях (например, на POS-терминалах, в местах проведения мероприятий, на турникетах, считывающих устройствах правоохранительных органов и мобильных приложениях для чтения) без необходимости активного подключения к интернету в момент предъявления.

Обзор офлайн-презентаций (ISO/IEC 18013-5)

Стандарт ISO/IEC 18013-5 определяет стандартизированный, совместимый протокол для автономной презентации между держателем (мобильным устройством пользователя с запущенным Google Wallet) и считывателем/верификатором (физическим терминалом или сопутствующим мобильным приложением).

Процесс презентации проходит в несколько этапов:

  1. Взаимодействие устройства: Считыватель и кошелек устанавливают первоначальный контакт посредством NFC-соединения (статическая или согласованная передача) или сканирования QR-кода . На этом этапе происходит обмен метаданными взаимодействия устройства и временным открытым ключом считывателя ( EReaderKey ).
  2. Соединение для передачи данных: устанавливается защищенный, зашифрованный канал Bluetooth Low Energy (BLE) (при этом считывающее устройство работает в режиме центрального клиента или периферийного сервера).
  3. Запрос устройства: Считыватель передает DeviceRequest в кодировке CBOR, указывающий запрашиваемый тип документа (например, org.iso.18013.5.1.mDL ), а также конкретные пространства имен и элементы данных.
  4. Согласие пользователя и аутентификация устройства: Google Wallet предлагает пользователю просмотреть запрашиваемые элементы данных и подтвердить их предоставление с помощью биометрической аутентификации или блокировки экрана.
  5. Ответ устройства и криптографическая проверка: Кошелек отправляет обратно DeviceResponse в кодировке CBOR, содержащий подписанный объект мобильной безопасности (MSO) и подписанные устройством элементы данных. Считыватель проверяет криптографические подписи по доверенным корневым сертификатам.

Комплект разработки программного обеспечения Multipaz с открытым исходным кодом

Для реализации приложения-считывателя или верификатора Google рекомендует использовать Multipaz — SDK с открытым исходным кодом для многоплатформенной разработки на Kotlin (KMP), первоначально разработанный Google и переданный в фонд OpenWallet Foundation (OWF) .

Multipaz предоставляет готовую к использованию реализацию протоколов чтения и хранения данных ISO/IEC 18013-5, конвейеров криптографической верификации, кодирования/декодирования CBOR и расширяемых схем типов документов.

Интеграция Multipaz в ваше приложение для чтения электронных книг.

Следующие шаги демонстрируют, как интегрировать SDK Multipaz в приложение для чтения Android.

Шаг 1: Добавьте зависимости

Библиотеки Multipaz опубликованы в Maven Central . Добавьте необходимые модули в файл build.gradle.kts вашего приложения:

// build.gradle.kts
dependencies {
    // Core Multipaz library (protocol engine, CBOR, crypto)
    implementation("org.multipaz:multipaz:0.100.0")

    // Android-specific platform bindings (NFC, BLE, Keystore)
    implementation("org.multipaz:multipaz-android:0.100.0")

    // Standardized document types (mDL, EU PID, etc.)
    implementation("org.multipaz:multipaz-doctypes:0.100.0")
}

Шаг 2: Настройка разрешений Android

Для подтверждения личности при личном контакте требуются аппаратные разрешения на использование NFC, сканирование камерой (для QR-кода) и передачу данных по Bluetooth Low Energy. Добавьте следующие разрешения в файл AndroidManifest.xml :

<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- NFC Engagement -->
    <uses-permission android:name="android.permission.NFC" />
    <uses-feature android:name="android.hardware.nfc" android:required="false" />

    <!-- Camera for QR Code Engagement -->
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-feature android:name="android.hardware.camera" android:required="false" />

    <!-- Bluetooth Low Energy Transport (Android 12+) -->
    <uses-permission android:name="android.permission.BLUETOOTH_SCAN"
                     android:usesPermissionFlags="neverForLocation" />
    <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />

    <!-- Legacy Bluetooth Permissions for Android 11 and lower -->
    <uses-permission android:name="android.permission.BLUETOOTH"
                     android:maxSdkVersion="30" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"
                     android:maxSdkVersion="30" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"
                     android:maxSdkVersion="30" />
</manifest>

Шаг 3: Инициализация механизма проверки

Используйте абстракции подключения VerificationHelper или Reader в Multipaz для обработки событий взаимодействия и управления жизненным циклом BLE-связи:

import org.multipaz.verification.VerificationHelper
import org.multipaz.cbor.Cbor
import org.multipaz.crypto.Crypto

class ReaderManager(private val context: android.content.Context) {

    private var verificationHelper: VerificationHelper? = null

    fun startListeningForEngagement() {
        verificationHelper = VerificationHelper.Builder(
            context = context,
            listener = object : VerificationHelper.Listener {
                override fun onDeviceConnected() {
                    // BLE channel established, send request
                    sendDeviceRequest()
                }

                override fun onResponseReceived(deviceResponseBytes: ByteArray) {
                    // Process and verify the received credential payload
                    handleDeviceResponse(deviceResponseBytes)
                }

                override fun onError(error: Throwable) {
                    // Handle transport or protocol errors
                }

                override fun onDeviceDisconnected(transportTransportSpecificTermination: Boolean) {
                    // Connection closed
                }
            }
        ).build()
    }
}

Шаг 4: Формирование запроса устройства (DeviceRequest).

Укажите тип документа и отдельные элементы данных, которые ваше приложение должно проверить. Всегда применяйте принцип минимального раскрытия информации (например, запрашивайте только age_over_21 а не полную birth_date при проверке возраста):

fun sendDeviceRequest() {
    // Specify the DocType and requested elements
    val docType = "org.iso.18013.5.1.mDL"
    val namespace = "org.iso.18013.5.1"

    // Map of requested elements: elementName -> intentToRetain
    val requestedElements = mapOf(
        "family_name" to false,
        "given_name" to false,
        "age_over_21" to false,
        "portrait" to false,
        "driving_privileges" to false
    )

    // Build ISO/IEC 18013-5 DeviceRequest structure
    val deviceRequestBytes = verificationHelper?.buildDeviceRequest(
        docType = docType,
        itemsToRequest = mapOf(namespace to requestedElements)
    )

    if (deviceRequestBytes != null) {
        verificationHelper?.sendDeviceRequest(deviceRequestBytes)
    }
}

Поддержка дополнительных типов документов (DocTypes)

Multipaz поддерживает стандартизированные учетные данные «из коробки» и предоставляет расширяемую архитектуру для запроса пользовательских или предметно-ориентированных типов документов.

1. Встроенные стандартные типы документов

Библиотека multipaz-doctypes предоставляет предопределенные модели схем для стандартных учетных данных:

Идентификатор типа документа Стандарт / Область применения Типичное пространство имен Общие элементы
org.iso.18013.5.1.mDL Мобильное водительское удостоверение ISO/IEC 18013-5 org.iso.18013.5.1 family_name , given_name , birth_date , issue_date , expiry_date , issuing_authority документ, document_number , portrait , driving_privileges , age_over_18 , age_over_21
eu.europa.ec.eudi.pid.1 Данные идентификации личности в цифровом кошельке идентификации ЕС (EUDIW) eu.europa.ec.eudi.pid.1 family_name , first_name , birth_date , nationality , issuing_country , орган, issuing_authority , personal_administrative_number
com.google.wallet.idcard.1 Идентификатор Google Wallet / Пароль / Тестовые идентификаторы com.google.wallet.idcard.1 given_name , family_name , birth_date , document_number , portrait

2. Запрос пользовательских типов документов

Для запроса пользовательских типов документов укажите целевую строку docType и соответствующие сопоставления пространств имен при создании объекта DeviceRequest :

// Example: Requesting a custom event ticket credential
val customDocType = "com.example.events.ticket"
val customNamespace = "com.example.events.ticket.1"

val customRequestedItems = mapOf(
    "ticket_id" to false,
    "event_name" to false,
    "seat_section" to false,
    "vip_access" to false
)

val multiDocRequestBytes = verificationHelper?.buildMultiDocDeviceRequest(
    documents = listOf(
        DocumentRequest(
            docType = customDocType,
            namespaces = mapOf(customNamespace to customRequestedItems)
        )
    )
)

Криптографическая верификация и управление доверием

Получение ответного содержимого — это только первый шаг. Читателям необходимо выполнить четырехэтапную криптографическую проверку для подтверждения подлинности и целостности представленных учетных данных.

Этап проверки Цель проверки
1. Аутентификация эмитента Проверьте IssuerAuth ( COSE_Sign1 ) на соответствие доверенным корневым сертификатам IACA.
2. Проверка окна действия Убедитесь, validFrom ≤ current time ≤ validUntil
3. Проверка целостности данных Вычислить дайджесты SHA-256 возвращенных элементов и сопоставить их с ValueDigests MSO.
4. Аутентификация устройства Проверьте подпись DeviceSigned или MAC-адрес, используя DeviceKey , привязанный к SessionTranscript

1. Четырехэтапный конвейер верификации

  1. Аутентификация эмитента ( IssuerAuth ):
    • Объект мобильной безопасности (MSO) подписывается органом-эмитентом (полезная нагрузка IssuerAuth ).
    • Читатель проверяет подпись COSE_Sign1 используя сертификат подписанта документа, и убеждается, что цепочка сертификатов ведет к доверенному корневому сертификату центра сертификации (IACA) .
  2. Проверка окна действия:
    • Считыватель проверяет метки времени validityInfo.validFrom и validityInfo.validUntil в MSO, сверяя их с текущими часами считывателя, чтобы убедиться, что учетные данные не истекли.
  3. Проверка целостности данных ( ValueDigests ):
    • Для каждого полученного IssuerSignedItem считыватель вычисляет его дайджест (например, SHA-256) и проверяет, совпадает ли он с соответствующей записью хеша в словаре ValueDigests оператора MSO.
  4. Аутентификация устройства ( DeviceSigned ):
    • Читатель подтверждает, что устройство, предъявляющее учетные данные, содержит закрытый ключ, соответствующий DeviceKey опубликованному внутри подписанного MSO.
    • Это достигается путем проверки DeviceAuth (либо DeviceSignature , либо DeviceMac ) через SessionTranscript , привязки сессии к временному ключу читателя и предотвращения повторного воспроизведения и атак типа «человек посередине».

2. Управление доверенными корневыми сертификатами IACA

Читатели, работающие в производственной среде, должны поддерживать защищенное локальное хранилище доверенных сертификатов, содержащее доверенные корневые сертификаты IACA:

  • Производственные сертификаты IACA: Загрузите и настройте корневые сертификаты от официальных центров выдачи. См. наш список поддерживаемых центров выдачи и сертификатов IACA .
  • AAMVA VICAL: Для юрисдикций США системы считывания могут интегрироваться со службой Verified Issuer Certificate Authority List (VICAL) Американской ассоциации администраторов транспортных средств (AAMVA) для автоматической синхронизации государственных доверенных точек.
  • Корневые ресурсы для тестирования в песочнице: При тестировании с использованием учетных данных песочницы убедитесь, что читатель доверяет корневому ресурсу IACA песочницы Google .
import org.multipaz.crypto.X509Cert

// Configure trusted IACA certificates in the trust store
val trustedCertificates = mutableListOf<X509Cert>()

// Add official state IACA certificates
trustedCertificates.add(X509Cert.fromPem(sampleStateIacaPem))

// Add Google Sandbox IACA root certificate for testing
trustedCertificates.add(X509Cert.fromPem(googleSandboxIacaPem))

val verifier = MultipazVerifier(trustStore = trustedCertificates)
val verificationResult = verifier.verify(deviceResponseBytes, sessionTranscript)

if (verificationResult.isIssuerAuthorized && verificationResult.isDeviceAuthenticated) {
    // Credential is valid and authentic
} else {
    // Reject presentation: cryptographic validation failed
}

Аутентификация читателя (рекомендуется)

Аутентификация читателя позволяет приложению для чтения криптографически подтвердить свою личность Google Wallet, подписав структуру ReaderAuthentication с использованием авторизованного сертификата читателя X.509.

  • Почему это рекомендуется: Аутентификация читателя позволяет вашему приложению или терминалу для чтения представлять пользователю доверенную личность. Хотя она необязательна для основных общедоступных атрибутов (например, проверка age_over_21 ), настоятельно рекомендуется для интеграции с приложениями для чтения, чтобы повысить доверие пользователей, и может быть обязательной по закону или в соответствии с политикой компании при запросе конфиденциальных атрибутов (таких как полный номер социального страхования, адрес проживания или рекомендации конкретного штата).
  • Как это работает: устройство чтения предоставляет цепочку сертификатов и подписывает протокол сеанса. Google Wallet отображает пользователю подтвержденную личность и название организации устройства чтения на экране согласия перед передачей данных.

Инструменты тестирования и разработки

Для ускорения интеграции используйте следующие инструменты разработчика и эталонные реализации:

  1. Справочные приложения Multipaz:
    • Клонируйте репозиторий Multipaz и запустите демонстрационное приложение IdentityReader для Android, чтобы протестировать процессы физической верификации.
  2. Создайте тестовый ID в Google Wallet:
  3. Веб-тестирование с помощью верификатора:
    • Используйте verifier.multipaz.org для проверки запросов CBOR, изучения запросов по претензиям и тестирования веб-презентаций W3C / ISO 18013-7.

Поиск и устранение неисправностей и диагностика в полевых условиях

В таблице ниже перечислены распространенные проблемы, возникающие при проверке в автономном режиме, и рекомендуемые способы их решения:

Проблема / Симптом Первопричина Рекомендуемое разрешение
Истекло время ожидания соединения BLE / Сбой подключения
  • Радиочастотные помехи в условиях высокой плотности населения.
  • Несовместимость периферийного и центрального режимов на конкретном оборудовании считывателя.
  • Истекли тайм-ауты сканирования.
  • Убедитесь, что считыватель поддерживает как режим центрального клиента BLE, так и режим периферийного сервера.
  • Настройте окно и интервал сканирования BLE для более интенсивного сканирования во время активного взаимодействия.
  • Убедитесь, что согласование размера MTU завершилось успешно.
Срабатывание NFC-метки при касании не удается или прерывается. Пользователь отводит мобильное устройство от антенны считывателя до того, как запись о передаче BLE будет полностью передана.
  • Обеспечьте мгновенную визуальную/звуковую/тактильную обратную связь на терминале, как только начнётся взаимодействие по протоколу NFC.
  • Попросите пользователей удерживать телефон неподвижно относительно NFC-метки до тех пор, пока не будет установлено BLE-соединение.
UNTRUSTED_ISSUER / Сбой цепочки сертификатов Сертификат подписанта документа не связан ни с одним доверенным сертификатом IACA в локальном хранилище доверенных сертификатов читателя.
  • Убедитесь, что корневой сертификат эмитента загружен в хранилище доверенных сертификатов читателя.
  • При тестировании в песочнице убедитесь, что корневой каталог IACA Google Sandbox загружен.
  • Необходимо периодически обновлять списки сертификатов IACA (например, AAMVA VICAL).
INVALID_VALIDITY_INFO / Срок действия MSO истек
  • Системные часы считывателя не синхронизированы.
  • Срок действия подписи MSO истек.
  • Убедитесь, что считывающее устройство регулярно синхронизирует свое системное время через NTP.
  • Предложите пользователю открыть Google Wallet, подключившись к интернету, чтобы обновить учетные данные.
DEVICE_AUTHENTICATION_FAILED Несоответствие стенограммы сессии между считывателем и кошельком или недействительная подпись временного устройства.
  • Убедитесь, что точные исходные байты DeviceEngagementBytes и EReaderKeyBytes сохранены в структуре SessionTranscript без перекодирования.
Сбой при получении разрешений в Android 12+ Приложение попыталось выполнить сканирование или передачу данных по BLE без необходимых разрешений во время выполнения.
  • Перед запуском сеансов чтения проверьте и запросите значения BLUETOOTH_SCAN , BLUETOOTH_CONNECT и BLUETOOTH_ADVERTISE во время выполнения.

Рекомендации по пользовательскому опыту и конфиденциальности для читателей, присутствующих лично.

При разработке печатных электронных книг и сопутствующих приложений:

  • Практикуйте выборочное раскрытие информации в пользовательском интерфейсе: отображайте оператору только решение или минимально необходимую информацию (например, покажите заметную зеленую галочку и надпись « Возраст 21+ подтвержден », вместо отображения полной даты рождения пользователя, адреса и номера водительского удостоверения).
  • Четкие индикаторы физического взаимодействия: Четко обозначьте целевую зону NFC и отобразите визуальные подсказки (например, анимацию или индикаторы выполнения), показывающие каждый этап: Касание / Сканирование → Подключение → Проверка → Завершено .
  • Обработка временных данных: Не сохраняйте и не регистрируйте элементы персональных данных, полученные из кошелька, если это явно не требуется применимым законодательством и не указано параметром intentToRetain = true .