क्लासिक एपीआई अनुरोध करें

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

ज़रूरी बातें

स्टैंडर्ड और क्लासिक अनुरोधों की तुलना करना

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

यहां दी गई टेबल में, दोनों तरह के अनुरोधों के बीच के मुख्य अंतर को हाइलाइट किया गया है:

स्टैंडर्ड एपीआई अनुरोध क्लासिक एपीआई अनुरोध
ज़रूरी शर्तें
Android SDK टूल का ज़रूरी वर्शन* Android 6.0 (एपीआई लेवल 23) या इसके बाद का वर्शन Android 6.0 (एपीआई लेवल 23) या इसके बाद का वर्शन
Google Play की ज़रूरी शर्तें Google Play Store और Google Play services Google Play Store और Google Play services
इंटिग्रेशन की जानकारी
एपीआई को वॉर्म अप करना ज़रूरी है ✔️ (कुछ सेकंड) ❌
अनुरोध के इंतज़ार का सामान्य समय कुछ सौ मिलीसेकंड कुछ सेकंड
संभावित अनुरोध की फ़्रीक्वेंसी बार-बार (किसी कार्रवाई या अनुरोध के लिए, मांग के हिसाब से जांच करना) कभी-कभी (सबसे ज़्यादा वैल्यू वाली कार्रवाइयों या सबसे संवेदनशील अनुरोधों के लिए, एक बार की जाने वाली जांच)
टाइम आउट की संख्या ज़्यादातर वॉर्म अप 10 सेकंड से कम समय में हो जाते हैं. हालांकि, इनमें सर्वर कॉल शामिल होता है. इसलिए, टाइम आउट की अवधि ज़्यादा रखने का सुझाव दिया जाता है. जैसे, एक मिनट. फ़ैसले के अनुरोध, क्लाइंट-साइड पर किए जाते हैं ज़्यादातर अनुरोध 10 सेकंड से कम समय में पूरे हो जाते हैं. हालांकि, इनमें सर्वर कॉल शामिल होता है. इसलिए, हमारा सुझाव है कि टाइम आउट की अवधि ज़्यादा रखें. उदाहरण के लिए, एक मिनट
पूरी सुरक्षा की जांच के नतीजे का टोकन
इसमें डिवाइस, ऐप्लिकेशन, और खाते की जानकारी शामिल होती है ✔️ ✔️
टोकन कैश मेमोरी में सेव करना Google Play की मदद से, उपयोगकर्ता के डिवाइस पर कैश मेमोरी को सुरक्षित रखना हम आपको इसका सुझाव नहीं देते हैं
Google Play सर्वर का इस्तेमाल करके, टोकन को डिक्रिप्ट करना और उसकी पुष्टि करना ✔️ ✔️
डिक्रिप्ट करने के लिए, एक सर्वर से दूसरे सर्वर को भेजे गए अनुरोध में लगने वाला सामान्य समय 99.9% उपलब्धता के साथ 10 मिलीसेकंड 99.9% उपलब्धता के साथ 10 मिलीसेकंड
सुरक्षित सर्वर एनवायरमेंट में, टोकन को लोकल तौर पर डिक्रिप्ट करना और उसकी पुष्टि करना ❌ ✔️
क्लाइंट-साइड पर टोकन को डिक्रिप्ट करना और उसकी पुष्टि करना ❌ ❌
पूरी सुरक्षा की जांच के नतीजे का अपडेट होना Google Play की ओर से, कुछ डेटा अपने-आप कैश मेमोरी में सेव होना और रीफ़्रेश होना हर अनुरोध पर, सभी फ़ैसलों का फिर से आकलन किया जाता है
सीमाएं
हर ऐप्लिकेशन के लिए, हर दिन के हिसाब से अनुरोध करना डिफ़ॉल्ट रूप से 10,000 (इस संख्या को बढ़ाने का अनुरोध किया जा सकता है) डिफ़ॉल्ट रूप से 10,000 (इस संख्या को बढ़ाने का अनुरोध किया जा सकता है)
हर मिनट, ऐप्लिकेशन के हर इंस्टेंस के लिए किए जाने वाले अनुरोध वॉर्म अप: हर मिनट पांच
इंटेग्रिटी टोकन: कोई सार्वजनिक सीमा तय नहीं है**
इंटेग्रिटी टोकन: हर मिनट में पांच
सुरक्षा के लिए
छेड़छाड़ और इसी तरह के हमलों से बचाव करना requestHash फ़ील्ड का इस्तेमाल करें अनुरोध के डेटा के आधार पर, कॉन्टेंट बाइंडिंग के साथ nonce फ़ील्ड का इस्तेमाल करें
रीप्ले और मिलते-जुलते हमलों से बचाव करना Google Play की ओर से जोखिम कम करने की प्रोसेस अपने-आप पूरी होना सर्वर साइड लॉजिक के साथ nonce फ़ील्ड का इस्तेमाल करना

