پذیرش حضوری مدارک دیجیتال (آفلاین)

این راهنما توضیح می‌دهد که چگونه طرفین اعتماد (RP) و توسعه‌دهندگان خواننده می‌توانند تأیید حضوری (آفلاین) اعتبارنامه‌های دیجیتال ارائه شده از Google Wallet را مطابق با استاندارد بین‌المللی ISO/IEC 18013-5 پیاده‌سازی کنند.

اعتبارنامه‌های دیجیتال در گوگل والت را می‌توان به طور ایمن در محیط‌های فیزیکی (مانند پایانه‌های فروش، محل‌های برگزاری رویدادها، دروازه‌های حمل و نقل، دستگاه‌های خواننده قانون و برنامه‌های خواننده تلفن همراه) بدون نیاز به اتصال فعال اینترنت در زمان ارائه، تأیید کرد.

مروری بر ارائه آفلاین (ISO/IEC 18013-5)

استاندارد ISO/IEC 18013-5 یک پروتکل استاندارد و سازگار برای ارائه آفلاین بین یک دارنده (دستگاه تلفن همراه کاربر که Google Wallet را اجرا می‌کند) و یک خواننده/تأییدکننده (یک ترمینال فیزیکی یا برنامه تلفن همراه همراه) تعریف می‌کند.

جریان ارائه در مراحل متمایزی رخ می‌دهد:

  1. تعامل دستگاه: دستگاه خواننده و کیف پول از طریق NFC Tap (انتقال ایستا یا مذاکره‌ای) یا اسکن کد QR ارتباط اولیه را برقرار می‌کنند. در طول این مرحله، فراداده‌های تعامل دستگاه و کلید عمومی موقت خواننده ( EReaderKey ) رد و بدل می‌شوند.
  2. اتصال انتقال داده: یک کانال بلوتوث کم‌مصرف (BLE) امن و رمزگذاری‌شده برقرار می‌شود (با دستگاه خواننده که در حالت کلاینت مرکزی یا سرور جانبی عمل می‌کند).
  3. درخواست دستگاه: دستگاه خواننده یک DeviceRequest کدگذاری شده با CBOR را ارسال می‌کند که نوع سند درخواستی (مانند org.iso.18013.5.1.mDL ) و فضاهای نام خاص و عناصر داده درخواستی را مشخص می‌کند.
  4. رضایت کاربر و تأیید هویت دستگاه: گوگل والت از کاربر می‌خواهد تا عناصر داده‌ای درخواستی را بررسی کرده و با استفاده از احراز هویت بیومتریک یا قفل صفحه، اشتراک‌گذاری را تأیید کند.
  5. پاسخ دستگاه و تأیید رمزنگاری: کیف پول یک DeviceResponse کدگذاری شده توسط CBOR حاوی شیء امنیتی موبایل (MSO) امضا شده و عناصر داده امضا شده توسط دستگاه را ارسال می‌کند. دستگاه خواننده، امضاهای رمزنگاری شده را با گواهی‌های ریشه معتبر تأیید می‌کند.

کیت توسعه نرم‌افزار متن‌باز مالتی‌پاز (Multipaz)

برای پیاده‌سازی یک برنامه‌ی خواننده یا تأییدکننده، گوگل استفاده از Multipaz را توصیه می‌کند، یک SDK متن‌باز Kotlin Multiplatform (KMP) که در ابتدا توسط گوگل توسعه داده شده و در بنیاد OpenWallet (OWF) مشارکت داشته است.

Multipaz پیاده‌سازی آماده به تولید از پروتکل‌های خواننده و کیف پول ISO/IEC 18013-5، خطوط لوله تأیید رمزنگاری، رمزگذاری/رمزگشایی CBOR و طرحواره‌های نوع سند قابل توسعه را ارائه می‌دهد.

ادغام Multipaz در برنامه Reader شما

مراحل زیر نحوه ادغام Multipaz SDK را در یک برنامه خواننده اندروید نشان می‌دهد.

مرحله ۱: اضافه کردن وابستگی‌ها

کتابخانه‌های 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")
}

مرحله ۲: پیکربندی مجوزهای اندروید

تأیید حضوری به مجوزهای سخت‌افزاری برای تعامل NFC، اسکن دوربین (برای تعامل QR) و انتقال داده با بلوتوث کم‌مصرف نیاز دارد. مجوزهای زیر را به 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>

مرحله ۳: راه‌اندازی موتور تأیید

از انتزاع‌های اتصال 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()
    }
}

مرحله ۴: ساخت 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 از اعتبارنامه‌های استاندارد شده به صورت آماده پشتیبانی می‌کند و یک معماری توسعه‌پذیر برای درخواست انواع سند سفارشی یا خاص دامنه ارائه می‌دهد.

