پذیرش آنلاین مدارک دیجیتال

شناسه های دیجیتال را می توان هم در برنامه و هم جریان های وب پذیرفت. برای پذیرش اعتبارنامه از Google Wallet باید:

  1. با استفاده از برنامه یا وب به دنبال دستورالعمل های ارائه شده، یکپارچه سازی کنید.
  2. از شناسه آزمایشی برای آزمایش جریان خود در جعبه ایمنی Google Wallet استفاده کنید.
  3. وقتی آماده پخش زنده شدید، این فرم را پر کنید تا شرایط خدمات پذیرش اعتبارنامه از Google Wallet را درخواست کنید و با آن موافقت کنید.

پیش نیازها

برای آزمایش ارائه شناسه ها به صورت دیجیتال، ابتدا باید با استفاده از حساب آزمایشی مورد نظر در برنامه بتای عمومی ثبت نام کنید (این باید یک حساب جی میل باشد). متعاقباً، جزئیات بعدی را به مخاطب تعیین شده Google خود ارائه دهید.

  • پیوند شرایط خدمات
  • لوگو
  • وب سایت
  • شناسه‌های بسته برنامه (برای ادغام برنامه اندروید)
    • از جمله ساخت های توسعه دهنده / اشکال زدایی
  • امضای برنامه
    • $ $ANDROID_SDK/build-tools/$BUILD_TOOLS_VERSION/apksigner verify --print-certs -v $APK
  • شناسه Gmail که برای پیوستن به نسخه بتا عمومی استفاده شد

فرمت های اعتبار پشتیبانی شده

چندین استاندارد پیشنهادی وجود دارد که فرمت داده‌های اسناد هویت دیجیتال را تعریف می‌کنند، که دو مورد از آنها جذابیت صنعت را به دست می‌آورند:

  1. mdocs - توسط ISO تعریف شده است.
  2. اعتبارنامه های قابل تأیید w3c - توسط w3c تعریف شده است.

در حالی که Android Credential Manager از هر دو فرمت پشتیبانی می کند، Google Wallet در حال حاضر فقط از شناسه های دیجیتال مبتنی بر mdoc پشتیبانی می کند.

اعتبارنامه های پشتیبانی شده

Google Wallet از 2 نوع اعتبار پشتیبانی می کند:

  1. گواهینامه رانندگی موبایل (mDL)
  2. کارت شناسایی

شما می توانید هر یک از اعتبارنامه ها را در جریان خود با یک تغییر پارامتر درخواست کنید.

تجربه کاربری

این بخش در مورد جریان ارائه آنلاین توصیه شده صحبت می کند. این جریان نمایش سن را به یک برنامه برای تحویل الکل نشان می دهد، اما UX برای وب و همچنین انواع دیگر ارائه ها مشابه است.

از کاربر خواسته می شود سن را در برنامه یا وب سایت تأیید کندکاربر اعتبارنامه های واجد شرایط موجود را می بیندکاربر صفحه تأیید را در Google Wallet می بیندکاربر برای تایید اشتراک‌گذاری، احراز هویت می‌کندداده ها به برنامه یا وب سایت ارسال می شود
از کاربر خواسته می شود سن را در برنامه یا وب سایت تأیید کند کاربر اعتبارنامه های واجد شرایط موجود را می بیند کاربر صفحه تأیید را در Google Wallet می بیند کاربر برای تایید اشتراک‌گذاری، احراز هویت می‌کند داده ها به برنامه یا وب سایت ارسال می شود

