مرحله ۳: ادغام به‌عنوان «طرف متکی»

این راهنما توضیح می‌دهد که چگونه طرف‌های متکی مستقیم (RP)—فروشندگان، کسب‌وکارها، و توسعه‌دهندگان برنامه—Digital Credentials API را برای درخواست و اعتبارسنجی اطلاعات کاربری هویت دیجیتال در برنامه‌های Android و وب ادغام می‌کنند.

نحوه عملکرد ادغام «طرف معتمد»

هر ادغام «طرف معتمد» چهار مرحله را دنبال می‌کند. مراحل الف و پ در سرور شما اجرا می‌شوند؛ مرحله ب در برنامه Android یا مرورگر شما اجرا می‌شود. هر مرحله‌ای را انتخاب کنید تا به جزئیات پیاده‌سازی آن بروید:

قبل‌از درخواست اعتبارنامه تولید، در جعبه شنی بسازید و آزمایش کنید

هنگام اجرای مراحل الف تا ت، از دارایی‌های پیش‌اعتمادشده جعبه امن Google استفاده کنید تا بتوانید فوراً بسازید و آزمایش کنید:

درخواست امضا

درخواست‌های OpenID4VP را بااستفاده از فراداده و کلیدهای آزمایشی جعبه امن Google امضا کنید.

اعتبارنامه آزمایشی

با شناسه دیجیتال آزمایشی Utopia در حالت «جعبه امن» در دستگاه Android آزمایش کنید.

اعتبارسنجی پاسخ

issuerAuth را دربرابر گواهی Utopia Sandbox اعتبارسنجی کنید.

توالی سرتاسر بین سرور زیرینه، برنامه کارخواه یا مرورگر، و «کیف پول Google» برای درستی‌سنجی آنلاین

قالب‌ها، اعتبارنامه‌ها، و قابلیت‌های پشتیبانی‌شده

«کیف پول Google» از «مدارک دیجیتال» مبتنی بر ISO mdoc ازطریق OpenID4VP (نسخه ۱.۰) در Android 9 (سطح API‏ ۲۸) و بالاتر و در مرورگرهای پشتیبانی‌شده پشتیبانی می‌کند.

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

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

صادرکنندگان و گواهینامه‌های IACA پشتیبانی‌شده

گواهی‌های ریشه رسمی IACA را برای ایالت‌های ایالات متحده، صادرکنندگان بین‌المللی، و صادرکننده Sandbox Utopia برای اعتبارسنجی issuerAuth بارگیری کنید.


مرحله الف: قالب‌بندی و امضای درخواست (سمت سرور)

برای درخواست اعتبارنامه از هر کیف پولی، باید درخواستتان را بااستفاده از OpenID4VP در سرورتان قالب‌بندی کنید. می‌توانید یک یا چند اعتبارنامه خاص را در یک شیء dcql_query درخواست کنید.

نمونه درخواست JSON

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

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

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

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

فراداده OpenID4VP یکپارچه

هنگام قالب‌بندی درخواست اطلاعات کاربری، باید فیلد gw_rp_metadata_bytes را در شیء client_metadata اضافه کنید (همان‌طور که در نمونه کد درخواست زیر نشان داده شده است). این فیلد حاوی فراداده طرف متکی کدگذاری‌شده با Base64URL است که «کیف پول Google» برای درستی‌سنجی کردن هویت شما و نمایش نمانام‌سازی شما به کاربر به آن نیاز دارد.

پایه‌بار درخواست اطلاعات اعتباری

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

اعتبارنامه خاص

{
  "response_type": "vp_token",
  "response_mode": "dc_api.jwt", // change this to dc_api if you want to demo with a non encrypted response.
  "nonce": "1234",
  "dcql_query": {
    "credentials": [
      {
        "id": "cred1",
        "format": "mso_mdoc",
        "meta": {
          // Use org.iso.18013.5.1.mDL for mDL,
          // com.google.wallet.idcard.1 for ID pass, or
          // org.iso.23220.photoid.1 for ID pass (using photo ID document type)
          "doctype_value": "org.iso.18013.5.1.mDL"
        },
        "claims": [
          {
            "path": [
              "org.iso.18013.5.1",
              "family_name"
            ],
            "intent_to_retain": false // set this to true if you are saving the value of the field
          },
          {
            "path": [
              "org.iso.18013.5.1",
              "given_name"
            ],
            "intent_to_retain": false
          },
          {
            "path": [
              "org.iso.18013.5.1",
              "age_over_18"
            ],
            "intent_to_retain": false
          }
        ]
      }
    ]
  },
  "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",  // This is required
          "alg" : "ECDH-ES",  // This is required
        }
      ]
    },
    "vp_formats_supported": {
      "mso_mdoc": {
        "deviceauth_alg_values": [
          -7
        ],
        "issuerauth_alg_values": [
          -7
        ]
      }
    },
    "gw_rp_metadata_bytes": "<base64url encoded metadata string>"
  }
}