* Play Integrity API लाइब्रेरी के v1.4.0 और इसके बाद के वर्शन के लिए, Android SDK का कम से कम वर्शन, दोनों तरह के अनुरोधों के लिए एक जैसा होता है. यह लाइब्रेरी के minSdkVersion से तय होता है. v1.3.0 और इससे पहले की रिलीज़ के लिए, स्टैंडर्ड एपीआई अनुरोधों के लिए Android SDK टूल का कम से कम वर्शन Android 5.0 (एपीआई लेवल 21) और क्लासिक एपीआई अनुरोधों के लिए Android 4.4 (एपीआई लेवल 19) होना चाहिए.

** सभी अनुरोधों पर, सुरक्षा के लिए तय की गई ऐसी सीमाएं लागू होती हैं जो सार्वजनिक नहीं की जाती हैं. इनमें वे अनुरोध भी शामिल हैं जिनके लिए सार्वजनिक तौर पर कोई सीमा तय नहीं की गई है.

क्लासिक अनुरोधों का इस्तेमाल कम करें

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

फ़ैसलों को कैश मेमोरी में सेव करने से बचना

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

क्लासिक अनुरोधों को सुरक्षित रखने के लिए, नॉन्स फ़ील्ड का इस्तेमाल करना

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 फ़ील्ड का इस्तेमाल करके, कुछ खास तरह के हमलों को कम किया जा सकता है. जैसे, पर्सन-इन-द-मिडल (पीआईटीएम) टैंपरिंग अटैक और रीप्ले अटैक. Play Integrity API, इस फ़ील्ड में सेट की गई वैल्यू को साइन किए गए इंटिग्रिटी रिस्पॉन्स में दिखाता है.

nonce फ़ील्ड में सेट की गई वैल्यू को सही तरीके से फ़ॉर्मैट किया जाना चाहिए:

  • String
  • यूआरएल के लिए सुरक्षित
  • Base64 और नॉन-रैपिंग के तौर पर कोड में बदला गया
  • कम से कम 16 वर्ण
  • ज़्यादा से ज़्यादा 500 वर्ण

Play Integrity API में nonce फ़ील्ड का इस्तेमाल करने के कुछ सामान्य तरीके यहां दिए गए हैं. nonce से सबसे बेहतर सुरक्षा पाने के लिए, नीचे दिए गए तरीकों को एक साथ इस्तेमाल किया जा सकता है.

छेड़छाड़ से बचने के लिए, अनुरोध हैश शामिल करें

क्लासिक एपीआई अनुरोध में nonce पैरामीटर का इस्तेमाल किया जा सकता है. यह स्टैंडर्ड एपीआई अनुरोध में requestHash पैरामीटर की तरह ही काम करता है. इससे अनुरोध के कॉन्टेंट को छेड़छाड़ से बचाया जा सकता है.

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

  1. उपयोगकर्ता की कार्रवाई या सर्वर के अनुरोध से, सभी ज़रूरी अनुरोध पैरामीटर (जैसे, स्टेबल अनुरोध सीरियलाइज़ेशन का SHA256) का डाइजेस्ट कंप्यूट करें.
  2. setNonce का इस्तेमाल करके, nonce फ़ील्ड को कैलकुलेट किए गए डाइजेस्ट की वैल्यू पर सेट करें.

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

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

