تقديم طلب من واجهة برمجة التطبيقات الكلاسيكية

إذا كنت تخطّط فقط لتقديم طلبات بيانات من واجهة برمجة التطبيقات تناسب معظم المطوّرين، يمكنك التخطّي إلى بيانات السلامة. توضّح هذه الصفحة كيفية إجراء طلبات من واجهة برمجة التطبيقات الكلاسيكية للحصول على بيانات السلامة، وهي متاحة في الإصدار 4.4 من نظام التشغيل Android (المستوى 19 من واجهة برمجة التطبيقات) أو الإصدارات الأحدث.

الاعتبارات

مقارنة الطلبات العادية والكلاسيكية

يمكنك إنشاء طلبات عادية أو طلبات كلاسيكية أو مزيج من الاثنين حسب احتياجات الأمان ومكافحة إساءة الاستخدام في تطبيقك. تُعدّ الطلبات العادية مناسبة لجميع التطبيقات والألعاب، ويمكن استخدامها للتحقّق من أنّ أي إجراء أو طلب خادم صحيح، مع تفويض بعض الحماية ضد إعادة التشغيل والاستخراج للبيانات إلى Google Play. تكون الطلبات الكلاسيكية أكثر تكلفة في الإنشاء، وتقع على عاتقك مسؤولية تنفيذها بشكل صحيح للحماية من الاستخراج وبعض أنواع الهجمات. يجب تقديم الطلبات الكلاسيكية بمعدّل أقل تكرارًا من الطلبات العادية، على سبيل المثال، طلب واحد من حين لآخر للتحقّق مما إذا كان هناك إجراء قيّم أو حسّاس للغاية.

يوضّح الجدول التالي الاختلافات الرئيسية بين نوعَي الطلبات:

طلب البيانات من واجهة برمجة التطبيقات العادية طلب البيانات من واجهة برمجة التطبيقات الكلاسيكية
المتطلبات الأساسية
مطلوب إصدار حزمة تطوير البرامج (SDK) لنظام التشغيل Android بالحدّ الأدنى Android 5.0 (مستوى واجهة برمجة التطبيقات 21) أو إصدار أحدث الإصدار 4.4 من نظام التشغيل Android (المستوى 19 من واجهة برمجة التطبيقات) أو الإصدارات الأحدث
متطلبات Google Play "متجر Google Play" وخدمات Google Play "متجر Google Play" وخدمات Google Play
تفاصيل عملية الدمج
يجب تحضير واجهة برمجة التطبيقات ✔️ (بضع ثوانٍ)
وقت الاستجابة المعتاد للطلبات بضع مئات من المللي ثانية بضع ثوانٍ
معدّل تكرار الطلب المحتمَل متكرر (فحص عند الطلب لأي إجراء أو طلب) غير متكرّر (عملية تحقّق لمرة واحدة للإجراءات ذات القيمة الأعلى أو الطلبات الأكثر حساسية)
عملية استبعاد للقناة لمهلة معيّنة تقل معظم عمليات الإحماء عن 10 ثوانٍ ولكنها تتضمن الاتصال بالخادم، لذلك يُنصح بتحديد مهلة طويلة (على سبيل المثال، دقيقة واحدة). يتم تقديم طلبات الحصول على بيان السلامة من جهة العميل تكون معظم الطلبات أقل من 10 ثوانٍ ولكنها تتضمّن اتصالًا بالخادم، لذا يُنصح باستخدام مهلة طويلة (دقيقة واحدة مثلاً).
الرمز المميّز لبيان السلامة
يحتوي على تفاصيل الجهاز والتطبيق والحساب ✔️ ✔️
التخزين المؤقت للرموز المميّزة خدمة تخزين مؤقت على الجهاز محمية من Google Play (يُفضَّل عدم النقر هنا.)
فك تشفير الرمز المميّز وإثبات ملكيته عبر خادم Google Play ✔️ ✔️
وقت الاستجابة المعتاد لطلبات فك التشفير من خادم إلى خادم 10 ثوانٍ من المللي ثانية مع مدى التوفّر إلى ثلاث تسعة 10 ثوانٍ من المللي ثانية مع مدى التوفّر إلى ثلاث تسعة
فك تشفير الرمز المميّز وإثبات ملكيته محليًا في بيئة خادم آمنة ✔️
فك تشفير الرمز المميّز والتحقّق من جهة العميل
حداثة بيان السلامة بعض عمليات التخزين المؤقت والتحديث التلقائي في Google Play تتم إعادة احتساب جميع البيانات عند كل طلب.
الحدود
الطلبات لكل تطبيق في اليوم 10000 بشكل افتراضي (يمكن طلب زيادة) 10000 بشكل افتراضي (يمكن طلب زيادة)
الطلبات لكل نسخة تطبيق في الدقيقة عمليات الإحماء: 5 في الدقيقة
رموز التكامل المميّزة: ما من حد أقصى عام*
الرموز المميّزة للتحقق من سلامة التطبيق: 5 في الدقيقة
الحماية
الحد من التلاعب والهجمات المماثلة استخدام الحقل requestHash استخدام الحقل nonce مع ربط المحتوى استنادًا إلى بيانات الطلب
الحد من عمليات إعادة التشغيل والهجمات المماثلة إجراءات التخفيف التلقائية من خلال Google Play استخدام الحقل nonce مع منطق جهة الخادم