هرگونه اعتبارنامه واجدشرایط

در اینجا نمونه درخواست برای «گواهینامه رانندگی دیجیتال»، شناسه دیجیتال، و شناسه دیجیتال (بااستفاده از نوع مدرک شناسایی عکس‌دار) آورده شده است. کاربر می‌تواند با هرکدام که خواست ادامه دهد.

{
  "response_type": "vp_token",
  "response_mode": "dc_api.jwt", // change this to dc_api if you want to demo with a non encrypted response.
  "nonce": "1234",
  "dcql_query": {
    "credentials": [
      {
        "id": "mdl-request",
        "format": "mso_mdoc",
        "meta": {
          "doctype_value": "org.iso.18013.5.1.mDL"
        },
        "claims": [
          {
            "path": [
              "org.iso.18013.5.1",
              "family_name"
            ],
            "intent_to_retain": false // set this to true if you are saving the value of the field
          },
          {
            "path": [
              "org.iso.18013.5.1",
              "given_name"
            ],
            "intent_to_retain": false
          },
          {
            "path": [
              "org.iso.18013.5.1",
              "age_over_18"
            ],
            "intent_to_retain": false
          }
        ]
      },
      {  // Credential type 2: ID pass
        "id": "id_pass-request",
        "format": "mso_mdoc",
        "meta": {
          "doctype_value": "com.google.wallet.idcard.1"
        },
        "claims": [
          {
            "path": [
              "org.iso.18013.5.1",
              "family_name"
            ],
            "intent_to_retain": false // set this to true if you are saving the value of the field
          },
          {
            "path": [
              "org.iso.18013.5.1",
              "given_name"
            ],
            "intent_to_retain": false
          },
          {
            "path": [
              "org.iso.18013.5.1",
              "age_over_18"
            ],
            "intent_to_retain": false
          }
        ]
      },
      {  // Credential type 3: ID pass (using photo ID document type)
        "id": "photo_id-request",
        "format": "mso_mdoc",
        "meta": {
          "doctype_value": "org.iso.23220.photoid.1"
        },
        "claims": [
          {
            "path": [
              "org.iso.23220.1",
              "family_name"
            ],
            "intent_to_retain": false // set this to true if you are saving the value of the field
          },
          {
            "path": [
              "org.iso.23220.1",
              "given_name"
            ],
            "intent_to_retain": false
          },
          {
            "path": [
              "org.iso.23220.1",
              "age_over_18"
            ],
            "intent_to_retain": false
          }
        ]
      }
    ]
    credential_sets : [
      {
        "options": [
          [ "mdl-request" ],
          [ "id_pass-request" ],
          [ "photo_id-request" ]
        ]
      }
    ]
  },
  "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",  // This is required
          "alg" : "ECDH-ES",  // This is required
        }
      ]
    },
    "vp_formats_supported": {
      "mso_mdoc": {
        "deviceauth_alg_values": [
          -7
        ],
        "issuerauth_alg_values": [
          -7
        ]
      }
    },
    "gw_rp_metadata_bytes": "<base64url encoded metadata string>"
  }
}

می‌توانید هر تعداد مشخصه پشتیبانی‌شده را که می‌خواهید از هر اعتبارنامه هویتی ذخیره‌شده در «کیف پول Google» درخواست کنید.

درخواست‌های امضاشده

درخواست‌های امضاشده (درخواست‌های مجوز ایمن‌شده با JWT) درخواست ارائه قابل‌تأیید شما را در یک JSON Web Token (JWT) امضاشده با رمزنگاری بااستفاده از زیرساخت PKI شما کپسوله می‌کند، که این امر تمامیت درخواست را تضمین می‌کند و هویت شما را به «کیف پول Google» اثبات می‌کند.

پیش‌نیازها

قبل‌از اعمال تغییرات کد برای درخواست‌های امضاشده، مطمئن شوید که:

  • کلید خصوصی: برای امضای درخواست، به کلید خصوصی (برای مثال، Elliptic Curve ES256) نیاز دارید که در سرورتان مدیریت می‌شود. برای آزمایش جعبه امن به‌عنوان «طرف متکی»، از کلید خصوصی آزمایش جعبه امن استفاده کنید.
  • گواهی: به گواهی استاندارد X.509 مشتق‌شده از جفت کلیدتان نیاز دارید.
  • ثبت: مطمئن شوید گواهی عمومی شما (یا مرجع صدور گواهی ریشه برای ثبت‌کنندگان درستی‌سنج) مورد اعتماد «کیف پول Google» است.