रीप्ले अटैक से बचने के लिए यूनीक वैल्यू शामिल करें

नुकसान पहुंचाने वाले उपयोगकर्ताओं को Play Integrity API से मिले पिछले जवाबों का फिर से इस्तेमाल करने से रोकने के लिए, nonce फ़ील्ड का इस्तेमाल किया जा सकता है. इससे हर मैसेज की अलग से पहचान की जा सकती है.

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

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

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

  1. इंटिग्रिटी टोकन को डिकोड करें और उसकी पुष्टि करें. साथ ही, nonce फ़ील्ड से यूनीक वैल्यू पाएं.
  2. अगर पहले चरण की वैल्यू सर्वर पर जनरेट की गई थी, तो देखें कि मिली यूनीक वैल्यू, जनरेट की गई वैल्यू में से एक हो. साथ ही, यह भी देखें कि उसका इस्तेमाल पहली बार किया जा रहा हो. आपके सर्वर को जनरेट की गई वैल्यू का रिकॉर्ड, सही अवधि के लिए रखना होगा. अगर मिली हुई यूनीक वैल्यू का इस्तेमाल पहले ही किया जा चुका है या वह रिकॉर्ड में नहीं दिखती है, तो अनुरोध को अस्वीकार कर दें
  3. अगर यूनीक वैल्यू डिवाइस पर जनरेट की गई थी, तो देखें कि मिली हुई वैल्यू का इस्तेमाल पहली बार किया जा रहा है या नहीं. आपके सर्वर को पहले से देखी गई वैल्यू का रिकॉर्ड, सही समय तक रखना होगा. अगर मिली हुई यूनीक वैल्यू का इस्तेमाल पहले ही किया जा चुका है, तो अनुरोध को अस्वीकार कर दें.

छेड़छाड़ और रीप्ले अटैक से सुरक्षा देने वाली दोनों सुविधाओं को जोड़ना (सुझाया गया)

nonce फ़ील्ड का इस्तेमाल करके, छेड़छाड़ और रीप्ले अटैक, दोनों से एक साथ बचा जा सकता है. इसके लिए, ऊपर बताए गए तरीके से यूनीक वैल्यू जनरेट करें और उसे अपने अनुरोध में शामिल करें. इसके बाद, अनुरोध हैश की गणना करें. साथ ही, यह पक्का करें कि हैश के हिस्से के तौर पर यूनीक वैल्यू शामिल हो. दोनों तरीकों को मिलाकर लागू करने का तरीका यहां बताया गया है:

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

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

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

  1. अनुरोध से यूनीक वैल्यू पाना
  2. इंटेग्रिटी टोकन को डिकोड करें और उसकी पुष्टि करें. इसके बाद, nonce फ़ील्ड से डाइजेस्ट पाएं.
  3. छेड़छाड़ से बचाने के लिए, अनुरोध में हैश शामिल करें सेक्शन में बताए गए तरीके के मुताबिक, सर्वर साइड पर डाइजेस्ट को फिर से कैलकुलेट करें. साथ ही, देखें कि यह इंटिग्रिटी टोकन से मिले डाइजेस्ट से मेल खाता है या नहीं.
  4. रीप्ले अटैक से बचने के लिए यूनीक वैल्यू शामिल करें सेक्शन में बताए गए तरीके के मुताबिक, यूनीक वैल्यू की वैधता की जांच करें.

यहां दिए गए सीक्वेंस डायग्राम में, सर्वर-साइड nonce के साथ इन चरणों को दिखाया गया है:

दूसरी इमेज. सीक्वेंस डायग्राम, जिसमें छेड़छाड़ और रीप्ले अटैक, दोनों से बचने का तरीका बताया गया है.

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

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

  1. IntegrityManager बनाएं, जैसा कि इन उदाहरणों में दिखाया गया है.
  2. IntegrityTokenRequest बनाएं. इसके लिए, असोसिएटेड बिल्डर में setNonce() तरीके का इस्तेमाल करके, nonce दें. Google Play और एसडीके के अलावा, अन्य प्लैटफ़ॉर्म पर उपलब्ध कराए जाने वाले ऐप्लिकेशन को भी setCloudProjectNumber() तरीके का इस्तेमाल करके, अपने Google Cloud प्रोजेक्ट का नंबर बताना होगा. Google Play पर मौजूद ऐप्लिकेशन, Play Console में किसी Cloud प्रोजेक्ट से लिंक होते हैं. इसलिए, अनुरोध में Cloud प्रोजेक्ट नंबर सेट करने की ज़रूरत नहीं होती.
  3. requestIntegrityToken() को कॉल करने के लिए, मैनेजर का इस्तेमाल करें. साथ ही, IntegrityTokenRequest की जानकारी दें. चेतावनी: nonce वैल्यू, Google के सिस्टम को उसी तरह पास की जाती हैं जिस तरह वे मौजूद होती हैं. इसलिए, आपको nonce में व्यक्तिगत पहचान से जुड़ी जानकारी या अन्य संवेदनशील डेटा को सीधे तौर पर या किसी अन्य तरीके से शामिल नहीं करना चाहिए.

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

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 वेब टोकन (JWT) है, जो JSON वेब सिग्नेचर (JWS) का JSON वेब एन्क्रिप्शन (JWE) है. जेडब्ल्यूई और जेडब्ल्यूएस कॉम्पोनेंट को कॉम्पैक्ट सीरियलाइज़ेशन का इस्तेमाल करके दिखाया जाता है.

एन्क्रिप्ट (सुरक्षित) करने / साइन करने के एल्गोरिदम, JWT के अलग-अलग तरीकों के साथ काम करते हैं:

  • JWE, alg के लिए A256KW और enc के लिए A256GCM का इस्तेमाल करता है

  • जेडब्ल्यूएस, ES256 का इस्तेमाल करता है.

Google के सर्वर पर डिक्रिप्ट और पुष्टि करना (सुझाया गया)

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

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

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

लोकल डिवाइस पर डिक्रिप्ट और पुष्टि करना

अगर आपने जवाब को एन्क्रिप्ट करने की कुंजियों को मैनेज और डाउनलोड करने का विकल्प चुना है, तो आपके पास अपने सुरक्षित सर्वर के डिवाइस की सुरक्षा और स्थिति की जानकारी में, मिले टोकन को डिक्रिप्ट करने और उसकी पुष्टि करने का विकल्प होता है. IntegrityTokenResponse#token() का इस्तेमाल करके, वापस किया गया टोकन पाया जा सकता है.

यहां दिए गए उदाहरण में, 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));

इसके बाद, इन कुंजियों का इस्तेमाल करके, पहले इंटिग्रिटी टोकन (जेडब्ल्यूई पार्ट) को डिक्रिप्ट करें. इसके बाद, नेस्ट किए गए जेडब्ल्यूएस पार्ट की पुष्टि करें और उसे निकालें.

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

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

Google Play के प्रॉम्प्ट की मदद से, फ़ैसले से जुड़ी समस्याएं ठीक करना (ज़रूरी नहीं)

सर्वर को पूरी सुरक्षा जांच के बाद नतीजा मिलने पर, वह तय कर सकता है कि आगे कैसे बढ़ना है. अगर नतीजे से पता चलता है कि कोई समस्या है, जैसे कि ऐप्लिकेशन के पास लाइसेंस नहीं है, उसमें छेड़छाड़ की गई है या डिवाइस को हैक किया गया है, तो उपयोगकर्ताओं को समस्या को खुद ठीक करने का मौका दिया जा सकता है.

Play Integrity API, Google Play का एक डायलॉग बॉक्स दिखाने का विकल्प देता है. इसमें उपयोगकर्ता को कोई कार्रवाई करने के लिए कहा जाता है. उदाहरण के लिए, Google Play से आपके ऐप्लिकेशन का आधिकारिक वर्शन डाउनलोड करने के लिए कहा जाता है.

सर्वर के जवाब के आधार पर, अपने ऐप्लिकेशन से इन डायलॉग को ट्रिगर करने का तरीका जानने के लिए, समस्या हल करने वाले डायलॉग देखें.