يمكن قبول مستندات التعريف الرقمية في مسارات داخل التطبيق وعلى الويب. لقبول مستندات التعريف من "محفظة Google"، عليك استيفاء الشروط التالية:
- يمكنك الدمج باستخدام التطبيق أو الموقع الإلكتروني باتّباع التعليمات المقدَّمة.
- استخدِم معرّف الاختبار لاختبار سير العمل باستخدام وضع الحماية في "محفظة Google".
- للبدء بالبث المباشر، يُرجى ملء هذا النموذج لطلب الوصول إلى الميزة وقبول بنود خدمة بيانات الاعتماد في Google Wallet. عليك ملء هذا النموذج لكل كيان من كيانات نشاطك التجاري. سيتواصل معك فريقنا بعد ملء النموذج.
- إذا كانت لديك أسئلة، يمكنك التواصل مع
wallet-identity-rp-support@google.com
.
تنسيقات بيانات الاعتماد المتوافقة
تتوفّر العديد من المعايير المقترَحة التي تحدّد تنسيق البيانات لمستندات الهوية الرقمية، وقد حظي اثنان منها باهتمام كبير في المجال:
- mdocs: معرَّف حسب الهيئة الدولية للمواصفات (ISO).
- المستندات القابلة للتحقّق من W3C: هي مستندات محدّدة من قِبل W3C.
مع أنّ "مدير بيانات الاعتماد على Android" يتيح استخدام التنسيقَين، لا تتيح "محفظة Google" حاليًا سوى مستندات التعريف الرقمية المستندة إلى mdoc.
بيانات الاعتماد المتوافقة
تتيح "محفظة Google" نوعَين من مستندات التعريف:
- رخصة القيادة الرقمية (mDL)
- بطاقة تعريف الهوية
يمكنك طلب أي من بيانات الاعتماد في مسار الدفع من خلال تغيير مَعلمة واحدة.
تجربة المستخدم
يتناول هذا القسم مسار العرض التقديمي المقترَح على الإنترنت. يعرض المخطط التقديم على تطبيق لتوصيل المشروبات الكحولية، ولكن تجربة المستخدم مشابهة على الويب أيضًا بالإضافة إلى أنواع أخرى من التقديم.
![]() |
![]() |
![]() |
![]() |
![]() |
يُطلب من المستخدم تأكيد عمره في التطبيق أو الموقع الإلكتروني | يطلع المستخدم على بيانات الاعتماد المؤهَّلة المتاحة | تظهر للمستخدم صفحة تأكيد في "محفظة Google" | يصادق المستخدم لتأكيد المشاركة | البيانات المُرسَلة إلى التطبيق أو الموقع الإلكتروني |
ملاحظات أساسية
- يتمتع التطبيق أو الموقع الإلكتروني بالمرونة في طريقة إنشاء نقطة الدخول إلى واجهة برمجة التطبيقات. كما هو موضّح في الخطوة 1، ننصح بعرض زر عام، مثل "إثبات الهوية باستخدام مستند تعريف رقمي"، لأنّنا نتوقّع أن تتوفّر خيارات أخرى غير "محفظة Google" من خلال واجهة برمجة التطبيقات بمرور الوقت.
- تعرض شاشة أداة الاختيار في الخطوة 2 نظام التشغيل Android. يتم تحديد بيانات الاعتماد المؤهّلة من خلال مطابقة منطق التسجيل الذي توفّره كل "محفظة" مع الطلب الذي يرسله الطرف المعتمِد.
- تعرض "محفظة Google" الخطوة 3. ستعرض "محفظة Google" الاسم والشعار وسياسة الخصوصية التي يقدّمها المطوّر على هذه الشاشة.
إضافة مسار بطاقة تعريف رقمية
في حال عدم توفّر مستند تعريف لدى المستخدم، ننصحك بتوفير رابط بجانب الزر "التحقّق باستخدام مستند التعريف الرقمي" يؤدي إلى رابط لصفحة معيّنة في "محفظة Google" للسماح للمستخدم بإضافة مستند تعريف رقمي.
![]() |
![]() |
يُطلب من المستخدم تأكيد عمره في التطبيق أو الموقع الإلكتروني | يتم نقل المستخدم إلى "محفظة Google" للحصول على مستند تعريف رقمي |
لا يتوفّر أي مستند تعريف رقمي
إذا اختار المستخدم خيار "التحقّق من الهوية باستخدام بطاقة تعريف رقمية" بدون أن تكون لديه بطاقة تعريف رقمية، ستظهر له رسالة الخطأ هذه.
![]() |
![]() |
يُطلب من المستخدم تأكيد عمره في التطبيق أو الموقع الإلكتروني | ظهور رسالة خطأ للمستخدم إذا لم يكن لديه مستند تعريف رقمي |
لا تتوافق واجهة برمجة التطبيقات مع ميزة تتيح معرفة ما إذا كان لدى المستخدم أي مستندات تعريف رقمية متاحة بدون إشعاره، وذلك للحفاظ على خصوصيته. لذلك، ننصحك بتضمين خيار رابط الإعداد على النحو الموضّح.
تنسيق الطلب لطلب مستندات تعريف الهوية من المحفظة
في ما يلي نموذج لطلب مستند رقمي 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",
"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"
],
"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",
"alg" : "ECDH-ES",
}
]
},
"authorization_encrypted_response_alg": "ECDH-ES",
"authorization_encrypted_response_enc": "A128GCM"
}
}
يمكنك طلب أي عدد من السمات المتوافقة من أي مستند تعريف مخزَّن في "محفظة Google".
في التطبيق
لطلب مستندات إثبات الهوية من تطبيقات 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")
}
ضبط "إدارة بيانات الاعتماد"
لضبط كائن 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 لفهم طلب تحديد الهوية. - تحديد بيانات الاعتماد المخزَّنة التي تستوفي الطلب، إن وُجدت
ننصح الشركاء بإنشاء طلباتهم على الخادم حتى عند دمج تطبيقات 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. تطبيق "محفظة Google" هو المسؤول عن إنشاء هذا الردّ.
مثال:
{
"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.
}
]
}
})
أرسِل الردّ من واجهة برمجة التطبيقات هذه إلى خادمك للتحقّق من صحة الردّ على بيانات الاعتماد
خطوات التحقّق من صحة رد بيانات الاعتماد
عند تلقّي identityToken المشفّر من تطبيقك أو موقعك الإلكتروني، عليك إجراء عمليات تحقّق متعددة قبل الوثوق بالردّ.
فك تشفير الردّ باستخدام المفتاح الخاص
تتمثل الخطوة الأولى في فك تشفير الرمز المميّز باستخدام المفتاح الخاص المحفوظ والحصول على ملف JSON للاستجابة.
مثال على Python:
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>" } }
إنشاء نص الجلسة
الخطوة التالية هي إنشاء SessionTranscript من ISO/IEC 18013-5:2021 باستخدام بنية Handover خاصة بنظام التشغيل Android أو الويب:
SessionTranscript = [ null, // DeviceEngagementBytes not available null, // EReaderKeyBytes not available [ "OpenID4VPDCAPIHandover", AndroidHandoverDataBytes // BrowserHandoverDataBytes for Web ] ]
في كلتا عمليتَي التسليم على Android والويب، عليك استخدام قيمة nonce نفسها التي استخدمتها لإنشاء
credential_request
.تسليم Android
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. يتضمّن ذلك عدة خطوات، مثل:التحقّق من شهادة جهة الإصدار الحكومية الاطّلاع على شهادات IACA الخاصة بالجهات المعتمدة لإصدار البطاقات
التحقّق من توقيع MSO (القسم 9.1.2 من معيار 18013-5)
حساب ValueDigests والتحقّق منها لعناصر البيانات (القسم 9.1.2 من معيار 18013-5)
التحقّق من توقيع
deviceSignature
(القسم 9.1.3 من المعيار 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
}
اختبار الحلّ
لاختبار الحلّ، يمكنك إنشاء تطبيق Android مفتوح المصدر وتشغيله. في ما يلي خطوات إنشاء تطبيق حامل المرجع وتشغيله:
- إنشاء نسخة طبق الأصل من مستودع التطبيقات المرجعية
- افتح المشروع على استوديو Android.
- أنشئ هدف
appholder
وشغِّله على جهاز Android أو المحاكي.
التحقّق المستند إلى "إثبات المعرفة الصفرية" (ZKP)
التحقّق بدون معرفة (ZKP) هو طريقة تشفير تتيح للفرد (المثبت) أن يثبت للمتحقّق أنّه يملك معلومات هوية معيّنة أو يستوفي معيارًا محدّدًا (مثل أن يكون عمره أكثر من 18 عامًا، أو أن يحمل مستند تعريف صالحًا) بدون الكشف عن البيانات الأساسية الفعلية نفسها. بشكل أساسي، هي طريقة لتأكيد صحة بيان حول هوية الشخص مع الحفاظ على سرية التفاصيل الحساسة.
تتطلّب أنظمة الهوية الرقمية التي تعتمد على المشاركة المباشرة لبيانات الهوية غالبًا أن يشارك المستخدمون معلومات شخصية مفرطة، ما يزيد من خطر اختراق البيانات وسرقة الهوية. توفّر ZKP تغييرًا جذريًا في المفاهيم، ما يتيح إجراء عمليات التحقّق مع الحد الأدنى من الإفصاح.
المفاهيم الأساسية لبروتوكولات إثبات المعرفة الصفرية في الهوية الرقمية:
- المُثبِت: هو الشخص الذي يحاول إثبات أحد جوانب هويته.
- جهة التحقّق: هي الجهة التي تطلب مستندًا لإثبات إحدى سمات الهوية.
- الإثبات: بروتوكول تشفير يتيح للمثبت إقناع المدقق بصحة ادعائه بدون الكشف عن المعلومات السرية.
الخصائص الأساسية لإثبات صحة المعلومات بدون الكشف عنها:
- الكمال: إذا كانت العبارة صحيحة وكان كل من المُثبِت والمدقّق صادقَين، سيقتنع المدقّق.
- الصحة: إذا كانت الجملة خاطئة، لا يمكن للمثبت المخادع (باحتمالية عالية جدًا) إقناع المدقق الصادق بأنّها صحيحة.
- إثبات صحة المعلومات بدون الكشف عنها: لا يعرف المدقّق أي معلومات أخرى غير أنّ العبارة صحيحة. لا يتم عرض أي بيانات فعلية من هوية مقدّم الإثبات.
للحصول على إثبات عدم الإفصاح عن المعلومات من "محفظة Google"، عليك تغيير تنسيق الطلب إلى 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": "bd3168ea0a9096b4f7b9b61d1c210dac1b7126a9ec40b8bc770d4d485efce4e9", // This will differ if you need more than 1 attribute.
"num_attributes": 1, // number of attributes (in claims) this has can support
"version": 3
},
{
"system": "longfellow-libzk-v1",
"circuit_hash": "89288b9aa69d2120d211618fcca8345deb4f85d2e710c220cc9c059bbee4c91f", // This will differ if you need more than 1 attribute.
"num_attributes": 1, // number of attributes (in claims) this has can support
"version": 4
}
],
"verifier_message": "challenge"
},
"claims": [{
...
"client_metadata": {
"jwks": {
"keys": [ // sample request encryption key
{
...
ستتلقّى من المحفظة إثباتًا مشفّرًا بعدم الإفصاح عن المعلومات. يمكنك التحقّق من صحة هذا الإثبات باستخدام شهادات IACA الخاصة بالجهات المصدرة من خلال مكتبة longfellow-zk من Google.
يمكنك التواصل مع فريق الدعم عبر البريد الإلكتروني للحصول على مزيد من التفاصيل
wallet-identity-rp-support@google.com