یک درخواست API کلاسیک ایجاد کنید

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

ملاحظات

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

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

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

درخواست API استاندارد درخواست API کلاسیک
پیش‌نیازها
حداقل SDK اندروید مورد نیاز * اندروید ۶.۰ (سطح API ۲۳) یا بالاتر اندروید ۶.۰ (سطح API ۲۳) یا بالاتر
الزامات گوگل پلی فروشگاه گوگل پلی و سرویس‌های گوگل پلی فروشگاه گوگل پلی و سرویس‌های گوگل پلی
جزئیات ادغام
گرم کردن API مورد نیاز است ✔️ (چند ثانیه)
تأخیر معمول درخواست چند صد میلی ثانیه چند ثانیه
فراوانی درخواست‌های بالقوه مکرر (بررسی در صورت درخواست برای هرگونه اقدام یا درخواست) نادر (بررسی یک‌باره برای اقدامات با ارزش بالا یا حساس‌ترین درخواست‌ها)
تایم اوت‌ها بیشتر گرم کردن‌ها زیر ۱۰ ثانیه طول می‌کشند، اما شامل فراخوانی سرور می‌شوند، بنابراین توصیه می‌شود مدت زمان زیادی (مثلاً ۱ دقیقه) صبر کنید. درخواست‌های صدور حکم از طرف کلاینت انجام می‌شود. بیشتر درخواست‌ها کمتر از ۱۰ ثانیه هستند اما شامل فراخوانی سرور می‌شوند، بنابراین توصیه می‌شود مدت زمان انتظار طولانی باشد (مثلاً ۱ دقیقه).
توکن حکم صداقت
شامل جزئیات دستگاه، برنامه و حساب کاربری ✔️ ✔️
ذخیره سازی توکن ذخیره سازی محافظت شده روی دستگاه توسط گوگل پلی توصیه نمی‌شود
رمزگشایی و تأیید توکن از طریق سرور گوگل پلی ✔️ ✔️
تأخیر معمول درخواست رمزگشایی از سرور به سرور ده‌ها میلی‌ثانیه با دسترسی سه-نه ده‌ها میلی‌ثانیه با دسترسی سه-نه
رمزگشایی و تأیید توکن به صورت محلی در یک محیط سرور امن ✔️
رمزگشایی و تأیید توکن سمت کلاینت
تازگی حکم صداقت مقداری ذخیره‌سازی و به‌روزرسانی خودکار توسط گوگل پلی تمام احکام صادره برای هر درخواست مجدداً محاسبه می‌شوند
محدودیت‌ها
درخواست‌ها به ازای هر برنامه در روز ۱۰،۰۰۰ به طور پیش‌فرض (افزایش قابل درخواست است) ۱۰،۰۰۰ به طور پیش‌فرض (افزایش قابل درخواست است)
درخواست‌ها به ازای هر نمونه برنامه در هر دقیقه گرم کردن: ۵ بار در دقیقه
توکن‌های یکپارچگی: بدون محدودیت عمومی **
توکن‌های یکپارچگی: ۵ عدد در دقیقه
حفاظت
مقابله با دستکاری و حملات مشابه استفاده از فیلد requestHash استفاده از فیلد nonce با اتصال محتوا بر اساس داده‌های درخواست
مقابله با حملات تکرارشونده و مشابه کاهش خودکار توسط گوگل پلی استفاده از فیلد nonce با منطق سمت سرور

* برای کتابخانه Play Integrity API نسخه ۱.۴.۰ و بالاتر، حداقل SDK اندروید پشتیبانی‌شده برای هر دو نوع درخواست یکسان است و توسط minSdkVersion کتابخانه تعیین می‌شود. برای نسخه ۱.۳.۰ و نسخه‌های قبل از آن، حداقل SDK اندروید مورد نیاز برای درخواست‌های Standard API، اندروید ۵.۰ (سطح API ۲۱) و برای درخواست‌های Classic API، اندروید ۴.۴ (سطح API ۱۹) است.

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

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

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

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

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

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

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

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

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

نمای کلی

شکل ۱. نمودار توالی که طراحی سطح بالای Play Integrity API را نشان می‌دهد.

