پذیرش حضوری اعتبارنامه‌های دیجیتال (آفلاین)

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

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

نمای کلی «ارائه آفلاین» (ISO/IEC 18013-5)

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

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

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

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

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

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

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

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

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

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

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

درستی‌سنجی حضوری به اجازه‌های سخت‌افزاری برای تعامل NFC، اسکن دوربین (برای تعامل رمزینه پاسخ‌سریع)، و انتقال داده بلوتوث کم‌مصرف نیاز دارد. اجازه‌های زیر را به 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 شناسه دیجیتال «کیف پول Google» / شناسه‌های آزمایشی 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 ≤ زمان فعلی ≤ 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 «سازمان صادرکننده» مطابقت دارد.
  4. اصالت‌سنجی دستگاه (DeviceSigned):
    • خواننده تأیید می‌کند که دستگاه ارائه‌دهنده اطلاعات کاربری دارای کلید خصوصی مربوط به DeviceKey منتشرشده در MSO امضاشده است.
    • این کار با درستی‌سنجی DeviceAuth (DeviceSignature یا DeviceMac) ازطریق SessionTranscript، مقید کردن جلسه به کلید زودگذر خواننده، و جلوگیری از حملات بازپخش و مرد میانی انجام می‌شود.

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

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

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

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

ابزارهای آزمایش و توسعه

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

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

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

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

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

رهنمودهای حریم خصوصی و تجربه کاربری برای کارت‌خوان‌های حضوری

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

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