* تخضع جميع الطلبات، بما فيها تلك التي ليس لها حدود علنية، لحدود دفاعية غير علنية عند القيم العالية

تقديم طلبات كلاسيكية نادرًا

إنّ إنشاء رمز مميّز يستند إلى البيانات يستهلك الوقت والبيانات والبطارية، ولكل تطبيق حدّ أقصى لعدد الطلبات الكلاسيكية التي يمكن إجراؤها يوميًا. لذلك، يجب إرسال طلبات كلاسيكية للتأكّد من أعلى قيمة أو أن تكون الإجراءات الأكثر حساسية صادقة عندما تريد ضمانًا إضافيًا لطلب عادي. يجب عليك عدم تقديم طلبات كلاسيكية للإجراءات ذات التكرار العالي أو منخفضة القيمة. تجنَّب إجراء طلبات كلاسيكية في كل مرة ينتقل فيها التطبيق إلى المقدّمة أو كل بضع دقائق في الخلفية، وتجنَّب الاتصال من عدد كبير من الأجهزة في الوقت نفسه. قد يتم تقييد التطبيقات التي تُجري عددًا كبيرًا جدًا من الطلبات الكلاسيكية لحماية المستخدمين من عمليات التنفيذ غير الصحيحة.

تجنُّب بيانات التخزين المؤقت

يزيد التخزين المؤقت للقرار من خطر وقوع هجمات مثل استخراج البيانات وإعادة تشغيلها، وذلك عندما يُعاد استخدام بيان جيد من بيئة غير موثوق بها. إذا كنت تفكر في إنشاء طلب كلاسيكي ثم تخزينه مؤقتًا لاستخدامه في وقت لاحق، ننصحك بدلاً من ذلك بإجراء طلب عادي عند الطلب. تتضمّن الطلبات العادية بعض عمليات التخزين المؤقت على الجهاز، ولكن يستخدم Google Play أساليب حماية إضافية للتخفيف من خطر إعادة تشغيل الهجمات وعمليات الاستخراج.

استخدام حقل nonce لحماية الطلبات الكلاسيكية

توفّر واجهة برمجة التطبيقات Play Integrity API حقلاً يُسمى "nonce" يمكن استخدامه لتوفير مزيد من الحماية لتطبيقك من هجمات معيَّنة، مثل هجمات إعادة التشغيل والتلاعب. تعرض واجهة برمجة التطبيقات Play Integrity API القيمة التي حدّدتها في هذا الحقل، داخل ردّ السلامة الموقَّع. اتّبِع بعناية الإرشادات حول كيفية إنشاء أرقام غير صحيحة لحماية تطبيقك من الهجمات.

إعادة محاولة الطلبات الكلاسيكية باستخدام خوارزمية الرقود الأسي الثنائي

قد تؤدي الظروف البيئية، مثل اتصال الإنترنت غير المستقر أو تحميل الجهاز بشكل زائد، إلى تعذُّر عمليات التحقّق من سلامة الجهاز. وقد لا يؤدي ذلك إلى عدم إنشاء تصنيفات لجهاز موثوق به من ناحية أخرى. للتخفيف من هذه السيناريوهات، قم بتضمين خيار إعادة المحاولة مع الرقود الأسي.

نظرة عامة

مخطّط بياني للتسلسل يوضّح التصميم العالي المستوى لواجهة برمجة التطبيقات Play Integrity API

عندما ينفِّذ المستخدم إجراءً عالي القيمة في تطبيقك تريد حمايته باستخدام عملية تحقُّق من السلامة، عليك إكمال الخطوات التالية:

  1. تنشئ الواجهة الخلفية من جهة الخادم لتطبيقك قيمة فريدة وترسلها إلى منطق العميل. وتشير الخطوات المتبقية إلى هذا المنطق باسم "التطبيق".
  2. ينشئ تطبيقك nonce من القيمة الفريدة ومحتوى الإجراء عالي القيمة. ويتم بعد ذلك استدعاء واجهة برمجة التطبيقات Play Integrity API، ما يؤدي إلى إدخال nonce.
  3. يتلقّى تطبيقك بيانًا موقَّعًا ومشفّرًا من واجهة برمجة التطبيقات Play Integrity API.
  4. يمرّر تطبيقك بيان التوقيع والمشفَّر إلى خلفية تطبيقك.
  5. وتُرسِل الخلفية في تطبيقك القرار إلى خادم Google Play. ويفكّ خادم Google Play تشفير البيانات ويتأكّد من صحتها، ويعرض النتائج إلى الواجهة الخلفية للتطبيق.
  6. وتحدّد الواجهة الخلفية لتطبيقك كيفية المتابعة استنادًا إلى الإشارات المضمَّنة في حمولة البيانات الخاصة بالرمز المميّز.
  7. ترسل خلفية تطبيقك نتائج القرار إلى تطبيقك.

