स्टैंडर्ड एपीआई अनुरोध करें

इस पेज पर, इंटिग्रिटी से जुड़े फ़ैसले के लिए स्टैंडर्ड एपीआई अनुरोध करने के बारे में बताया गया है. ये अनुरोध, Android 5.0 (एपीआई लेवल 21) या इसके बाद के वर्शन पर काम करते हैं. जब भी आपका ऐप्लिकेशन किसी सर्वर को कॉल कर रहा हो, तो पूरी सुरक्षा की जांच के नतीजे के लिए स्टैंडर्ड एपीआई अनुरोध किया जा सकता है. इससे यह पता चलता है कि इंटरैक्शन सही है या नहीं.

खास जानकारी

सीक्वेंस डायग्राम, जिसमें Play Integrity API का हाई-लेवल डिज़ाइन दिखाया गया है

स्टैंडर्ड अनुरोध में दो हिस्से होते हैं:

  • इंटिग्रिटी टोकन उपलब्ध कराने वाली कंपनी को तैयार करना (सिर्फ़ एक बार): आपको इंटिग्रिटी टोकन उपलब्ध कराने वाली कंपनी को तैयार करने के लिए, इंटिग्रिटी एपीआई को कॉल करना होगा. ऐसा, इंटिग्रिटी का नतीजा पाने से पहले करना होगा. उदाहरण के लिए, ऐसा तब किया जा सकता है, जब आपका ऐप्लिकेशन लॉन्च हो या पूरी सुरक्षा के बारे में फ़ैसला लेने से पहले, बैकग्राउंड में.
  • इंटिग्रिटी टोकन का अनुरोध करना (मांग पर): जब भी आपका ऐप्लिकेशन किसी ऐसे सर्वर के लिए अनुरोध करता है जिसकी पुष्टि आपको करनी है, तो आपके पास इंटिग्रिटी टोकन का अनुरोध करने का विकल्प होता है. इसके बाद, आपको यह टोकन अपने ऐप्लिकेशन के बैकएंड सर्वर पर भेजना होता है, ताकि उसे डिक्रिप्ट किया जा सके और उसकी पुष्टि की जा सके. इसके बाद, आपका बैकएंड सर्वर यह तय कर सकता है कि क्या करना है.

इंटिग्रिटी टोकन उपलब्ध कराने वाली कंपनी को तैयार करना (सिर्फ़ एक बार):

  1. आपका ऐप्लिकेशन, आपके Google Cloud प्रोजेक्ट के नंबर के साथ इंटिग्रिटी टोकन देने वाली कंपनी को कॉल करता है.
  2. आपका ऐप्लिकेशन, पुष्टि करने के लिए आने वाले कॉल के लिए, इंटिग्रिटी टोकन उपलब्ध कराने वाली कंपनी को मेमोरी में सेव रखता है.

इंटिग्रिटी टोकन का अनुरोध करना (मांग पर):

  1. जिस उपयोगकर्ता कार्रवाई को सुरक्षित रखने की ज़रूरत है उसके लिए, आपका ऐप्लिकेशन किए जाने वाले अनुरोध का हैश कैलकुलेट करता है. इसके लिए, SHA256 जैसे किसी भी सही हैश एल्गोरिदम का इस्तेमाल किया जाता है.
  2. आपका ऐप्लिकेशन, अनुरोध हैश को पास करके इंटिग्रिटी टोकन का अनुरोध करता है.
  3. आपके ऐप्लिकेशन को Play Integrity API से, साइन किया गया और एन्क्रिप्ट किया गया इंटिग्रिटी टोकन मिलता है.
  4. आपका ऐप्लिकेशन, इंटिग्रिटी टोकन को अपने बैकएंड को भेजता है.
  5. आपके ऐप्लिकेशन का बैकएंड, टोकन को Google Play के सर्वर पर भेजता है. Google Play का सर्वर, नतीजे को डिक्रिप्ट करता है और उसकी पुष्टि करता है. इसके बाद, वह नतीजे आपके ऐप्लिकेशन के बैकएंड को भेजता है.
  6. टोकन पेलोड में मौजूद सिग्नल के आधार पर, आपके ऐप्लिकेशन का बैकएंड यह तय करता है कि आगे क्या करना है.
  7. आपके ऐप्लिकेशन का बैकएंड, फ़ैसले के नतीजे आपके ऐप्लिकेशन को भेजता है.