منطق ساخت درخواست

هنگام ساختن و امضا کردن درخواست OpenID4VP، به قالب دقیق کدبندی موردانتظار برای هر فیلد توجه کنید—مخلوط کردن base64 و base64url یا فاصله‌گذاری (=) باعث می‌شود اعتبارسنجی امضا یا مبدأ ناموفق باشد:

فیلد کدبندی / قالب الزامی نویسه‌ها و حاشیه داخلی
‫client_id‏ (x509_hash:<hash>) base64url بدون لایه‌گذاری از الفبای امن برای نشانی وب (-، _) استفاده می‌کند؛ = دنباله را حذف می‌کند
‫expected_origins‏ (android:apk-key-hash:<hash>) مبنای ۶۴ استاندارد بدون لایه‌گذاری از الفبای استاندارد (+، /) استفاده می‌کند؛ = دنباله‌دار را حذف می‌کند
‫expected_origins‏ (https://...) نشانی وب با حروف کوچک بدون کج‌خط انتهایی مثال: https://example.com (بدون / در انتها)
سرایند JWS x5c برپایه ۶۴ استاندارد با لایه‌گذاری از الفبای استاندارد (+، /) استفاده می‌کند؛ لایه = دنباله‌دار را حفظ می‌کند

برای ساختن درخواست، از کلید خصوصی‌تان استفاده کنید و بار داده را در JWS قرار دهید:

def construct_openid4vp_request(
    doctypes: list[str],
    requested_fields: list[dict],
    nonce_base64: str,
    jwe_encryption_public_jwk: jwk.JWK,
    is_zkp_request: bool,
    is_signed_request: bool,
    state: dict,
    origin: str
) -> dict:

    # ... [Existing logic to build 'presentation_definition' and basic 'request_payload'] ...

    # ------------------------------------------------------------------
    # SIGNED REQUEST IMPLEMENTATION (JAR)
    # ------------------------------------------------------------------
    if is_signed_request:
        try:
            # 1. Load the Verifier's Certificate
            # We must load the PEM string into a cryptography x509 object
            verifier_cert_obj = x509.load_pem_x509_certificate(
                CERTIFICATE.encode('utf-8'),
                backend=default_backend()
            )

            # 2. Calculate Client ID (x509_hash)
            # We calculate the SHA-256 hash of the DER-encoded certificate.
            cert_der = verifier_cert_obj.public_bytes(serialization.Encoding.DER)
            verifier_fingerprint_bytes = hashlib.sha256(cert_der).digest()

            # Important: Use URL-safe Base64 (base64url: '-', '_') without padding ('=') for client_id
            verifier_fingerprint_b64 = base64.urlsafe_b64encode(verifier_fingerprint_bytes).decode('utf-8').rstrip("=")

            # Format the client_id as required by the spec
            client_id = f'x509_hash:{verifier_fingerprint_b64}'

            # 3. Update Request Payload with JAR specific fields
            request_payload["client_id"] = client_id

            # Explicitly set expected origins to prevent relay attacks
            # Important: Use standard Base64 (not URL-safe) without padding for android:apk-key-hash:
            # origin = f"android:apk-key-hash:{base64.b64encode(apk_cert_hash).decode('utf-8').rstrip('=')}"
            # Format for web origin (lowercase URL without trailing slash): origin = "https://example.com"
            if origin:
                request_payload["expected_origins"] = [origin]

            # 4. Create Signed JWT (JWS)
            # Load the signing private key
            signing_key = jwk.JWK.from_pem(PRIVATE_KEY.encode('utf-8'))

            # Initialize JWS with the JSON payload
            jws_token = jws.JWS(json.dumps(request_payload).encode('utf-8'))

            # Construct the JOSE Header
            # 'x5c' (X.509 Certificate Chain) is critical: it allows the wallet
            # to validate your key against the one registered in the console.
            # Important: Use standard Base64 ('+', '/') WITH padding ('=') for x5c
            x5c_value = base64.b64encode(cert_der).decode('utf-8')

            protected_header = {
                "alg": "ES256",                 # Algorithm (e.g., ES256 or RS256)
                "typ": "oauth-authz-req+jwt",   # Standard type for JAR
                "kid": "1",                     # Key ID
                "x5c": [x5c_value]              # Embed the certificate
            }

            # Sign the token
            jws_token.add_signature(
                key=signing_key,
                alg=None,
                protected=json_encode(protected_header)
            )

            # 5. Return the Request Object
            # Instead of returning the raw JSON, we return the signed JWT string
            # under the 'request' key.
            return {"request": jws_token.serialize(compact=True)}

        except Exception as e:
            print(f"Error signing OpenID4VP request: {e}")
            return None

    # ... [Fallback for unsigned requests] ...
    return request_payload

مرحله ب: راه‌اندازی کردن API (سمت کارخواه)

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

درون‌برنامه (Android)

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

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

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

dependencies {
    implementation("androidx.credentials:credentials:1.5.0-beta01")
    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 ارائه می‌دهد. «مدیر اطلاعات کاربری» این رشته JSON را بدون بررسی محتوای آن به کیف پول‌های دیجیتال دردسترس ارسال می‌کند. سپس هر کیف پول مسئول موارد زیر است:

  • تجزیه رشته JSON برای درک درخواست هویت.
  • تعیین اینکه کدام‌یک از اطلاعات اعتباری ذخیره‌شده آن، درصورت وجود، با درخواست مطابقت دارد.

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

از requestJson از قالب‌بندی و امضای درخواست به‌عنوان 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 حاوی identityToken (JWT) رمزگذاری‌شده است، که توسط W3C تعریف شده است. برنامه «کیف پول» مسئول ساختن این پاسخ است.

مثال:

{
  "protocol" : "openid4vp-v1-signed",
  "data" : {
    <encrypted_response>
  }
}

این پاسخ را به سرورتان برگردانید تا اصالت آن را اعتبارسنجی کند. به رمزگشایی و اعتبارسنجی پاسخ مراجعه کنید.

وب

برای درخواست «اعتبارنامه‌های هویتی» بااستفاده از Digital Credentials API در Chrome یا مرورگرهای پشتیبانی‌شده دیگر، درخواست زیر را ارسال کنید:

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

پاسخ این API را به سرورتان برگردانید تا پاسخ اطلاعات کاربری را اعتبارسنجی کند.


مرحله ۳: رمزگشایی و اعتبارسنجی پاسخ (سمت سرور)

وقتی کیف پول identityToken (JWT) رمزگذاری‌شده را برمی‌گرداند، باید قبل‌از اعتماد به داده‌ها، اعتبارسنجی دقیق سمت سرور را انجام دهید.

رمزگشایی پاسخ

از کلید خصوصی مربوط به کلید عمومی ارسال‌شده در client_metadata درخواست برای رمزگشایی JWE استفاده کنید. این کار vp_token را به‌همراه دارد.

مثال Python:

from jwcrypto import jwe, jwk

# Retrieve the Private Key from Datastore
reader_private_jwk = jwk.JWK.from_json(jwe_private_key_json_str)
# Save public key thumbprint for session transcript
encryption_public_jwk_thumbprint = reader_private_jwk.thumbprint()


# 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": ["<base64UrlNoPadding_encoded_credential>"] // This applies to OpenID4VP 1.0 spec.
  }
}