نکات کلیدی

  1. برنامه یا وب سایت در نحوه ایجاد نقطه ورود به API انعطاف پذیر است. همانطور که در مرحله 1 نشان داده شده است، توصیه می کنیم یک دکمه عمومی مانند "تأیید با شناسه دیجیتال" را نشان دهید زیرا ما انتظار داریم که گزینه های فراتر از Google Wallet از طریق API در دسترس باشد.
  2. صفحه انتخابگر در مرحله 2 توسط اندروید رندر شده است. اعتبارنامه های واجد شرایط با تطابق بین منطق ثبت نام ارائه شده توسط هر کیف پول و درخواست ارسال شده توسط طرف متکی تعیین می شود.
  3. مرحله 3 توسط Google Wallet ارائه شده است. Google Wallet نام، نشان‌واره و خط‌مشی رازداری را که برنامه‌نویس ارائه می‌کند در این صفحه نمایش می‌دهد.

یک جریان شناسه دیجیتال اضافه کنید

در صورتی که کاربر اعتبارنامه ای نداشته باشد، توصیه می کنیم پیوندی را در کنار دکمه "تأیید با شناسه دیجیتال" ارائه دهید که به Google Wallet پیوند عمیق داده می شود تا کاربر بتواند یک شناسه دیجیتال اضافه کند.

از کاربر خواسته می شود سن را در برنامه یا وب سایت تأیید کندکاربر برای دریافت شناسه دیجیتال به Google Wallet منتقل می شود
از کاربر خواسته می شود سن را در برنامه یا وب سایت تأیید کند کاربر برای دریافت شناسه دیجیتال به Google Wallet منتقل می شود

شناسه دیجیتالی موجود نیست

اگر کاربر بدون داشتن شناسه دیجیتال گزینه "تأیید با شناسه دیجیتال" را انتخاب کند این پیغام خطا نشان داده می شود.

از کاربر خواسته می شود سن را در برنامه یا وب سایت تأیید کندکاربر خطا نشان داده است این است که آنها شناسه دیجیتال ندارند
از کاربر خواسته می شود سن را در برنامه یا وب سایت تأیید کند کاربر خطا نشان داده است این است که آنها شناسه دیجیتال ندارند

API از ویژگی‌ای پشتیبانی نمی‌کند تا بی‌صدا بداند آیا کاربر شناسه‌های دیجیتالی در دسترس برای حفظ حریم خصوصی کاربر دارد یا خیر. از این رو توصیه می کنیم گزینه پیوند ورود را همانطور که نشان داده شده است اضافه کنید.

فرمت درخواست برای درخواست اعتبار شناسه از کیف پول

در اینجا نمونه ای از درخواست mdoc requestJson برای دریافت اعتبار هویت از هر کیف پول در دستگاه Android یا وب است.

{
      "requests" : [
        {
          "protocol": "openid4vp",
          "data": {<credential_request>} // This is an object, shouldn't be a string.
        }
      ]
}

درخواست رمزگذاری

client_metadata حاوی کلید عمومی رمزگذاری برای هر درخواست است. شما باید کلیدهای خصوصی را برای هر درخواست ذخیره کنید و از آن برای احراز هویت و تأیید رمزی که از برنامه کیف پول دریافت می کنید استفاده کنید.

پارامتر credential_request در requestJson شامل فیلدهای زیر است.

{
  "response_type": "vp_token",
  "response_mode": "dc_api.jwt",
  "nonce": "1234",
  "dcql_query": {
    "credentials": [
      {
        "id": "cred1",
        "format": "mso_mdoc",
        "meta": {
          "doctype_value": "org.iso.18013.5.1.mDL"  // this is for mDL. Use com.google.wallet.idcard.1 for ID pass
        },
        "claims": [
          {
            "path": [
              "org.iso.18013.5.1",
              "family_name"
            ]
          },
          {
            "path": [
              "org.iso.18013.5.1",
              "given_name"
            ]
          },
          {
            "path": [
              "org.iso.18013.5.1",
              "age_over_18"
            ]
          }
        ]
      }
    ]
  },
  "client_metadata": {
    "jwks": {
      "keys": [ // sample request encryption key
        {
          "kty": "EC",
          "crv": "P-256",
          "x": "pDe667JupOe9pXc8xQyf_H03jsQu24r5qXI25x_n1Zs",
          "y": "w-g0OrRBN7WFLX3zsngfCWD3zfor5-NLHxJPmzsSvqQ",
          "use": "enc",
          "kid" : "1",
          "alg" : "ECDH-ES",
        }
      ]
    },
    "authorization_encrypted_response_alg": "ECDH-ES",
    "authorization_encrypted_response_enc": "A128GCM"
  }
}

