ایجاد درخواست کلاسیک میانای برنامه‌سازی کاربردی

اگر فقط قصد دارید درخواست‌های استاندارد API را انجام دهید، که برای اکثر توسعه‌دهندگان مناسب است، می‌توانید به بخش حکم‌های یکپارچگی بروید. این صفحه نحوه ارائه درخواست‌های API قدیمی برای حکم‌های یکپارچگی را شرح می‌دهد که در Android 4.4 (سطح API‏ ۱۹) یا بالاتر پشتیبانی می‌شود.

ملاحظات

مقایسه درخواست‌های استاندارد و کلاسیک

می‌توانید درخواست‌های استاندارد، درخواست‌های کلاسیک، یا ترکیبی از این دو را بسته به نیازهای امنیتی و ضدسوءاستفاده برنامه‌تان ایجاد کنید. درخواست‌های استاندارد برای همه برنامه‌ها و بازی‌ها مناسب است و می‌توان از آن‌ها برای بررسی واقعی بودن هر کنش یا فراخوانی سرور استفاده کرد، درحالی‌که برخی‌از محافظت‌ها دربرابر قابلیت بازپخش و استخراج به Google Play واگذار می‌شود. درخواست‌های کلاسیک هزینه بیشتری دارند و شما مسئول اجرای صحیح آن‌ها برای محافظت دربرابر استخراج و انواع خاصی از حملات هستید. درخواست‌های کلاسیک باید کمتر از درخواست‌های استاندارد انجام شوند، برای مثال به‌عنوان یک درخواست گاه‌به‌گاه برای بررسی اینکه آیا یک اقدام بسیار ارزشمند یا حساس واقعی است یا خیر.

جدول زیر تفاوت‌های کلیدی بین دو نوع درخواست را برجسته می‌کند:

درخواست استاندارد میانای برنامه‌سازی کاربردی درخواست کلاسیک میانای برنامه‌سازی کاربردی
پیش‌نیازها
حداقل کیت توسعه نرم‌افزار Android موردنیاز* ‫Android نسخه ۶.۰ (سطح میانای برنامه‌سازی کاربردی ۲۳) یا بالاتر ‫Android نسخه ۶.۰ (سطح میانای برنامه‌سازی کاربردی ۲۳) یا بالاتر
الزامات Google Play «فروشگاه Google Play» و «خدمات Google Play» «فروشگاه Google Play» و «خدمات Google Play»
جزئیات یکپارچه‌سازی
گرم کردن میانای برنامه‌سازی کاربردی لازم است ✔️ (چند ثانیه) ❌
تأخیر درخواست معمول چند صد میلی‌ثانیه چند ثانیه
بسامد درخواست احتمالی مکرر (بررسی درصورت درخواست برای هرگونه کنش یا درخواست) به‌ندرت (بررسی یک‌باره برای کنش‌های دارای بالاترین ارزش یا حساس‌ترین درخواست‌ها)
تعلیق اکثر آماده‌سازی‌ها کمتر از ۱۰ ثانیه طول می‌کشند اما شامل فراخوانی سرور می‌شوند، بنابراین مهلت زمانی طولانی (مثلاً ۱ دقیقه) توصیه می‌شود. درخواست‌های رأی در سمت کارخواه اتفاق می‌افتد بیشتر درخواست‌ها کمتر از ۱۰ ثانیه طول می‌کشد اما شامل تماس سرور می‌شود، بنابراین مهلت زمانی طولانی (مثلاً ۱ دقیقه) توصیه می‌شود
کد حکم تمامیت
حاوی جزئیات دستگاه، برنامه، و حساب است ✔️ ✔️
ذخیره کردن کد در حافظه نهان ذخیره‌سازی موقت درون‌دستگاهی محافظت‌شده توسط Google Play توصیه نمی‌شود
رمزگشایی و تأیید کردن کد ازطریق سرور Google Play ✔️ ✔️
تأخیر معمول درخواست سرور به سرور برای رمزگشایی ۱۰ میلی‌ثانیه با دردسترس بودن ۹۹٫۹٪ ۱۰ میلی‌ثانیه با دردسترس بودن ۹۹٫۹٪
رمزگشایی و درستی‌سنجی محلی کد در محیط سرور امن ❌ ✔️
رمزگشایی و درستی‌سنجی کردن سمت کارخواه توکن ❌ ❌
تازگی حکم تمامیت برخی‌از ذخیره‌سازی‌های خودکار در حافظه پنهان و بازآوری‌ها توسط Google Play انجام می‌شود همه حکم‌ها در هر درخواست دوباره محاسبه می‌شود
محدودیت‌ها
درخواست‌ها برای هر برنامه در روز ۱۰٬۰۰۰ به‌طور پیش‌فرض (می‌توان درخواست افزایش داد) ۱۰٬۰۰۰ به‌طور پیش‌فرض (می‌توان درخواست افزایش داد)
درخواست‌ها به‌ازای هر نمونه برنامه در دقیقه آماده‌سازی: ۵ بار در دقیقه
نشان‌های یکپارچگی: بدون محدودیت عمومی**
توکن‌های یکپارچگی: ۵ توکن در دقیقه
محافظت
کاهش خطر دست‌کاری و حملات مشابه استفاده از فیلد requestHash استفاده از فیلد nonce با اتصال محتوا براساس داده‌های درخواست
کاهش دادن حملات بازپخش و حملات مشابه کاهش خودکار توسط Google Play استفاده از فیلد nonce با منطق سمت سرور