इंटिग्रिटी टोकन की सेवा देने वाली कंपनी को तैयार करना (सिर्फ़ एक बार)

Google Play से पूरी सुरक्षा देने की सुविधा के नतीजे का स्टैंडर्ड अनुरोध करने से पहले, आपको पूरी सुरक्षा देने वाला टोकन उपलब्ध कराने वाली कंपनी को तैयार करना होगा या "वॉर्म अप" करना होगा. इससे Google Play, डिवाइस पर पुष्टि की कुछ जानकारी को कैश मेमोरी में सेव कर सकता है. इससे, पुष्टि के नतीजे का अनुरोध करने पर, क्रिटिकल पाथ पर लगने वाले समय को कम किया जा सकता है. टोकन उपलब्ध कराने वाली कंपनी को फिर से तैयार करना, पूरी सुरक्षा की जांच को फिर से करने का एक तरीका है. इससे, पूरी सुरक्षा से जुड़ा अगला फ़ैसला ज़्यादा अप-टू-डेट होगा.

इंटिग्रिटी टोकन की सेवा देने वाली कंपनी को तैयार करने के लिए:

  • जब आपका ऐप्लिकेशन लॉन्च होता है (यानी कोल्ड स्टार्ट अप पर). टोकन प्रोवाइडर को तैयार करना, एसिंक्रोनस होता है. इसलिए, इससे स्टार्ट अप के समय पर कोई असर नहीं पड़ेगा. अगर आपको ऐप्लिकेशन लॉन्च होने के कुछ समय बाद ही सुरक्षा जांच के नतीजे का अनुरोध करना है, तो यह विकल्प आपके लिए बेहतर होगा. उदाहरण के लिए, जब कोई उपयोगकर्ता साइन इन करता है या कोई खिलाड़ी किसी गेम में शामिल होता है.
  • जब आपका ऐप्लिकेशन खोला जाता है (यानी वॉर्म स्टार्ट अप पर). हालांकि, ध्यान दें कि हर ऐप्लिकेशन इंस्टेंस, हर मिनट में सिर्फ़ पांच बार इंटिग्रिटी टोकन तैयार कर सकता है.
  • बैकग्राउंड में किसी भी समय, जब आपको पूरी सुरक्षा के लिए फ़ैसले के अनुरोध से पहले टोकन तैयार करना हो.

इंटिग्रिटी टोकन की सेवा देने वाली कंपनी को तैयार करने के लिए, यह तरीका अपनाएं:

  1. StandardIntegrityManager बनाएं, जैसा कि नीचे दिए गए उदाहरणों में दिखाया गया है.
  2. setCloudProjectNumber() तरीके से Google Cloud प्रोजेक्ट नंबर डालकर, PrepareIntegrityTokenRequest बनाएं.
  3. prepareIntegrityToken() को कॉल करने के लिए, मैनेजर का इस्तेमाल करें और PrepareIntegrityTokenRequest डालें.

Java

import com.google.android.gms.tasks.Task;

// Create an instance of a manager.
StandardIntegrityManager standardIntegrityManager =
    IntegrityManagerFactory.createStandard(applicationContext);

StandardIntegrityTokenProvider integrityTokenProvider;
long cloudProjectNumber = ...;

// Prepare integrity token. Can be called once in a while to keep internal
// state fresh.
standardIntegrityManager.prepareIntegrityToken(
    PrepareIntegrityTokenRequest.builder()
        .setCloudProjectNumber(cloudProjectNumber)
        .build())
    .addOnSuccessListener(tokenProvider -> {
        integrityTokenProvider = tokenProvider;
    })
    .addOnFailureListener(exception -> handleError(exception));

Unity