إنشاء رقم Nonce

عند حماية إجراء في تطبيقك باستخدام واجهة برمجة التطبيقات Play Integrity API، يمكنك الاستفادة من الحقل nonce للحدّ من أنواع معيّنة من الهجمات، مثل هجمات التلاعب بالوسيط (PITM) وهجمات إعادة التشغيل. تعرض واجهة برمجة التطبيقات Play Integrity API القيمة التي حدّدتها في هذا الحقل داخل استجابة السلامة الموقَّعة.

يجب أن تكون القيمة التي تم ضبطها في الحقل nonce بالتنسيق الصحيح:

  • String
  • عدم أمان عنوان URL
  • تم ترميزه كـ Base64 وغير قابل للالتفاف
  • 16 حرفًا كحدّ أدنى
  • 500 حرف كحدّ أقصى

في ما يلي بعض الطرق الشائعة لاستخدام الحقل nonce في واجهة برمجة التطبيقات Play Integrity API. للحصول على أعلى مستوى من الحماية من nonce، يمكنك الجمع بين الطرق الموضَّحة أدناه.

تضمين تجزئة طلب للحماية من التلاعب

يمكنك استخدام معلَمة nonce في طلب بيانات من واجهة برمجة التطبيقات الكلاسيكية مثلما تستخدم المعلَمة requestHash في طلب البيانات من واجهة برمجة التطبيقات العادية لحماية محتوى الطلب من التلاعب.

عند طلب بيان سلامة:

  1. يمكنك احتساب ملخّص لجميع مَعلمات الطلب المهمة (مثل SHA256 لتسلسل طلبات ثابت) من إجراء المستخدِم أو طلب الخادم الجاري.
  2. استخدِم setNonce لضبط الحقل nonce على قيمة الملخّص الذي تم حسابه.

عند تلقّي بيان سلامة:

  1. يجب فك ترميز الرمز المميّز للأمان والتحقّق من صحته، والحصول على الملخّص من حقل nonce.
  2. احتساب ملخص للطلب بالطريقة نفسها المستخدَمة في التطبيق (مثلاً SHA256 لتسلسل ثابت للطلبات)
  3. مقارنة الملخّصات من جهة التطبيق ومن جهة الخادم وفي حال عدم التطابق، يصبح الطلب غير موثوق به.

تضمين قيم فريدة للحماية من هجمات إعادة التشغيل

لمنع المستخدمين الضارين من إعادة استخدام الردود السابقة من واجهة برمجة التطبيقات Play Integrity API، يمكنك استخدام الحقل nonce لتحديد كل رسالة بشكل فريد.

عند طلب بيان سلامة:

  1. الحصول على قيمة فريدة عامة بطريقة لا يمكن للمستخدمين الضارين توقّعها على سبيل المثال، قد يكون الرقم العشوائي الآمن من ناحية التشفير والذي يتم إنشاؤه من جهة الخادم مثلًا مثل هذه القيمة أو معرِّفًا موجودًا مسبقًا، مثل جلسة أو معرِّف معاملة. هناك خيار أبسط وأقل أمانًا وهو إنشاء رقم عشوائي على الجهاز. نوصي بإنشاء قيم يبلغ حجمها 128 بت أو أكبر.
  2. يمكنك طلب setNonce() لضبط الحقل nonce على القيمة الفريدة من الخطوة 1.

عند تلقّي بيان سلامة:

  1. يمكنك فك ترميز الرمز المميّز للسلامة والتحقّق من ذلك، والحصول على القيمة الفريدة من الحقل nonce.
  2. إذا تم إنشاء القيمة من الخطوة 1 على الخادم، تأكَّد من أنّ القيمة الفريدة التي تم استلامها كانت إحدى القيم التي تم إنشاؤها، وأنّه يتم استخدامها لأول مرة (سيحتاج الخادم إلى الاحتفاظ بسجلّ بالقيم التي تم إنشاؤها لمدة مناسبة). إذا سبق أن تم استخدام القيمة الفريدة المستلمة أو لم تظهر في السجل، فارفض الطلب
  3. إذا تم إنشاء القيمة الفريدة على الجهاز، تأكَّد من أنّه يتم استخدام القيمة المُستلَمة لأول مرة (يجب أن يحتفظ الخادم بسجلّ بالقيم التي سبق رؤيتها لمدة مناسبة). إذا تم استخدام القيمة الفريدة المستلمة بالفعل، فرفض الطلب.