* برای کتابخانه Play Integrity API نسخه ۱.۴.۰ و بالاتر، حداقل کیت توسعه نرم‌افزار Android پشتیبانی‌شده برای هر دو نوع درخواست یکسان است و توسط minSdkVersion کتابخانه تعیین می‌شود. برای نسخه ۱.۳.۰ و نسخه‌های قبلی، حداقل کیت توسعه نرم‌افزار Android موردنیاز برای درخواست‌های API استاندارد، Android 5.0 (سطح API‏ ۲۱) و برای درخواست‌های API کلاسیک، Android 4.4 (سطح API‏ ۱۹) است.

** همه درخواست‌ها، ازجمله درخواست‌های بدون محدودیت عمومی، مشمول محدودیت‌های دفاعی غیرعمومی در مقادیر بالا هستند.

درخواست‌های کلاسیک را به‌ندرت ایجاد کنید

تولید کردن یک توکن یکپارچگی زمان، داده، و باتری مصرف می‌کند و هر برنامه حداکثر تعداد درخواست‌های کلاسیکی دارد که می‌تواند در روز ارائه دهد. بنابراین، فقط زمانی باید درخواست‌های کلاسیک را برای بررسی واقعی بودن بالاترین مقدار یا حساس‌ترین کنش‌ها انجام دهید که بخواهید تضمین بیشتری نسبت‌به درخواست استاندارد داشته باشید. نباید برای کنش‌های با بسامد بالا یا کم‌ارزش درخواست کلاسیک ایجاد کنید. هر بار که برنامه به پیش‌زمینه می‌رود یا هر چند دقیقه یک‌بار در پس‌زمینه، درخواست‌های کلاسیک ایجاد نکنید و از تماس هم‌زمان از تعداد زیادی دستگاه خودداری کنید. برنامه‌ای که تعداد زیادی تماس درخواست کلاسیک برقرار می‌کند ممکن است برای محافظت از کاربران دربرابر پیاده‌سازی‌های نادرست، محدود شود.

از ذخیره کردن حکم‌ها در حافظه نهان خودداری کنید

ذخیره کردن حکم در حافظه نهان خطر حملاتی مانند استخراج و بازپخش را افزایش می‌دهد، که در آن از حکم خوب در محیطی غیرقابل‌اعتماد مجدداً استفاده می‌شود. اگر قصد دارید درخواست کلاسیک ایجاد کنید و سپس آن را برای استفاده بعدی ذخیره کنید، توصیه می‌شود به‌جای آن، درخواست استاندارد را به‌صورت درخواستی انجام دهید. درخواست‌های استاندارد شامل مقداری ذخیره‌سازی در حافظه نهان دستگاه است، اما Google Play از فنون محافظتی اضافی برای کاهش خطر حملات بازپخش و استخراج داده استفاده می‌کند.

از فیلد nonce برای محافظت از درخواست‌های کلاسیک استفاده کنید

‫Play Integrity API فیلدی به‌نام nonce ارائه می‌دهد که می‌توان از آن برای محافظت بیشتر از برنامه دربرابر حملات خاص، مانند حملات بازپخش و دست‌کاری، استفاده کرد. ‫Play Integrity API مقداری را که در این فیلد تنظیم کرده‌اید، در پاسخ یکپارچگی امضاشده برمی‌گرداند. برای محافظت از برنامه‌تان دربرابر حملات، راهنمای نحوه تولید nonce را به‌دقت دنبال کنید.

درخواست‌های کلاسیک را با عقب‌گرد نمایی دوباره امتحان کنید

شرایط محیطی، مانند اتصال اینترنت ناپایدار یا دستگاهی که بار بیش‌ازحد دارد، می‌تواند باعث شود بررسی‌های تمامیت دستگاه ناموفق باشد. این امر می‌تواند منجر به این شود که هیچ برچسبی برای دستگاهی که درغیراین‌صورت قابل‌اعتماد است تولید نشود. برای کاهش این سناریوها، گزینه امتحان مجدد با عقب‌نشینی نمایی را اضافه کنید.