IEnumerator PrepareIntegrityTokenCoroutine() {
    long cloudProjectNumber = ...;

    // Create an instance of a standard integrity manager.
    var standardIntegrityManager = new StandardIntegrityManager();

    // Request the token provider.
    var integrityTokenProviderOperation =
      standardIntegrityManager.PrepareIntegrityToken(
        new PrepareIntegrityTokenRequest(cloudProjectNumber));

    // Wait for PlayAsyncOperation to complete.
    yield return integrityTokenProviderOperation;

    // Check the resulting error code.
    if (integrityTokenProviderOperation.Error != StandardIntegrityErrorCode.NoError)
    {
        AppendStatusLog("StandardIntegrityAsyncOperation failed with error: " +
                integrityTokenProviderOperation.Error);
        yield break;
    }

    // Get the response.
    var integrityTokenProvider = integrityTokenProviderOperation.GetResult();
}

मूल भाषा वाला

/// Initialize StandardIntegrityManager
StandardIntegrityManager_init(/* app's java vm */, /* an android context */);
/// Create a PrepareIntegrityTokenRequest opaque object.
int64_t cloudProjectNumber = ...;
PrepareIntegrityTokenRequest* tokenProviderRequest;
PrepareIntegrityTokenRequest_create(&tokenProviderRequest);
PrepareIntegrityTokenRequest_setCloudProjectNumber(tokenProviderRequest, cloudProjectNumber);

/// Prepare a StandardIntegrityTokenProvider opaque type pointer and call
/// StandardIntegrityManager_prepareIntegrityToken().
StandardIntegrityTokenProvider* tokenProvider;
StandardIntegrityErrorCode error_code =
        StandardIntegrityManager_prepareIntegrityToken(tokenProviderRequest, &tokenProvider);

/// ...
/// Proceed to polling iff error_code == STANDARD_INTEGRITY_NO_ERROR
if (error_code != STANDARD_INTEGRITY_NO_ERROR)
{
    /// Remember to call the *_destroy() functions.
    return;
}
/// ...
/// Use polling to wait for the async operation to complete.

IntegrityResponseStatus token_provider_status;

/// Check for error codes.
StandardIntegrityErrorCode error_code =
        StandardIntegrityTokenProvider_getStatus(tokenProvider, &token_provider_status);
if (error_code == STANDARD_INTEGRITY_NO_ERROR
    && token_provider_status == INTEGRITY_RESPONSE_COMPLETED)
{
    /// continue to request token from the token provider
}
/// ...
/// Remember to free up resources.
PrepareIntegrityTokenRequest_destroy(tokenProviderRequest);

अनुरोधों में छेड़छाड़ से बचाना (सुझाया गया)

Play Integrity API की मदद से, अपने ऐप्लिकेशन में उपयोगकर्ता की कार्रवाई की जांच करते समय, आपके पास requestHash फ़ील्ड का इस्तेमाल करके, डेटा में बदलाव करने से जुड़े हमलों को कम करने का विकल्प होता है. उदाहरण के लिए, हो सकता है कि कोई गेम, खिलाड़ी के स्कोर की जानकारी गेम के बैकएंड सर्वर को भेजना चाहे. साथ ही, आपका सर्वर यह पक्का करना चाहे कि किसी प्रॉक्सी सर्वर ने इस स्कोर में छेड़छाड़ न की हो. Play Integrity API, हस्ताक्षर किए गए इंटिग्रिटी रिस्पॉन्स में, requestHash फ़ील्ड में सेट की गई वैल्यू दिखाता है. requestHash के बिना, इंटिग्रिटी टोकन सिर्फ़ डिवाइस से जुड़ा होगा, न कि किसी खास अनुरोध से. इससे हमले की संभावना बढ़ जाती है. यहां दिए गए निर्देशों में, requestHash फ़ील्ड का असरदार तरीके से इस्तेमाल करने का तरीका बताया गया है:

पूरी सुरक्षा की जांच का नतीजा पाने का अनुरोध करने पर:

  • उपयोगकर्ता की कार्रवाई या सर्वर के अनुरोध से, सभी काम के अनुरोध पैरामीटर (जैसे, स्थिर अनुरोध के सीरियलाइज़ेशन का SHA256) का डाइजेस्ट कैलकुलेट करें. requestHash फ़ील्ड में सेट की गई वैल्यू की लंबाई ज़्यादा से ज़्यादा 500 बाइट हो सकती है. requestHash में, ऐप्लिकेशन के अनुरोध का वह डेटा शामिल करें जो जांची जा रही या सुरक्षित की जा रही कार्रवाई के लिए ज़रूरी या काम का हो. requestHash फ़ील्ड को इंटिग्रिटी टोकन में हूबहू शामिल किया जाता है. इसलिए, लंबी वैल्यू से अनुरोध का साइज़ बढ़ सकता है.
  • Play Integrity API को डाइजेस्ट को requestHash फ़ील्ड के तौर पर दें और इंटिग्रिटी टोकन पाएं.

पूरी सुरक्षा की जांच का नतीजा मिलने पर:

  • इंटिग्रिटी टोकन को डिकोड करें और requestHash फ़ील्ड को निकालें.
  • अनुरोध के डाइजेस्ट को उसी तरह से कैलकुलेट करें जिस तरह से ऐप्लिकेशन में किया जाता है. उदाहरण के लिए, स्थिर अनुरोध के सीरियलाइज़ेशन का SHA256.
  • ऐप्लिकेशन-साइड और सर्वर-साइड डाइजेस्ट की तुलना करें. अगर वे मेल नहीं खाते हैं, तो इसका मतलब है कि अनुरोध भरोसेमंद नहीं है.

पूरी सुरक्षा की जांच का नतीजा पाने का अनुरोध करना (मांग पर)

इंटिग्रिटी टोकन प्रोवाइडर तैयार करने के बाद, Google Play से इंटिग्रिटी से जुड़े नतीजों का अनुरोध किया जा सकता है. ऐसा करने के लिए, यह तरीका अपनाएं:

  1. ऊपर दिखाए गए तरीके से StandardIntegrityTokenProvider पाएं.
  2. StandardIntegrityTokenRequest बनाएं. इसके लिए, setRequestHash तरीके से उस उपयोगकर्ता कार्रवाई का अनुरोध हैश दें जिसे आपको सुरक्षित रखना है.
  3. request() को कॉल करने के लिए, इंटिग्रिटी टोकन उपलब्ध कराने वाली कंपनी का इस्तेमाल करें. इसके लिए, StandardIntegrityTokenRequest की वैल्यू दें.

Java

import com.google.android.gms.tasks.Task;

StandardIntegrityTokenProvider integrityTokenProvider;

// See above how to prepare integrityTokenProvider.

// Request integrity token by providing a user action request hash. Can be called
// several times for different user actions.
String requestHash = "2cp24z...";
Task<StandardIntegrityToken> integrityTokenResponse =
    integrityTokenProvider.request(
        StandardIntegrityTokenRequest.builder()
            .setRequestHash(requestHash)
            .build());
integrityTokenResponse
    .addOnSuccessListener(response -> sendToServer(response.token()))
    .addOnFailureListener(exception -> handleError(exception));

Unity

IEnumerator RequestIntegrityTokenCoroutine() {
    StandardIntegrityTokenProvider integrityTokenProvider;

    // See above how to prepare integrityTokenProvider.

    // Request integrity token by providing a user action request hash. Can be called
    // several times for different user actions.
    String requestHash = "2cp24z...";
    var integrityTokenOperation = integrityTokenProvider.Request(
      new StandardIntegrityTokenRequest(requestHash)
    );

    // Wait for PlayAsyncOperation to complete.
    yield return integrityTokenOperation;

    // Check the resulting error code.
    if (integrityTokenOperation.Error != StandardIntegrityErrorCode.NoError)
    {
        AppendStatusLog("StandardIntegrityAsyncOperation failed with error: " +
                integrityTokenOperation.Error);
        yield break;
    }

    // Get the response.
    var integrityToken = integrityTokenOperation.GetResult();
}

मूल भाषा वाला