بازسازی SessionTranscript و اعتبارسنجی DeviceResponse

  1. SessionTranscript را از ISO/IEC 18013-5:2021 با ساختار «تحویل» مختص Android یا وب ایجاد کنید:
SessionTranscript = [
  null,                // DeviceEngagementBytes not available
  null,                // EReaderKeyBytes not available
  [
    "OpenID4VPDCAPIHandover",
    AndroidHandoverDataBytes   // BrowserHandoverDataBytes for Web
  ]
]

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

Android Handover

AndroidHandoverData = [
  origin,             // "android:apk-key-hash:<base64SHA256_ofAppSigningCert>",
  nonce,           // nonce that was used to generate credential request,
  encryption_public_jwk_thumbprint,  // Encryption public key (JWK) Thumbprint
]

AndroidHandoverDataBytes = hashlib.sha256(cbor2.dumps(AndroidHandoverData)).digest()

واگذاری مرورگر

BrowserHandoverData =[
  origin,               // Origin URL
  nonce,               //  nonce that was used to generate credential request
  encryption_public_jwk_thumbprint,  // Encryption public key (JWK) Thumbprint
]

BrowserHandoverDataBytes = hashlib.sha256(cbor2.dumps(BrowserHandoverData)).digest()

بااستفاده از SessionTranscript، «پاسخ دستگاه» باید مطابق با بند ۹ ISO/IEC 18013-5:2021 اعتبارسنجی شود.