نمای کلی

شکل ۱. نمودار توالی که طراحی سطح بالای 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-safe
  • کدبندی‌شده به‌صورت Base64 و بدون پیچش
  • حداقل ۱۶ نویسه داشته باشد
  • حداکثر ۵۰۰ نویسه داشته باشد

در زیر چند روش رایج برای استفاده از فیلد nonce در Play Integrity API آورده شده است. برای دریافت قوی‌ترین محافظت از nonce، می‌توانید روش‌های زیر را ترکیب کنید.

برای محافظت دربرابر دست‌کاری، درهم‌سازی درخواست را اضافه کنید

می‌توانید از پارامتر nonce در درخواست Classic API به‌طور مشابه با پارامتر requestHash در درخواست Standard API استفاده کنید تا از محتوای درخواست دربرابر دست‌کاری محافظت کنید.

وقتی حکم تمامیت درخواست می‌کنید:

  1. خلاصه‌ای از همه پارامترهای درخواست حیاتی (مثلاً SHA256 از سریال‌سازی درخواست پایدار) را از کنش کاربر یا درخواست سرور که درحال وقوع است محاسبه کنید.
  2. از setNonce برای تنظیم فیلد nonce روی مقدار خلاصه محاسبه‌شده استفاده کنید.

وقتی حکم تمامیت دریافت می‌کنید:

  1. توکن تمامیت را رمزگشایی و تأیید کنید و خلاصه را از فیلد nonce دریافت کنید.
  2. خلاصه‌ای از درخواست را به همان روشی که در برنامه انجام می‌شود محاسبه کنید (مثلاً SHA256 از سریال‌سازی درخواست پایدار).
  3. خلاصه‌های سمت برنامه و سمت سرور را مقایسه کنید. اگر مطابقت نداشته باشند، درخواست قابل‌اعتماد نیست.

برای محافظت دربرابر حملات بازپخش، مقادیر منحصربه‌فرد را اضافه کنید

برای جلوگیری از استفاده مجدد کاربران مخرب از پاسخ‌های قبلی Play Integrity API، می‌توانید از فیلد nonce برای شناسایی منحصربه‌فرد هر پیام استفاده کنید.

وقتی حکم تمامیت درخواست می‌کنید:

  1. مقدار منحصربه‌فردی را در سطح جهانی به‌دست آورید که کاربران مخرب نتوانند آن را پیش‌بینی کنند. برای مثال، یک عدد تصادفی امن ازنظر رمزنگاری که در سمت سرور تولید شده است می‌تواند چنین مقداری باشد، یا یک شناسه ازپیش موجود، مانند شناسه جلسه یا تراکنش. یک نوع ساده‌تر و با امنیت کمتر، تولید عدد تصادفی در دستگاه است. توصیه می‌کنیم مقادیری با ۱۲۸ بیت یا بیشتر ایجاد کنید.
  2. setNonce() را فراخوانی کنید تا فیلد nonce را روی مقدار یکتای مرحله ۱ تنظیم کنید.

وقتی حکم تمامیت دریافت می‌کنید:

  1. رمزگشایی و درستی‌سنجی کردن کد تمامیت، و دریافت مقدار یکتا از فیلد nonce.
  2. اگر مقدار مرحله ۱ در سرور تولید شده است، بررسی کنید که مقدار یکتای دریافتی یکی از مقادیر تولیدشده باشد و برای اولین‌بار استفاده شود (سرور شما باید سوابق مقادیر تولیدشده را برای مدت مناسبی نگه دارد). اگر مقدار یکتای دریافتی قبلاً استفاده شده است یا در سابقه وجود ندارد، درخواست را رد کنید
  3. درغیراین‌صورت، اگر مقدار یکتا در دستگاه تولید شده است، بررسی کنید که مقدار دریافتی برای اولین‌بار استفاده می‌شود (سرور شما باید سابقه‌ای از مقادیر دیده‌شده را برای مدت مناسبی نگه دارد). اگر مقدار یکتای دریافتی قبلاً استفاده شده است، درخواست را رد کنید.

ترکیب هر دو محافظت دربرابر دست‌کاری و حملات بازپخش (توصیه‌شده)

می‌توان از فیلد nonce برای محافظت دربرابر دست‌کاری و حملات بازپخش به‌طور هم‌زمان استفاده کرد. برای انجام این کار، مقدار منحصربه‌فرد را همان‌طور که در بالا توضیح داده شد تولید کنید و آن را به‌عنوان بخشی از درخواستتان اضافه کنید. سپس درهم‌سازی درخواست را محاسبه کنید و مطمئن شوید که مقدار منحصربه‌فرد را به‌عنوان بخشی از درهم‌سازی اضافه کرده‌اید. پیاده‌سازی‌ای که هر دو رویکرد را ترکیب می‌کند به‌صورت زیر است:

وقتی حکم تمامیت درخواست می‌کنید:

  1. کاربر کنش باارزش را شروع می‌کند.
  2. همان‌طور که در بخش گنجاندن مقادیر منحصربه‌فرد برای محافظت دربرابر حملات تکرار شرح داده شده است، مقدار منحصربه‌فردی برای این کنش دریافت کنید.
  3. پیامی را که می‌خواهید محافظت شود آماده کنید. مقدار منحصربه‌فرد مرحله ۲ را در پیام اضافه کنید.
  4. برنامه‌تان خلاصه پیامی را که می‌خواهد از آن محافظت کند محاسبه می‌کند، همان‌طور که در بخش گنجاندن درهم‌سازی درخواست برای محافظت دربرابر دست‌کاری شرح داده شده است. ازآنجایی‌که پیام حاوی مقدار یکتا است، مقدار یکتا بخشی از درهم‌سازی است.
  5. از setNonce() برای تنظیم فیلد nonce روی خلاصه محاسبه‌شده از مرحله قبلی استفاده کنید.

وقتی حکم تمامیت دریافت می‌کنید:

  1. مقدار منحصربه‌فرد را از درخواست دریافت کنید
  2. توکن تمامیت را رمزگشایی و تأیید کنید و خلاصه را از فیلد nonce دریافت کنید.
  3. همان‌طور که در بخش درج درهم‌سازی درخواست برای محافظت دربرابر دست‌کاری شرح داده شده است، خلاصه را در سمت سرور دوباره محاسبه کنید و بررسی کنید که با خلاصه به‌دست‌آمده از «کلید یکپارچگی» مطابقت داشته باشد.
  4. همان‌طور که در بخش گنجاندن مقادیر منحصربه‌فرد برای محافظت دربرابر حملات بازپخش شرح داده شده است، اعتبار مقدار منحصربه‌فرد را بررسی کنید.

نمودار توالی زیر این مراحل را با nonce سمت سرور نشان می‌دهد:

شکل ۲. نمودار توالی که نحوه محافظت دربرابر دست‌کاری و حملات بازپخش را نشان می‌دهد.

درخواست حکم تمامیت

پس‌از تولید nonce، می‌توانید حکم یکپارچگی را از Google Play درخواست کنید. برای انجام این کار، مراحل زیر را تکمیل کنید:

  1. همان‌طور که در مثال‌های زیر نشان داده شده است، یک IntegrityManager ایجاد کنید.
  2. یک IntegrityTokenRequest بسازید و nonce را ازطریق روش setNonce() در سازنده مربوطه ارائه دهید. برنامه‌هایی که منحصراً در خارج از Google Play توزیع می‌شوند و کیت‌های توسعه نرم‌افزار نیز باید شماره پروژه Google Cloud خود را ازطریق روش setCloudProjectNumber() مشخص کنند. برنامه‌های موجود در Google Play به پروژه Cloud در «کنسول Play» پیوند داده شده‌اند و نیازی به تنظیم شماره پروژه Cloud در درخواست ندارند.
  3. از مدیر برای تماس با requestIntegrityToken() استفاده کنید و IntegrityTokenRequest را ارائه دهید.

کاتلین

// 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())

جاوا

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 = ...

    // Initialize the V2 manager. Requires Play Integrity Unity Plugin v2.0.0
    // or higher.
    var integrityManager = new IntegrityManagerV2();

    // 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 != null &&
        requestIntegrityTokenOperation.Error.ErrorCode != IntegrityErrorCode.NoError)
    {
        AppendStatusLog("IntegrityAsyncOperation failed with error: " +
                requestIntegrityTokenOperation.Error.ErrorCode);
        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 Web Token (JWT) تودرتو است که JSON Web Encryption (JWE) JSON Web Signature (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» به کلیدهای مختص زبان (در مورد ما، زبان برنامه‌نویسی Java) در پس‌بک برنامه رمزگشایی کنید. توجه داشته باشید که کلیدها بااستفاده از پرچم‌های پیش‌فرض، کدبندی base64 شده‌اند.

کاتلین

// 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))

جاوا

// 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 تودرتو را درستی‌سنجی و استخراج کنید.

کاتلین

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()

جاوا

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 دریافت کند.

برای آشنایی با نحوه راه‌اندازی این کادرهای گفتگو از برنامه‌تان براساس پاسخ سرور، کادرهای گفتگوی اصلاح را ببینید.