إذا كنت تخطّط فقط لإجراء طلباتواجهة برمجة التطبيقات العادية، وهي مناسبة لمعظم المطوّرين، يمكنك الانتقال إلى قسم نتائج التحقّق من السلامة. توضّح هذه الصفحة كيفية تقديم طلبات إلى واجهة برمجة التطبيقات الكلاسيكية للحصول على بيانات السلامة، وهي متاحة على نظام التشغيل Android 4.4 (المستوى 19 من واجهة برمجة التطبيقات) أو الإصدارات الأحدث.
الاعتبارات
مقارنة بين الطلبات العادية والكلاسيكية
يمكنك إنشاء طلبات عادية أو طلبات كلاسيكية أو مزيج منهما حسب احتياجات تطبيقك المتعلقة بالأمان ومكافحة إساءة الاستخدام. تكون الطلبات العادية مناسبة لجميع التطبيقات والألعاب، ويمكن استخدامها للتحقّق من أنّ أي إجراء أو طلب من الخادم هو إجراء أو طلب حقيقي، مع تفويض Google Play بتقديم بعض الحماية من إمكانية إعادة التشغيل والتسرّب. تكون الطلبات الكلاسيكية أكثر تكلفة، وتتحمّل أنت مسؤولية تنفيذها بشكل صحيح للحماية من سرقة البيانات وأنواع معيّنة من الهجمات. يجب أن تكون الطلبات الكلاسيكية أقل تكرارًا من الطلبات العادية، مثلاً كطلب لمرة واحدة من حين لآخر للتحقّق مما إذا كان إجراء مهم أو حسّاس للغاية حقيقيًا.
يوضّح الجدول التالي الاختلافات الرئيسية بين نوعَي الطلبات:
طلب عادي للبيانات من واجهة برمجة التطبيقات | طلب البيانات من واجهة برمجة التطبيقات الكلاسيكية | |
---|---|---|
المتطلبات الأساسية | ||
الحد الأدنى لإصدار حزمة تطوير البرامج (SDK) لنظام التشغيل Android المطلوب | الإصدار 5.0 من نظام التشغيل Android (المستوى 21 لواجهة برمجة التطبيقات) أو إصدار أحدث | الإصدار 4.4 من نظام التشغيل Android (المستوى 19 لواجهة برمجة التطبيقات) أو إصدار أحدث |
متطلبات Google Play | متجر Google Play و"خدمات Google Play" | متجر Google Play و"خدمات Google Play" |
تفاصيل عملية الدمج | ||
يجب إعداد واجهة برمجة التطبيقات | ✔️ (بضع ثوانٍ) | ❌ |
وقت الاستجابة المعتاد للطلبات | بضع مئات من الملّي ثانية | بضع ثوانٍ |
معدّل تكرار الطلبات المحتملة | متكرّر (التحقّق عند الطلب من أي إجراء أو طلب) | غير متكرّر (عملية تحقّق لمرة واحدة من الإجراءات ذات القيمة الأعلى أو الطلبات الأكثر حساسية) |
عملية استبعاد للقناة لمهلة معيّنة | تستغرق معظم عمليات الإحماء أقل من 10 ثوانٍ، ولكنها تتضمّن طلبًا من الخادم، لذا يُنصح باستخدام مهلة طويلة (مثل دقيقة واحدة). تتم طلبات الحكم من جهة العميل | تستغرق معظم الطلبات أقل من 10 ثوانٍ، ولكنّها تتضمّن طلبًا من الخادم، لذا يُنصح بضبط مهلة طويلة (مثل دقيقة واحدة). |
الرمز المميز لبيان السلامة | ||
يحتوي على تفاصيل الجهاز والتطبيق والحساب | ✔️ | ✔️ |
التخزين المؤقت للرموز المميزة | التخزين المؤقت المحمي على الجهاز من خلال Google Play | (يُفضَّل عدم النقر هنا.) |
فك تشفير الرمز المميز والتحقّق منه من خلال خادم Google Play | ✔️ | ✔️ |
وقت الاستجابة النموذجي لطلب فك التشفير من خادم إلى خادم | أجزاء من الثانية مع توفّر بنسبة %99.9 | أجزاء من الثانية مع توفّر بنسبة %99.9 |
فك تشفير الرمز المميّز والتحقّق منه محليًا في بيئة خادم آمنة | ❌ | ✔️ |
فك تشفير الرمز المميّز والتحقّق منه من جهة العميل | ❌ | ❌ |
سرعة توفّر بيان السلامة | بعض عمليات التخزين المؤقت والتحديث التلقائية التي يجريها Google Play | إعادة احتساب جميع النتائج في كل طلب |
الحدود | ||
الطلبات لكل تطبيق في اليوم | 10,000 تلقائيًا (يمكن طلب زيادة) | 10,000 تلقائيًا (يمكن طلب زيادة) |
الطلبات لكل مثيل تطبيق في الدقيقة | عمليات الإحماء: 5 في الدقيقة رموز التحقّق من التكامل: ليس هناك حد أقصى عام* |
رموز التحقّق من السلامة: 5 رموز في الدقيقة |
الحماية | ||
الحدّ من التلاعب والهجمات المشابهة | استخدام حقل requestHash |
استخدام الحقل nonce مع ربط المحتوى استنادًا إلى بيانات الطلب |
التخفيف من هجمات إعادة الإرسال والهجمات المشابهة | إجراءات التخفيف التلقائية من Google Play | استخدام الحقل nonce مع منطق من جهة الخادم |
* تخضع جميع الطلبات، بما في ذلك تلك التي لا تتضمّن حدودًا علنية، لحدود دفاعية غير علنية عند القيم المرتفعة
تقديم طلبات كلاسيكية بشكل غير متكرّر
تستغرق عملية إنشاء رمز مميّز للسلامة وقتًا وتستهلك بيانات وبطارية، ولكل تطبيق حد أقصى لعدد الطلبات الكلاسيكية التي يمكنه إرسالها في اليوم. لذلك، يجب عدم إرسال طلبات كلاسيكية إلا للتأكّد من أنّ الإجراءات ذات القيمة الأعلى أو الأكثر حساسية هي إجراءات حقيقية، وذلك عندما تريد ضمانًا إضافيًا لطلب عادي. يجب عدم تقديم طلبات كلاسيكية للإجراءات المتكرّرة أو المنخفضة القيمة. لا تُرسِل طلبات كلاسيكية في كل مرة ينتقل فيها التطبيق إلى المقدّمة أو كل بضع دقائق في الخلفية، وتجنَّب إرسال الطلبات من عدد كبير من الأجهزة في الوقت نفسه. قد يتم تقييد التطبيقات التي تجري عددًا كبيرًا جدًا من طلبات الإصدار الكلاسيكي لحماية المستخدمين من عمليات التنفيذ غير الصحيحة.
تجنُّب تخزين النتائج مؤقتًا
يؤدي تخزين نتيجة التحقّق مؤقتًا إلى زيادة خطر حدوث هجمات مثل استخراج البيانات وإعادة التشغيل، حيث تتم إعادة استخدام نتيجة تحقّق جيدة من بيئة غير موثوق بها. إذا كنت تفكّر في إجراء طلب كلاسيكي ثم تخزينه مؤقتًا لاستخدامه لاحقًا، ننصحك بدلاً من ذلك بإجراء طلب عادي عند الحاجة. تتضمّن الطلبات العادية بعض التخزين المؤقت على الجهاز، ولكن يستخدم Google Play تقنيات حماية إضافية للحدّ من خطر هجمات إعادة الإرسال وسرقة البيانات.
استخدام حقل nonce لحماية الطلبات الكلاسيكية
توفّر واجهة برمجة التطبيقات Play Integrity API حقلًا يُسمى nonce
، ويمكن استخدامه لتعزيز حماية تطبيقك من بعض الهجمات، مثل هجمات إعادة التشغيل والتلاعب. تعرض واجهة برمجة التطبيقات Play Integrity API القيمة التي تحدّدها في هذا الحقل، وذلك ضمن
رد السلامة الموقَّع. اتّبِع الإرشادات بعناية حول كيفية إنشاء أرقام عشوائية لحماية تطبيقك من الهجمات.
إعادة محاولة الطلبات الكلاسيكية باستخدام خوارزمية الرقود الأسي الثنائي
يمكن أن تؤدي الظروف البيئية، مثل عدم استقرار الاتصال بالإنترنت أو زيادة حمولة الجهاز، إلى تعذُّر عمليات التحقّق من سلامة الجهاز. ويمكن أن يؤدي ذلك إلى عدم إنشاء تصنيفات لجهاز موثوق به. للتخفيف من حدة هذه السيناريوهات، أدرِج خيار إعادة المحاولة باستخدام خوارزمية الرقود الأسي الثنائي.
نظرة عامة
عندما ينفِّذ المستخدم إجراءً ذا قيمة عالية في تطبيقك تريد حمايته من خلال إجراء فحص للتأكّد من سلامة التطبيق، عليك إكمال الخطوات التالية:
- تنشئ الخلفية من جهة الخادم في تطبيقك قيمة فريدة وترسلها إلى منطق من جهة العميل. تشير الخطوات المتبقية إلى هذا المنطق باسم "التطبيق".
- ينشئ تطبيقك
nonce
من القيمة الفريدة ومحتوى الإجراء ذي القيمة العالية. بعد ذلك، يطلب البيانات من واجهة برمجة التطبيقات Play Integrity API، مع إدخالnonce
. - يتلقّى تطبيقك بيانًا موقّعًا ومشفّرًا من واجهة برمجة التطبيقات Play Integrity API.
- يرسل تطبيقك الحكم الموقَّع والمشفَّر إلى الخلفية.
- يرسل الخلفية في تطبيقك نتيجة التقييم إلى أحد خوادم Google Play. يفك خادم Google Play تشفير بيان السلامة ويتأكّد من صحته، ثم يرسل النتائج إلى الخلفية في تطبيقك.
- يحدّد خادم الخلفية في تطبيقك كيفية المتابعة استنادًا إلى الإشارات الواردة في حمولة الرمز المميّز.
- يرسل خادم الخلفية في تطبيقك نتائج القرار إلى تطبيقك.
إنشاء رقم عشوائي
عند حماية أحد الإجراءات في تطبيقك باستخدام واجهة برمجة التطبيقات Play Integrity API، يمكنك الاستفادة من الحقل nonce
للحدّ من أنواع معيّنة من الهجمات، مثل هجمات التلاعب من خلال اعتراض الاتصال (PITM) وهجمات إعادة الإرسال. تعرض واجهة برمجة التطبيقات Play Integrity API القيمة التي تحدّدها في هذا الحقل ضمن الردّ الموقَّع الخاص بالسلامة.
يجب تنسيق القيمة المضبوطة في الحقل nonce
بشكل صحيح:
String
- آمن للاستخدام في عناوين URL
- تم ترميزه باستخدام Base64 وبدون التفاف
- يجب أن تتضمّن 16 حرفًا على الأقل
- 500 حرف كحدّ أقصى
في ما يلي بعض الطرق الشائعة لاستخدام الحقل nonce
في واجهة برمجة التطبيقات Play Integrity API. للحصول على أقوى حماية من nonce
، يمكنك الجمع بين الطرق أدناه.
تضمين تجزئة الطلب للحماية من التلاعب
يمكنك استخدام المَعلمة nonce
في طلب بيانات من واجهة برمجة تطبيقات كلاسيكية بشكل مشابه للمَعلمة requestHash
في طلب بيانات من واجهة برمجة تطبيقات عادية لحماية محتوى الطلب من التلاعب.
عند طلب بيان سلامة:
- احتساب ملخّص لجميع مَعلمات الطلبات المهمة (مثل SHA256 لتسلسل الطلبات الثابت) من إجراء المستخدم أو طلب الخادم الذي يتم تنفيذه
- استخدِم
setNonce
لضبط الحقلnonce
على قيمة الملخّص المحسوب.
عند تلقّي بيان السلامة:
- فك ترميز الرمز المميز للتحقّق من السلامة والتحقّق منه، والحصول على الملخّص من الحقل
nonce
- احتساب ملخّص للطلب بالطريقة نفسها المستخدَمة في التطبيق (مثلاً، SHA256 لتسلسل ثابت للطلب)
- قارِن بين الملخّصات من جهة التطبيق ومن جهة الخادم. وفي حال عدم التطابق، لا يكون الطلب موثوقًا.
تضمين قيم فريدة للحماية من هجمات إعادة الإرسال
لمنع المستخدمين الضارين من إعادة استخدام الردود السابقة من واجهة برمجة التطبيقات Play Integrity API، يمكنك استخدام الحقل nonce
لتحديد كل رسالة بشكل فريد.
عند طلب بيان سلامة:
- الحصول على قيمة فريدة على مستوى العالم بطريقة لا يمكن للمستخدمين الضارين التنبؤ بها على سبيل المثال، يمكن أن تكون القيمة عبارة عن رقم عشوائي آمن مشفّر تم إنشاؤه من جهة الخادم، أو معرّف حالي، مثل معرّف جلسة أو معرّف معاملة. هناك طريقة أبسط وأقل أمانًا وهي إنشاء رقم عشوائي على الجهاز. ننصحك بإنشاء قيم 128 بت أو أكبر.
- اتّصِل بالرقم
setNonce()
لضبط الحقلnonce
على القيمة الفريدة من الخطوة 1.
عند تلقّي بيان سلامة:
- فك تشفير الرمز المميز الخاص بالتكامل والتحقّق منه، والحصول على القيمة الفريدة من الحقل
nonce
. - إذا تم إنشاء القيمة من الخطوة 1 على الخادم، تأكَّد من أنّ القيمة الفريدة التي تم تلقّيها هي إحدى القيم التي تم إنشاؤها، ومن أنّها تُستخدَم للمرة الأولى (سيحتاج الخادم إلى الاحتفاظ بسجلّ للقيم التي تم إنشاؤها لمدة مناسبة). إذا تم استخدام القيمة الفريدة المستلَمة من قبل أو لم تظهر في السجلّ، ارفض الطلب.
- بخلاف ذلك، إذا تم إنشاء القيمة الفريدة على الجهاز، تأكَّد من أنّ القيمة المستلَمة يتم استخدامها للمرة الأولى (يجب أن يحتفظ الخادم بسجلّ للقيم التي تمّت رؤيتها من قبل لمدة مناسبة). إذا تم استخدام القيمة الفريدة التي تم تلقّيها من قبل، ارفض الطلب.
الجمع بين الحماية من التلاعب والهجمات المتكررة (يُنصح بذلك)
يمكن استخدام الحقل nonce
للحماية من التلاعب والهجمات المتكررة في الوقت نفسه. لإجراء ذلك، أنشئ القيمة الفريدة كما هو موضح أعلاه، وأدرِجها كجزء من طلبك. بعد ذلك، احسب تجزئة الطلب، مع الحرص على تضمين القيمة الفريدة كجزء من التجزئة. في ما يلي مثال على عملية تنفيذ تجمع بين الطريقتَين:
عند طلب بيان سلامة:
- يبدأ المستخدم الإجراء العالي القيمة.
- احصل على قيمة فريدة لهذا الإجراء كما هو موضّح في قسم تضمين قيم فريدة للحماية من هجمات إعادة الإرسال.
- جهِّز رسالة تريد حمايتها. أدرِج القيمة الفريدة من الخطوة 2 في الرسالة.
- يحسب تطبيقك ملخّصًا للرسالة التي يريد حمايتها، كما هو موضّح في قسم تضمين تجزئة الطلب للحماية من التلاعب. بما أنّ الرسالة تحتوي على القيمة الفريدة، تكون القيمة الفريدة جزءًا من التجزئة.
- استخدِم
setNonce()
لضبط الحقلnonce
على الملخّص المحسوب من الخطوة السابقة.
عند تلقّي بيان سلامة:
- الحصول على القيمة الفريدة من الطلب
- فك ترميز الرمز المميز للتحقّق من السلامة والتحقّق منه، والحصول على الملخّص من الحقل
nonce
. - كما هو موضّح في قسم تضمين تجزئة الطلب للحماية من التلاعب، أعِد احتساب الملخّص من جهة الخادم، وتأكَّد من أنّه يطابق الملخّص الذي تم الحصول عليه من رمز التكامل.
- كما هو موضّح في قسم تضمين قيم فريدة للحماية من هجمات إعادة الإرسال، تحقَّق من صحة القيمة الفريدة.
يوضّح مخطط التسلسل التالي هذه الخطوات باستخدام nonce
من جهة الخادم:
طلب بيان سلامة
بعد إنشاء nonce
، يمكنك طلب بيان سلامة من Google Play. لإجراء ذلك، يُرجى إكمال الخطوات التالية:
- أنشئ
IntegrityManager
، كما هو موضّح في الأمثلة التالية. - أنشئ
IntegrityTokenRequest
، وقدِّمnonce
من خلال الطريقةsetNonce()
في أداة الإنشاء المرتبطة. يجب أيضًا أن تحدّد التطبيقات التي يتم توزيعها حصريًا خارج Google Play وحِزم SDK رقم مشروع Google Cloud الخاص بها من خلال الطريقةsetCloudProjectNumber()
. يتم ربط التطبيقات على Google Play بمشروع على Cloud في Play Console، ولا تحتاج إلى ضبط رقم مشروع Cloud في الطلب. استخدِم أداة الإدارة للاتصال بـ
requestIntegrityToken()
، مع توفيرIntegrityTokenRequest
.
Kotlin
// Receive the nonce from the secure server. val nonce: String = ... // Create an instance of a manager. val integrityManager = IntegrityManagerFactory.create(applicationContext) // Request the integrity token by providing a nonce. val integrityTokenResponse: Task<IntegrityTokenResponse> = integrityManager.requestIntegrityToken( IntegrityTokenRequest.builder() .setNonce(nonce) .build())
Java
import com.google.android.gms.tasks.Task; ... // Receive the nonce from the secure server. String nonce = ... // Create an instance of a manager. IntegrityManager integrityManager = IntegrityManagerFactory.create(getApplicationContext()); // Request the integrity token by providing a nonce. Task<IntegrityTokenResponse> integrityTokenResponse = integrityManager .requestIntegrityToken( IntegrityTokenRequest.builder().setNonce(nonce).build());
Unity
IEnumerator RequestIntegrityTokenCoroutine() { // Receive the nonce from the secure server. var nonce = ... // Create an instance of a manager. var integrityManager = new IntegrityManager(); // Request the integrity token by providing a nonce. var tokenRequest = new IntegrityTokenRequest(nonce); var requestIntegrityTokenOperation = integrityManager.RequestIntegrityToken(tokenRequest); // Wait for PlayAsyncOperation to complete. yield return requestIntegrityTokenOperation; // Check the resulting error code. if (requestIntegrityTokenOperation.Error != IntegrityErrorCode.NoError) { AppendStatusLog("IntegrityAsyncOperation failed with error: " + requestIntegrityTokenOperation.Error); yield break; } // Get the response. var tokenResponse = requestIntegrityTokenOperation.GetResult(); }
Unreal Engine
// .h void MyClass::OnRequestIntegrityTokenCompleted( EIntegrityErrorCode ErrorCode, UIntegrityTokenResponse* Response) { // Check the resulting error code. if (ErrorCode == EIntegrityErrorCode::Integrity_NO_ERROR) { // Get the token. FString Token = Response->Token; } } // .cpp void MyClass::RequestIntegrityToken() { // Receive the nonce from the secure server. FString Nonce = ... // Create the Integrity Token Request. FIntegrityTokenRequest Request = { Nonce }; // Create a delegate to bind the callback function. FIntegrityOperationCompletedDelegate Delegate; // Bind the completion handler (OnRequestIntegrityTokenCompleted) to the delegate. Delegate.BindDynamic(this, &MyClass::OnRequestIntegrityTokenCompleted); // Initiate the integrity token request, passing the delegate to handle the result. GetGameInstance() ->GetSubsystem<UIntegrityManager>() ->RequestIntegrityToken(Request, Delegate); }
مدمجة مع المحتوى
/// Create an IntegrityTokenRequest opaque object. const char* nonce = RequestNonceFromServer(); IntegrityTokenRequest* request; IntegrityTokenRequest_create(&request); IntegrityTokenRequest_setNonce(request, nonce); /// Prepare an IntegrityTokenResponse opaque type pointer and call /// IntegerityManager_requestIntegrityToken(). IntegrityTokenResponse* response; IntegrityErrorCode error_code = IntegrityManager_requestIntegrityToken(request, &response); /// ... /// Proceed to polling iff error_code == INTEGRITY_NO_ERROR if (error_code != INTEGRITY_NO_ERROR) { /// Remember to call the *_destroy() functions. return; } /// ... /// Use polling to wait for the async operation to complete. /// Note, the polling shouldn't block the thread where the IntegrityManager /// is running. IntegrityResponseStatus response_status; /// Check for error codes. IntegrityErrorCode error_code = IntegrityTokenResponse_getStatus(response, &response_status); if (error_code == INTEGRITY_NO_ERROR && response_status == INTEGRITY_RESPONSE_COMPLETED) { const char* integrity_token = IntegrityTokenResponse_getToken(response); SendTokenToServer(integrity_token); } /// ... /// Remember to free up resources. IntegrityTokenRequest_destroy(request); IntegrityTokenResponse_destroy(response); IntegrityManager_destroy();
فك تشفير بيان السلامة والتحقّق منه
عند طلب بيان سلامة، تقدّم واجهة برمجة التطبيقات Play Integrity API رمزًا مميّزًا للردّ موقّعًا. يصبح nonce
الذي تدرجه في طلبك جزءًا من رمز الاستجابة المميّز.
تنسيق الرمز المميّز
الرمز المميّز هو رمز JSON المميّز للويب (JWT) متداخل، وهو تشفير JSON على الويب (JWE) لـ توقيع JSON على الويب (JWS). يتم تمثيل مكوّنَي JWE وJWS باستخدام التسلسل المضغوط.
تتوافق خوارزميات التشفير / التوقيع بشكل جيد مع مختلف عمليات تنفيذ JWT:
فك التشفير والتحقّق على خوادم Google (الخيار الذي ننصح به)
تتيح لك واجهة برمجة التطبيقات Play Integrity API فك تشفير بيان السلامة والتحقّق منه على خوادم Google، ما يعزّز أمان تطبيقك. لإجراء ذلك، يُرجى إكمال الخطوات التالية:
- أنشئ حساب خدمة ضمن مشروع Google Cloud المرتبط بتطبيقك.
على خادم تطبيقك، اجلب رمز الدخول من بيانات اعتماد حساب الخدمة باستخدام النطاق
playintegrity
، وقدِّم الطلب التالي:playintegrity.googleapis.com/v1/PACKAGE_NAME:decodeIntegrityToken -d \ '{ "integrity_token": "INTEGRITY_TOKEN" }'
قراءة استجابة JSON
فك التشفير والتحقّق من صحة البيانات محليًا
إذا اخترت إدارة وتنزيل مفاتيح تشفير الردود، يمكنك فك تشفير الرمز المميّز الذي تم إرجاعه والتحقّق منه ضمن بيئة الخادم الآمنة الخاصة بك.
يمكنك الحصول على الرمز المميّز الذي تم إرجاعه باستخدام طريقة IntegrityTokenResponse#token()
.
يوضّح المثال التالي كيفية فك ترميز مفتاح AES ومفتاح EC العام المرمّز بتنسيق DER للتحقّق من التوقيع من Play Console إلى مفاتيح خاصة بلغة معيّنة (لغة البرمجة Java في حالتنا) في الخلفية الخاصة بالتطبيق. يُرجى العِلم أنّ المفاتيح مرمّزة بـ base64 باستخدام العلامات التلقائية.
Kotlin
// base64OfEncodedDecryptionKey is provided through Play Console. var decryptionKeyBytes: ByteArray = Base64.decode(base64OfEncodedDecryptionKey, Base64.DEFAULT) // Deserialized encryption (symmetric) key. var decryptionKey: SecretKey = SecretKeySpec( decryptionKeyBytes, /* offset= */ 0, AES_KEY_SIZE_BYTES, AES_KEY_TYPE ) // base64OfEncodedVerificationKey is provided through Play Console. var encodedVerificationKey: ByteArray = Base64.decode(base64OfEncodedVerificationKey, Base64.DEFAULT) // Deserialized verification (public) key. var verificationKey: PublicKey = KeyFactory.getInstance(EC_KEY_TYPE) .generatePublic(X509EncodedKeySpec(encodedVerificationKey))
Java
// base64OfEncodedDecryptionKey is provided through Play Console. byte[] decryptionKeyBytes = Base64.decode(base64OfEncodedDecryptionKey, Base64.DEFAULT); // Deserialized encryption (symmetric) key. SecretKey decryptionKey = new SecretKeySpec( decryptionKeyBytes, /* offset= */ 0, AES_KEY_SIZE_BYTES, AES_KEY_TYPE); // base64OfEncodedVerificationKey is provided through Play Console. byte[] encodedVerificationKey = Base64.decode(base64OfEncodedVerificationKey, Base64.DEFAULT); // Deserialized verification (public) key. PublicKey verificationKey = KeyFactory.getInstance(EC_KEY_TYPE) .generatePublic(new X509EncodedKeySpec(encodedVerificationKey));
بعد ذلك، استخدِم هذه المفاتيح لفك تشفير رمز التكامل (جزء JWE) أولاً، ثم تحقَّق من جزء JWS المضمّن واستخرِجه.
Kotlin
val jwe: JsonWebEncryption = JsonWebStructure.fromCompactSerialization(integrityToken) as JsonWebEncryption jwe.setKey(decryptionKey) // This also decrypts the JWE token. val compactJws: String = jwe.getPayload() val jws: JsonWebSignature = JsonWebStructure.fromCompactSerialization(compactJws) as JsonWebSignature jws.setKey(verificationKey) // This also verifies the signature. val payload: String = jws.getPayload()
Java
JsonWebEncryption jwe = (JsonWebEncryption)JsonWebStructure .fromCompactSerialization(integrityToken); jwe.setKey(decryptionKey); // This also decrypts the JWE token. String compactJws = jwe.getPayload(); JsonWebSignature jws = (JsonWebSignature) JsonWebStructure.fromCompactSerialization(compactJws); jws.setKey(verificationKey); // This also verifies the signature. String payload = jws.getPayload();
الحِمل الناتج هو رمز مميز بنص عادي يحتوي على نتائج التحقّق من السلامة.
حلّ المشاكل المتعلّقة بقرار التحقّق من الأهلية باستخدام طلب من Google Play (اختياري)
بعد أن يتلقّى الخادم بيان سلامة، يمكنه تحديد كيفية المتابعة. إذا أشارت النتيجة إلى وجود مشكلة، مثل عدم توفّر ترخيص للتطبيق أو التلاعب به أو تعرُّض الجهاز للخطر، يمكنك منح المستخدمين فرصة لحلّ المشكلة بأنفسهم.
توفّر واجهة برمجة التطبيقات Play Integrity API خيارًا لعرض مربّع حوار على Google Play يطلب من المستخدم اتّخاذ إجراء، مثل الحصول على الإصدار الرسمي من تطبيقك على Google Play.
للتعرّف على كيفية عرض مربّعات الحوار هذه من تطبيقك استنادًا إلى ردّ الخادم، يمكنك الاطّلاع على مربّعات حوار الإصلاح.