می‌توانید هر تعداد ویژگی پشتیبانی‌شده را از هر اعتبار هویتی ذخیره شده در Google Wallet درخواست کنید.

در برنامه

برای درخواست اعتبار هویت از برنامه‌های Android خود این مراحل را دنبال کنید:

به روز رسانی وابستگی ها

در build.gradle پروژه خود، وابستگی های خود را برای استفاده از Credential Manager (بتا) به روز کنید:

dependencies {
    implementation("androidx.credentials:credentials:1.5.0-beta01")
    // optional - needed for credentials support from play services, for devices running Android 13 and below.
    implementation("androidx.credentials:credentials-play-services-auth:1.5.0-beta01")
}

Credential Manager را پیکربندی کنید

برای پیکربندی و مقداردهی اولیه یک شی CredentialManager ، منطقی شبیه به زیر اضافه کنید:

// Use your app or activity context to instantiate a client instance of CredentialManager.
val credentialManager = CredentialManager.create(context)

ویژگی های هویت را درخواست کنید

به جای تعیین پارامترهای فردی برای درخواست های هویت، برنامه همه آنها را با هم به عنوان یک رشته JSON در CredentialOption ارائه می دهد. Credential Manager این رشته JSON را بدون بررسی محتویات آن به کیف پول‌های دیجیتال موجود منتقل می‌کند. سپس هر کیف پول مسئول موارد زیر است: - تجزیه رشته JSON برای درک درخواست هویت. - تعیین اینکه کدام یک از اعتبارنامه های ذخیره شده آن، در صورت وجود، درخواست را برآورده می کند.

ما به شرکا توصیه می کنیم حتی برای ادغام برنامه های اندروید درخواست های خود را روی سرور ایجاد کنند.

شما از requestJson از Request Format استفاده خواهید کرد که شامل request در فراخوانی تابع GetDigitalCredentialOption() است.

// The request in the JSON format to conform with
// the JSON-ified Digital Credentials API request definition.
val requestJson = generateRequestFromServer()
val digitalCredentialOption =
    GetDigitalCredentialOption(requestJson = requestJson)

// Use the option from the previous step to build the `GetCredentialRequest`.
val getCredRequest = GetCredentialRequest(
    listOf(digitalCredentialOption)
)

coroutineScope.launch {
    try {
        val result = credentialManager.getCredential(
            context = activityContext,
            request = getCredRequest
        )
        verifyResult(result)
    } catch (e : GetCredentialException) {
        handleFailure(e)
    }
}

پاسخ را تأیید و تأیید کنید

هنگامی که پاسخی را از کیف پول دریافت کردید، بررسی می کنید که آیا پاسخ موفقیت آمیز بوده و حاوی پاسخ credentialJson است یا خیر.

// Handle the successfully returned credential.
fun verifyResult(result: GetCredentialResponse) {
    val credential = result.credential
    when (credential) {
        is DigitalCredential -> {
            val responseJson = credential.credentialJson
            validateResponseOnServer(responseJson) // make a server call to validate the response
        }
        else -> {
            // Catch any unrecognized credential type here.
            Log.e(TAG, "Unexpected type of credential ${credential.type}")
        }
    }
}

// Handle failure.
fun handleFailure(e: GetCredentialException) {
  when (e) {
        is GetCredentialCancellationException -> {
            // The user intentionally canceled the operation and chose not
            // to share the credential.
        }
        is GetCredentialInterruptedException -> {
            // Retry-able error. Consider retrying the call.
        }
        is NoCredentialException -> {
            // No credential was available.
        }
        else -> Log.w(TAG, "Unexpected exception type ${e::class.java}")
    }
}