۱. انواع سند استاندارد داخلی

کتابخانه 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 شناسه‌های تایید/تست گوگل والت com.google.wallet.idcard.1 given_name ، family_name ، birth_date ، document_number ، portrait

۲. درخواست انواع سند سفارشی

برای درخواست انواع سند سفارشی، رشته 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)
        )
    )
)

مدیریت اعتبارسنجی و اعتماد رمزنگاری‌شده

دریافت بار داده پاسخ تنها گام اول است. خوانندگان باید یک تأیید رمزنگاری چهار مرحله‌ای را برای تأیید صحت و یکپارچگی اعتبارنامه ارائه شده انجام دهند.

مرحله تأیید هدف تأیید
۱. احراز هویت صادرکننده تأیید IssuerAuth ( COSE_Sign1 ) در برابر گواهی‌های ریشه معتبر IACA
۲. بررسی پنجره اعتبار اطمینان حاصل کنید validFrom ≤ current time ≤ validUntil
۳. بررسی یکپارچگی داده‌ها محاسبه خلاصه‌های SHA-256 عناصر بازگشتی و تطبیق آنها با MSO ValueDigests
۴. احراز هویت دستگاه امضای DeviceSigned یا MAC را با استفاده از DeviceKey متصل به SessionTranscript تأیید کنید

۱. خط لوله تأیید ۴ مرحله‌ای

  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 ، اتصال جلسه به کلید موقت خواننده و جلوگیری از حملات replay و man-in-the-middle انجام می‌شود.

۲. مدیریت گواهی‌های ریشه معتبر IACA

خوانندگان تولید باید یک فروشگاه امن و محلی معتبر حاوی گواهی‌های ریشه معتبر IACA را نگهداری کنند:

  • گواهینامه‌های IACA تولیدی: گواهینامه‌های ریشه را از مراجع رسمی صادرکننده دانلود و پیکربندی کنید. به فهرست صادرکنندگان پشتیبانی‌شده و گواهینامه‌های IACA ما مراجعه کنید.
  • AAMVA VICAL: برای حوزه‌های قضایی ایالات متحده، سیستم‌های خواننده می‌توانند با سرویس فهرست مرجع صدور گواهی تأیید شده (VICAL) انجمن مدیران وسایل نقلیه موتوری آمریکا (AAMVA) ادغام شوند تا به طور خودکار لنگرهای اعتماد ایالتی را همگام‌سازی کنند.
  • ریشه‌های آزمایش سندباکس: هنگام آزمایش اعتبارنامه‌های سندباکس، اطمینان حاصل کنید که خواننده به ریشه IACA سندباکس گوگل اعتماد دارد.
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
}

احراز هویت خواننده (توصیه شده)

احراز هویت خواننده به برنامه خواننده اجازه می‌دهد تا با امضای ساختار ReaderAuthentication با استفاده از یک گواهی خواننده مجاز X.509، هویت خود را به صورت رمزنگاری به Google Wallet اثبات کند.

  • چرا توصیه می‌شود: احراز هویت خواننده به برنامه یا ترمینال خواننده شما اجازه می‌دهد تا یک هویت قابل اعتماد به کاربر ارائه دهد. اگرچه برای ویژگی‌های عمومی اولیه (مثلاً تأیید age_over_21 ) اختیاری است، اما برای ادغام خواننده‌ها به منظور افزایش اعتماد کاربر اکیداً توصیه می‌شود و ممکن است هنگام درخواست ویژگی‌های حساس (مانند شماره تأمین اجتماعی کامل، آدرس محل سکونت یا تأییدیه‌های ایالتی خاص) از نظر قانونی یا سیاستی الزامی باشد.
  • نحوه کار: دستگاه خواننده زنجیره گواهی خود را وارد کرده و رونوشت جلسه را امضا می‌کند. گوگل والت قبل از انتشار داده‌ها، هویت تأیید شده و نام سازمانی دستگاه خواننده را در صفحه رضایت به کاربر نمایش می‌دهد.

ابزارهای تست و توسعه

برای تسریع ادغام، از ابزارهای توسعه‌دهنده و پیاده‌سازی‌های مرجع زیر استفاده کنید:

  1. اپلیکیشن‌های مرجع مولتی‌پاز:
    • مخزن Multipaz را کلون کنید و برنامه نمونه اندروید IdentityReader را برای آزمایش جریان‌های تأیید فیزیکی اجرا کنید.
  2. ایجاد یک شناسه آزمایشی در گوگل والت:
  3. آزمایش تأییدکننده مبتنی بر وب:
    • از verifier.multipaz.org برای بررسی درخواست‌های CBOR، بررسی درخواست‌های مربوط به ادعا و آزمایش ارائه‌های مبتنی بر وب W3C / ISO 18013-7 استفاده کنید.