الجمع بين وسائل الحماية ضد هجمات التلاعب وإعادة التشغيل (يُنصَح به)

يمكن استخدام الحقل nonce للحماية من التلاعب والهجمات لإعادة التشغيل في الوقت نفسه. للقيام بذلك، قم بإنشاء القيمة الفريدة على النحو الموضح أعلاه، وتضمينها كجزء من طلبك. ثم احسب تجزئة الطلب، مع التأكد من تضمين القيمة الفريدة كجزء من التجزئة. يكون التنفيذ الذي يجمع بين كلا النهجين على النحو التالي:

عند طلب بيان سلامة:

  1. يبدأ المستخدم الإجراء ذي القيمة العالية.
  2. يمكنك الحصول على قيمة فريدة لهذا الإجراء كما هو موضَّح في قسم تضمين قيم فريدة للحماية من هجمات إعادة التشغيل.
  3. يمكنك إعداد الرسالة التي تريد حمايتها. قم بتضمين القيمة الفريدة من الخطوة 2 في الرسالة.
  4. يحسب تطبيقك ملخصًا للرسالة التي يريد حمايتها، كما هو موضّح في القسم تضمين تجزئة طلب للحماية من التلاعب. بما أن الرسالة تحتوي على القيمة الفريدة، فإن القيمة الفريدة هي جزء من التجزئة.
  5. استخدِم setNonce() لضبط الحقل nonce على الملخّص المحسوب من الخطوة السابقة.

عند تلقّي بيان سلامة:

  1. الحصول على القيمة الفريدة من الطلب
  2. يجب فك ترميز الرمز المميّز للأمان والتحقّق من صحته، والحصول على الملخّص من حقل nonce.
  3. كما هو موضّح في قسم تضمين طلب تجزئة للحماية من التلاعب، عليك إعادة حساب الملخّص على جهة الخادم والتأكّد من أنّه يتطابق مع الملخّص الذي تم الحصول عليه من الرمز المميّز للأمان.
  4. كما هو موضّح في قسم تضمين قيم فريدة للحماية من الهجمات لإعادة التشغيل، تحقَّق من صلاحية القيمة الفريدة.

يوضّح مخطط التسلسل التالي هذه الخطوات باستخدام nonce من جانب الخادم:

مخطط التسلسل الذي يوضح كيفية الحماية من التلاعب
وهجمات إعادة التشغيل

طلب بيان سلامة

بعد إنشاء nonce، يمكنك طلب بيان سلامة من Google Play. للقيام بذلك، أكمل الخطوات التالية:

  1. أنشئ IntegrityManager، كما هو موضّح في الأمثلة التالية.
  2. يمكنك إنشاء IntegrityTokenRequest، مع توفير nonce من خلال طريقة setNonce() في أداة الإنشاء المرتبطة. وعلى التطبيقات التي يتم توزيعها حصريًا خارج Google Play وحِزم تطوير البرامج (SDK) تحديد رقم مشروع Google Cloud من خلال الطريقة setCloudProjectNumber(). يتم ربط التطبيقات على Google Play بمشروع على Cloud في Play Console ولا تحتاج إلى تحديد رقم المشروع على السحابة الإلكترونية في الطلب.
  3. يمكنك استخدام المدير للاتصال بـ 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();
}

مدمجة مع المحتوى

/// 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 المختلفة:

  • يستخدم JWE A256KW لـ alg وA256GCM لـ enc

  • تستخدم شركة JWS ES256.

فك التشفير وإثبات الملكية على خوادم Google (خيار يُنصَح به)

تتيح لك واجهة برمجة التطبيقات Play Integrity API فك تشفير بيان السلامة والتحقّق من صحته على خوادم Google، ما يعزِّز أمان تطبيقك. للقيام بذلك، أكمل هذه الخطوات:

  1. يمكنك إنشاء حساب خدمة ضمن مشروع Google Cloud المرتبط بتطبيقك.
  2. على خادم تطبيقك، أحضر رمز الدخول من بيانات اعتماد حساب الخدمة باستخدام نطاق playintegrity، وقدِّم الطلب التالي:

    playintegrity.googleapis.com/v1/PACKAGE_NAME:decodeIntegrityToken -d \
    '{ "integrity_token": "INTEGRITY_TOKEN" }'
  3. اقرأ استجابة 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();

الحمولة الناتجة هي رمز مميّز بنص عادي يحتوي على بيانات السلامة.