پاسخ credentialJson حاوی یک شناسه رمزگذاری شده (JWT) است که توسط W3C تعریف شده است. برنامه Wallet مسئول ایجاد این پاسخ است.

مثال:

{
  "protocol" : "openid4vp",
  "data" : {
    <encrpted_response>
  }
}

شما این پاسخ را به سرور ارسال می کنید تا صحت آن را تأیید کند. می‌توانید مراحل تأیید اعتبار پاسخ را بیابید.

وب

برای درخواست اعتبار هویت با استفاده از Digital Credentials API در Chrome، باید برای نسخه آزمایشی اولیه Digital Credentials API ثبت نام کنید.

const credentialResponse = await navigator.credentials.get({
          digital : {
          requests : [
            {
              protocol: "openid4vp",
              data: {<credential_request>} // This is an object, shouldn't be a string.
            }
          ]
        }
      })

پاسخ این api را به سرور خود برای تأیید اعتبار پاسخ ارسال کنید

مراحل اعتبارسنجی پاسخ اعتبارنامه

به محض دریافت شناسه رمزگذاری شده از برنامه یا وب سایت خود، چندین اعتبارسنجی وجود دارد که باید قبل از اعتماد به پاسخ انجام دهید.

  1. رمزگشایی پاسخ با استفاده از کلید خصوصی

    اولین قدم این است که رمز را با استفاده از کلید خصوصی ذخیره شده رمزگشایی کنید و پاسخ JSON را دریافت کنید.

    مثال پایتون:

    from jwcrypto import jwe, jwk
    
    # Retrieve the Private Key from Datastore
    reader_private_jwk = jwk.JWK.from_json(jwe_private_key_json_str)
    
    # Decrypt the JWE encrypted response from Google Wallet
    jwe_object = jwe.JWE()
    jwe_object.deserialize(encrypted_jwe_response_from_wallet)
    jwe_object.decrypt(reader_private_jwk)
    decrypted_payload_bytes = jwe_object.payload
    decrypted_data = json.loads(decrypted_payload_bytes)
    

    decrypted_data منجر به vp_token JSON می شود که حاوی اعتبارنامه است

    {
      "vp_token":
      {
        "cred1": "<credential_token>"
      }
    }
    
  2. رونوشت جلسه را ایجاد کنید

    مرحله بعدی ایجاد SessionTranscript از ISO/IEC 18013-5:2021 با ساختار Handover خاص اندروید یا وب است:

    SessionTranscript = [
      null,                // DeviceEngagementBytes not available
      null,                // EReaderKeyBytes not available
      [
        "OpenID4VPDCAPIHandover",
        AndroidHandoverDataBytes   // BrowserHandoverDataBytes for Web
      ]
    ]
    

    برای هر دو انتقال اندروید / وب، باید از همان nonce استفاده کنید که برای ایجاد credential_request استفاده کردید.

    Android Handover

        AndroidHandoverData = [
          origin,             // "android:apk-key-hash:<base64SHA256_ofAppSigningCert>",
          clientId,           // "android-origin:<app_package_name>",
          nonce,              // nonce that was used to generate credential request
        ]
    
        AndroidHandoverDataBytes = hashlib.sha256(cbor2.dumps(AndroidHandoverData)).digest()
        

    انتقال مرورگر

        BrowserHandoverData =[
          origin,               // Origin URL
          clientId,             // "web-origin:<origin>"
          nonce,               //  nonce that was used to generate credential request
        ]
    
        BrowserHandoverDataBytes = hashlib.sha256(cbor2.dumps(BrowserHandoverData)).digest()
        

    با استفاده از SessionTranscript ، DeviceResponse باید طبق بند 9 ISO/IEC 18013-5:2021 اعتبارسنجی شود. این شامل چندین مرحله است، مانند:

  3. گواهی صادرکننده دولتی را بررسی کنید. گواهینامه های IACA صادرکننده پشتیبانی شده را بررسی کنید

  4. تأیید امضای MSO (18013-5 بخش 9.1.2)

  5. محاسبه و بررسی ValueDigests برای عناصر داده (18013-5 بخش 9.1.2)

  6. تأیید امضای امضای deviceSignature (18013-5 بخش 9.1.3)