وقتی کاربر یک عمل با ارزش بالا را در برنامه شما انجام می‌دهد که می‌خواهید با بررسی یکپارچگی از آن محافظت کنید، مراحل زیر را انجام دهید:

  1. بک‌اند سمت سرور برنامه شما یک مقدار منحصر به فرد را تولید و به منطق سمت کلاینت ارسال می‌کند. مراحل باقی‌مانده به این منطق به عنوان "برنامه" شما اشاره می‌کنند.
  2. برنامه شما nonce را از مقدار منحصر به فرد و محتوای اقدام ارزشمند شما ایجاد می‌کند. سپس API Play Integrity را فراخوانی می‌کند و nonce را به آن ارسال می‌کند.
  3. برنامه شما یک حکم امضا شده و رمزگذاری شده از Play Integrity API دریافت می‌کند.
  4. برنامه شما حکم امضا شده و رمزگذاری شده را به backend برنامه شما منتقل می‌کند.
  5. بخش مدیریت اپلیکیشن شما، نتیجه را به سرور گوگل پلی ارسال می‌کند. سرور گوگل پلی، نتیجه را رمزگشایی و تأیید می‌کند و نتایج را به بخش مدیریت اپلیکیشن شما برمی‌گرداند.
  6. بخش مدیریت برنامه شما، بر اساس سیگنال‌های موجود در توکن، نحوه‌ی ادامه‌ی کار را تعیین می‌کند.
  7. بک‌اند برنامه شما نتایج تصمیم‌گیری را به برنامه شما ارسال می‌کند.

یک نانس (nonce) ایجاد کنید

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

مقدار تعیین شده در فیلد nonce باید به درستی قالب بندی شود:

  • String
  • ایمن در برابر URL
  • کدگذاری شده به صورت Base64 و بدون پوشش
  • حداقل ۱۶ کاراکتر
  • حداکثر ۵۰۰ کاراکتر

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

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

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

وقتی درخواست حکم عدم سوء پیشینه می‌کنید:

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

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

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

برای محافظت در برابر حملات تکرارشونده، مقادیر منحصر به فرد را وارد کنید

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

وقتی درخواست حکم عدم سوء پیشینه می‌کنید:

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

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

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

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

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

وقتی درخواست حکم عدم سوء پیشینه می‌کنید:

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

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

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

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

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

درخواست حکم عدم سوء پیشینه

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

  1. همانطور که در مثال‌های زیر نشان داده شده است، یک IntegrityManager ایجاد کنید.
  2. یک IntegrityTokenRequest بسازید و nonce را از طریق متد setNonce() در سازنده‌ی مرتبط ارائه دهید. برنامه‌هایی که منحصراً خارج از Google Play و SDKها توزیع شده‌اند نیز باید شماره پروژه Google Cloud خود را از طریق متد setCloudProjectNumber() مشخص کنند. برنامه‌های موجود در Google Play به یک پروژه Cloud در Play Console متصل هستند و نیازی به تنظیم شماره پروژه Cloud در درخواست ندارند.
  3. از manager برای فراخوانی 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());

وحدت

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

موتور غیرواقعی

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

رمزگشایی و تأیید حکم یکپارچگی

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

قالب توکن

این توکن یک JSON Web Token (JWT) تو در تو است، که همان JSON Web Encryption (JWE) از JSON Web Signature (JWS) است. اجزای JWE و JWS با استفاده از سریال‌سازی فشرده نمایش داده می‌شوند.

الگوریتم‌های رمزگذاری/امضا در پیاده‌سازی‌های مختلف JWT به خوبی پشتیبانی می‌شوند:

  • JWE از A256KW برای alg و A256GCM برای enc استفاده می‌کند.

  • JWS از ES256 استفاده می‌کند.

رمزگشایی و تأیید در سرورهای گوگل (توصیه می‌شود)

رابط برنامه‌نویسی کاربردی Play Integrity به شما امکان می‌دهد تا حکم یکپارچگی را در سرورهای گوگل رمزگشایی و تأیید کنید، که این امر امنیت برنامه شما را افزایش می‌دهد. برای انجام این کار، این مراحل را دنبال کنید:

  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 به کلیدهای مختص زبان (در مورد ما زبان برنامه‌نویسی جاوا) در backend برنامه نشان می‌دهد. توجه داشته باشید که کلیدها با استفاده از پرچم‌های پیش‌فرض به صورت 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();

بار داده‌ی حاصل، یک توکن متنی ساده است که حاوی احکام یکپارچگی است.

رفع مشکلات مربوط به حکم با اعلان گوگل پلی (اختیاری)

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

API یکپارچگی بازی (Play Integrity API) گزینه‌ای را برای نمایش یک کادر محاوره‌ای گوگل پلی فراهم می‌کند که کاربر را به انجام کاری ترغیب می‌کند، برای مثال، دریافت نسخه رسمی برنامه شما از گوگل پلی.

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