إذا كنت تخطط لتقديم طلبات واجهة برمجة التطبيقات العادية فقط، والتي تكون مناسبة لغالبية المطوّرين، يمكنك التخطّي إلى نتائج اختبار سلامة التطبيق. توضّح هذه الصفحة كيفية إجراء طلبات برمجة تطبيقات كلاسيكية للحصول على بيانات السلامة، وهي متاحة على نظام التشغيل 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 | ✔️ | ✔️ |
وقت الاستجابة المعتاد لطلب فك التشفير من خادم إلى خادم | 10 مللي ثانية مع توفّر 99.99% | 10 مللي ثانية مع توفّر 99.99% |
فك تشفير الرمز المميّز وإثبات صحته محليًا في بيئة خادم آمنة | ❌ | ✔️ |
فك تشفير الرمز المميّز وإثبات صحته من جهة العميل | ❌ | ❌ |
حداثة بيان السلامة | بعض عمليات التخزين المؤقت والتحديث التلقائي من 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
للحدّ من أنواع معيّنة من الهجمات، مثل
هجمات التلاعب من خلال شخص ثالث وهجمات إعادة التشغيل. تعرض واجهة برمجة التطبيقات
Integrity API القيمة التي تحدّدها في هذا الحقل داخل ردّ
integrity الموقَّع.
يجب أن تكون القيمة التي تم ضبطها في حقل 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());
الوحدة
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();
الحمولة الناتجة هي رمز مميّز بنص عادي يحتوي على بيانات السلامة.