{
  "version": "1.0",
  "documents": [
    {
      "docType": "org.iso.18013.5.1.mDL",
      "issuerSigned": {
        "nameSpaces": {...}, // contains data elements
        "issuerAuth": [...]  // COSE_Sign1 w/ issuer PK, mso + sig
      },
      "deviceSigned": {
        "nameSpaces": 24(<< {} >>), // empty
        "deviceAuth": {
          "deviceSignature": [...] // COSE_Sign1 w/ device signature
        }
      }
    }
  ],
  "status": 0
}

راه حل خود را تست کنید

برای آزمایش راه حل خود، برنامه Android دارنده مرجع منبع باز ما را بسازید و اجرا کنید. در اینجا مراحل ساخت و اجرای برنامه دارنده مرجع آورده شده است:

  • مخزن برنامه های مرجع را کلون کنید
  • پروژه را در Android Studio باز کنید
  • هدف appholder را در دستگاه یا شبیه ساز Android خود بسازید و اجرا کنید.

تأیید مبتنی بر دانش صفر (ZKP).

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

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

مفاهیم کلیدی ZKP ها در هویت دیجیتال:

  • اثبات کننده: فردی که سعی در اثبات جنبه ای از هویت خود دارد.
  • تأیید کننده: نهادی که درخواست اثبات یک ویژگی هویتی را می کند.
  • The Proof: یک پروتکل رمزنگاری که به اثبات کننده اجازه می دهد تا تایید کننده صحت ادعای خود را بدون افشای اطلاعات محرمانه متقاعد کند.

ویژگی های اصلی اثبات های دانش صفر:

  • کامل بودن: اگر گفته درست باشد و هم اثبات کننده و هم تصدیق کننده صادق باشند، تصدیق کننده قانع می شود.
  • درستی: اگر گزاره نادرست باشد، یک اثبات کننده ناصادق نمی تواند (با احتمال بسیار زیاد) یک تأیید کننده صادق را متقاعد کند که درست است.
  • دانش صفر: تأییدکننده چیزی فراتر از این واقعیت که عبارت درست است، نمی‌آموزد. هیچ داده واقعی از هویت اثبات کننده فاش نشده است.

برای بازگرداندن مدرک Zero Knowledge از Google Wallet، باید قالب درخواست را به mso_mdoc_zk تغییر دهید و zk_system_type به درخواست خود اضافه کنید.

  ...
  "dcql_query": {
    "credentials": [{
      "id": "cred1",
      "format": "mso_mdoc_zk",
      "meta": {
        "doctype_value": "org.iso.18013.5.1.mDL"
        "zk_system_type": [
         {
            "system": "longfellow-libzk-v1",
            "circuit_hash": "2093f64f54c81fb2f7f96a46593951d04005784da3d479e4543e2190dcf205d6", //This will differ if you need more than 1 attribute.
            "num_attributes": 1, // number of attributes (in claims) this has can support
            "version": 2
        },
        {
            "system": "longfellow-libzk-v1",
            "circuit_hash": "2836f0df5b7c2c431be21411831f8b3d2b7694b025a9d56a25086276161f7a93", // This will differ if you need more than 1 attribute.
            "num_attributes": 1, // number of attributes (in claims) this has can support
            "version": 1
        }
       ],
       "verifier_message": "challenge"
      },
     "claims": [{
         ...