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

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

الاعتبارات

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

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

يسلط الجدول التالي الضوء على الاختلافات الرئيسية بين نوعي الطلبات:

طلب بيانات عادي من واجهة برمجة التطبيقات طلب واجهة برمجة التطبيقات الكلاسيكية
المتطلّبات الأساسية
يجب توفير الحد الأدنى من إصدار حزمة تطوير البرامج (SDK) لنظام التشغيل Android. الإصدار 5.0 من Android (المستوى 21 من واجهة برمجة التطبيقات) أو إصدار أحدث Android 4.4 (المستوى 19 لواجهة برمجة التطبيقات) أو إصدار أحدث
متطلبات Google Play "متجر Google Play" و"خدمات Google Play" "متجر Google Play" و"خدمات Google Play"
تفاصيل عملية الدمج
مطلوب إعادة تشغيل واجهة برمجة التطبيقات ✔️ (بضع ثوانٍ)
وقت الاستجابة المعتاد للطلب بضع مئات من المللي ثانية بضع ثوانٍ
معدل تكرار الطلب المحتمل متكرر (فحص عند الطلب لأي إجراء أو طلب) نادرة (التحقق لمرة واحدة من الإجراءات ذات القيمة الأعلى أو الطلبات الأكثر حساسية)
عملية استبعاد للقناة لمهلة معيّنة تكون معظم عمليات الإحماء أقل من 10 ثوانٍ ولكنها تتضمن اتصالاً بالخادم، لذا يُنصح بمهلة طويلة (على سبيل المثال دقيقة واحدة). تُجرى طلبات البيان من جهة العميل تقل مدة معظم الطلبات عن 10 ثوانٍ ولكنها تتضمن اتصالاً بالخادم، لذا يُنصح باستخدام مهلة طويلة (مثلاً دقيقة واحدة).
الرمز المميّز لبيان السلامة
يحتوي على تفاصيل الجهاز والتطبيق والحساب ✔️ ✔️
التخزين المؤقت للرموز المميّزة حماية للتخزين المؤقت على الجهاز من خلال Google Play (يُفضَّل عدم النقر هنا.)
فك تشفير الرمز المميّز والتحقّق منه عبر خادم Google Play ✔️ ✔️
وقت الاستجابة النموذجي لطلب خادم إلى خادم لفك التشفير 10 ثوان من المللي ثانية مع توفُّر ثلاثة تسعة 10 ثوان من المللي ثانية مع توفُّر ثلاثة تسعة
فك تشفير الرمز المميّز والتحقّق منه محليًا في بيئة خادم آمنة ✔️
فك تشفير الرمز المميّز والتحقّق منه من جهة العميل
حداثة بيان السلامة بعض عمليات التخزين المؤقت والتحديث التلقائية من خلال Google Play تتم إعادة احتساب جميع القرارات عند كل طلب.
الحدود
الطلبات لكل تطبيق في اليوم 10,000 بشكل تلقائي (يمكن طلب زيادة) 10,000 بشكل تلقائي (يمكن طلب زيادة)
الطلبات لكل نسخة افتراضية من التطبيق في الدقيقة عمليات الإحماء: 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. ترسِل خلفية تطبيقك نتائج القرار إلى تطبيقك.

إنشاء رقم خاص

عند حماية إجراء في تطبيقك باستخدام واجهة برمجة التطبيقات 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 بمشروع على السحابة الإلكترونية في Play Console ولا تحتاج إلى تحديد رقم المشروع على Google Cloud في الطلب.
  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 Web Token (JWT) المدمَج، وهو JSON Web Encryption (JWE) من توقيع JSON Web (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();

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