/// Create a StandardIntegrityTokenRequest opaque object.
const char* requestHash = ...;
StandardIntegrityTokenRequest* tokenRequest;
StandardIntegrityTokenRequest_create(&tokenRequest);
StandardIntegrityTokenRequest_setRequestHash(tokenRequest, requestHash);

/// Prepare a StandardIntegrityToken opaque type pointer and call
/// StandardIntegrityTokenProvider_request(). Can be called several times for
/// different user actions. See above how to prepare token provider.
StandardIntegrityToken* token;
StandardIntegrityErrorCode error_code =
        StandardIntegrityTokenProvider_request(tokenProvider, tokenRequest, &token);

/// ...
/// Proceed to polling iff error_code == STANDARD_INTEGRITY_NO_ERROR
if (error_code != STANDARD_INTEGRITY_NO_ERROR)
{
    /// Remember to call the *_destroy() functions.
    return;
}
/// ...
/// Use polling to wait for the async operation to complete.

IntegrityResponseStatus token_status;

/// Check for error codes.
StandardIntegrityErrorCode error_code =
        StandardIntegrityToken_getStatus(token, &token_status);
if (error_code == STANDARD_INTEGRITY_NO_ERROR
    && token_status == INTEGRITY_RESPONSE_COMPLETED)
{
    const char* integrityToken = StandardIntegrityToken_getToken(token);
}
/// ...
/// Remember to free up resources.
StandardIntegrityTokenRequest_destroy(tokenRequest);
StandardIntegrityToken_destroy(token);
StandardIntegrityTokenProvider_destroy(tokenProvider);
StandardIntegrityManager_destroy();

पूरी सुरक्षा की जांच के नतीजे को डिक्रिप्ट करना और उसकी पुष्टि करना

पूरी सुरक्षा की जांच के नतीजे का अनुरोध करने के बाद, Play Integrity API एन्क्रिप्ट (सुरक्षित) किया गया रिस्पॉन्स टोकन उपलब्ध कराता है. डिवाइस इंटिग्रिटी के नतीजे पाने के लिए, आपको Google के सर्वर पर इंटिग्रिटी टोकन को डिक्रिप्ट करना होगा. ऐसा करने के लिए, यह तरीका अपनाएं:

  1. अपने ऐप्लिकेशन से लिंक किए गए Google Cloud प्रोजेक्ट में, सेवा खाता बनाएं.
  2. अपने ऐप्लिकेशन के सर्वर पर, playintegrity दायरे का इस्तेमाल करके अपने सेवा खाते के क्रेडेंशियल से ऐक्सेस टोकन फ़ेच करें. इसके बाद, यह अनुरोध करें:

    playintegrity.googleapis.com/v1/PACKAGE_NAME:decodeIntegrityToken -d \
    '{ "integrity_token": "INTEGRITY_TOKEN" }'
  3. JSON रिस्पॉन्स पढ़ें.

इससे मिलने वाला पेलोड, एक सादा टेक्स्ट टोकन होता है. इसमें इंटिग्रिटी के फ़ैसले शामिल होते हैं.

ऑटोमैटिक रीप्ले प्रोटेक्शन

रीप्ले अटैक को कम करने के लिए, Google Play अपने-आप यह पक्का करता है कि हर इंटिग्रिटी टोकन का कई बार इस्तेमाल न किया जा सके. एक ही टोकन को बार-बार डिक्रिप्ट करने की कोशिश करने पर, 'सही' के नतीजे मिलेंगे. फिर से चलाए जाने से सुरक्षित किए गए टोकन के लिए, डिकोड किए गए नतीजे इस तरह दिखाए जाते हैं:

  • डिवाइस की पहचान करने से जुड़ा फ़ैसला खाली होगा.
  • ऐप्लिकेशन की पहचान की पुष्टि के नतीजे और ऐप्लिकेशन के लिए लाइसेंस के नतीजे को UNEVALUATED पर सेट किया जाएगा.
  • Play Console का इस्तेमाल करके चालू किए गए वैकल्पिक नतीजों को UNEVALUATED पर सेट किया जाएगा. अगर नतीजा कई वैल्यू वाला है, तो उसे खाली पर सेट किया जाएगा.