این اعتبارسنجی شامل چهار بررسی است:

  1. بررسی گواهی صادرکننده: زنجیره گواهی امضای صادرکننده را از issuerAuth استخراج کنید و آن را با گواهی‌های ریشه IACA مورداعتماد اعتبارسنجی کنید. به صادرکنندگان پشتیبانی‌شده و گواهی‌های IACA مراجعه کنید (و هنگام آزمایش با شناسه آزمایشی جعبه امن، گواهی Utopia Sandbox را اضافه کنید).
  2. درستی‌سنجی امضای MSO (ISO/IEC 18013-5 بخش ۹.۱.۲).
  3. محاسبه و بررسی ValueDigests برای عناصر داده (ISO/IEC 18013-5 بخش ۹.۱.۲).
  4. درستی‌سنجی امضای deviceSignature (ISO/IEC 18013-5 بخش ۹.۱.۳).
{
  "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
}

مرحله ۴ (اختیاری): درستی‌سنجی سن با حفظ حریم خصوصی (ZKP)

برای پشتیبانی از «اثبات با دانش صفر» (برای مثال، تأیید اینکه کاربر بالای ۱۸ سال دارد بدون دیدن تاریخ تولد دقیق او)، قالب درخواستتان را به mso_mdoc_zk تغییر دهید و پیکربندی zk_system_type موردنیاز را ارائه دهید.

برای نمای کلی سطح بالا از اینکه ZKP چیست و چه قابلیت‌هایی دارد، به پرسشگان مراجعه کنید.

  ...
  "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": "f88a39e561ec0be02bb3dfe38fb609ad154e98decbbe632887d850fc612fea6f", // This will differ if you need more than 1 attribute.
          "num_attributes": 1, // number of attributes (in claims) this has can support
          "version": 5,
          "block_enc_hash": 4096,
          "block_enc_sig": 2945,
        }
        {
          "system": "longfellow-libzk-v1",
          "circuit_hash": "137e5a75ce72735a37c8a72da1a8a0a5df8d13365c2ae3d2c2bd6a0e7197c7c6", // This will differ if you need more than 1 attribute.
          "num_attributes": 1, // number of attributes (in claims) this has can support
          "version": 6,
          "block_enc_hash": 4096,
          "block_enc_sig": 2945,
        }
       ],
       "verifier_message": "challenge"
      },
     "claims": [{
         ...
      "client_metadata": {
        "jwks": {
          "keys": [ // sample request encryption key
            {
              ...

یک اثبات دانش صفر رمزگذاری‌شده از کیف پول دریافت خواهید کرد. می‌توانید این مدرک را بااستفاده از کتابخانه longfellow-zk Google دربرابر گواهی‌های IACA صادرکننده اعتبارسنجی کنید.

verifier-service حاوی سرور مبتنی بر Docker آماده استقرار است که به شما امکان می‌دهد پاسخ را دربرابر گواهی‌های IACA صادرکننده اعتبارسنجی کنید.

می‌توانید certs.pem را اصلاح کنید تا گواهی‌های صادرکننده IACA را که می‌خواهید به آن‌ها اعتماد کنید مدیریت کنید.


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

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

منبع / کتابخانه آنچه ارائه می‌دهد پیوند
پیاده‌سازی مرجع درستی‌سنج‌های هویت نمونه سرور و کارخواه که تولید درخواست OpenID4VP، امضای JWS، رمزگشایی JWE، و اعتبارسنجی پاسخ mdoc را نشان می‌دهد. مخزن GitHub
کیت توسعه نرم‌افزار Multipaz کتابخانه متن‌باز (OpenWallet Foundation) شامل DeviceResponseParser برای رمزگشایی CBOR، بازسازی SessionTranscript، و اعتبارسنجی امضای ISO/IEC 18013-5/7. openwallet-foundation/multipaz
Longfellow ZKP Library & Verifier Service کتابخانه متن‌باز و سرور مبتنی بر Docker برای درستی‌سنجی سن و ادعاهای ویژگی «اثبات با دانش صفر» (mso_mdoc_zk). google/longfellow-zk
ابزار درستی‌سنج وب تعاملی درستی‌سنج وب میزبانی‌شده برای آزمایش درخواست‌های W3C Digital Credentials API / OpenID4VP در «کیف پول Google». verifier.multipaz.org
مشخصات OpenID4VP 1.0 مشخصات پروتکل رسمی OpenID برای Verifiable Presentations 1.0. مشخصات OpenID4VP
پرسشگان و پشتیبانی توسعه‌دهنده پاسخ به سؤالات رایج درباره ادغام فنی، یا ارسال ایمیل به wallet-identity-rp-support@google.com برای دریافت کمک در اشکال‌زدایی. پرسشگان ادغام فنی

مرحله بعدی