عیب‌یابی و تشخیص میدانی

جدول زیر مشکلات رایجی که در طول تأیید آفلاین با آنها مواجه می‌شوید و راه‌حل‌های پیشنهادی را فهرست می‌کند:

مشکل / علامت علت ریشه‌ای وضوح پیشنهادی
پایان زمان اتصال BLE / عدم اتصال
  • تداخل RF در محیط‌های با تراکم بالا
  • ناسازگاری حالت محیطی در مقابل حالت مرکزی در سخت‌افزار خاص خواننده.
  • وقفه‌های اسکن.
  • مطمئن شوید که دستگاه خواننده از هر دو حالت BLE Central Client و Peripheral Server پشتیبانی می‌کند.
  • پنجره اسکن BLE و فاصله زمانی را برای اسکن تهاجمی در حین تعامل فعال تنظیم کنید.
  • تأیید کنید که مذاکره در مورد اندازه MTU با موفقیت انجام شده است.
عدم موفقیت یا افت عملکرد NFC tap کاربر قبل از اینکه رکورد تحویل BLE به طور کامل منتقل شود، دستگاه تلفن همراه را از آنتن خواننده دور می‌کند.
  • به محض شروع تعامل NFC، بازخورد فوری بصری/صوتی/لمسی را در ترمینال ارائه دهید.
  • به کاربران دستور دهید تا زمانی که اتصال BLE برقرار شود، تلفن را ثابت در مقابل هدف NFC نگه دارند.
UNTRUSTED_ISSUER / خرابی زنجیره گواهی گواهی امضاکننده سند به هیچ گواهی IACA معتبری در مخزن اعتماد محلی خواننده متصل نیست.
  • بررسی کنید که گواهی ریشه صادرکننده در مخزن اعتماد خواننده بارگذاری شده باشد.
  • اگر در سندباکس آزمایش می‌کنید، تأیید کنید که Google Sandbox IACA Root بارگذاری شده باشد.
  • اطمینان حاصل کنید که فهرست گواهینامه‌های IACA (مثلاً AAMVA VICAL) به صورت دوره‌ای به‌روزرسانی می‌شوند.
INVALID_VALIDITY_INFO / تاریخ انقضای MSO
  • ساعت سیستم خواننده هماهنگ نیست.
  • امضای MSO منقضی شده است.
  • مطمئن شوید که دستگاه خواننده، زمان سیستم خود را به طور منظم از طریق NTP همگام‌سازی می‌کند.
  • از کاربر بخواهید هنگام اتصال به اینترنت، کیف پول گوگل را باز کند تا توکن‌های اعتبارسنجی به‌روزرسانی شوند.
DEVICE_AUTHENTICATION_FAILED عدم تطابق رونوشت جلسه بین دستگاه خواننده و کیف پول، یا امضای موقت نامعتبر دستگاه.
  • اطمینان حاصل کنید که بایت‌های خام دقیق DeviceEngagementBytes و EReaderKeyBytes بدون رمزگذاری مجدد در ساختار SessionTranscript حفظ می‌شوند.
خرابی مجوز اندروید ۱۲+ برنامه‌ای سعی کرد بدون مجوزهای زمان اجرا، از طریق BLE اسکن یا تبلیغ کند.
  • قبل از شروع جلسات خواننده BLUETOOTH_SCAN ، BLUETOOTH_CONNECT و BLUETOOTH_ADVERTISE را در زمان اجرا بررسی و درخواست کنید.

دستورالعمل‌های UX و حریم خصوصی برای خوانندگان حضوری

هنگام طراحی کتابخوان‌های فیزیکی و برنامه‌های همراه:

  • افشای گزینشی را در رابط کاربری تمرین کنید: فقط تصمیم یا حداقل ویژگی مورد نیاز را به اپراتور نمایش دهید (مثلاً به جای نمایش تاریخ تولد کامل، آدرس و شماره گواهینامه کاربر، یک علامت تیک سبز برجسته و عبارت « سن ۲۱+ تأیید شده » را نشان دهید).
  • شاخص‌های تعامل فیزیکی واضح: منطقه هدف NFC را به وضوح برچسب‌گذاری کنید و نشانه‌های بصری (مانند انیمیشن‌ها یا نوارهای پیشرفت) را نمایش دهید که هر مرحله را نشان می‌دهند: ضربه بزنید / اسکن → اتصال → تأیید → تکمیل .
  • مدیریت داده‌های موقت: عناصر داده‌های شخصی دریافتی از کیف پول را ذخیره یا ثبت نکنید، مگر اینکه صریحاً طبق قانون مربوطه الزامی شده باشد و از طریق intentToRetain = true افشا شده باشد.