अगर आपको सिर्फ़ स्टैंडर्ड एपीआई अनुरोध करने हैं, जो ज़्यादातर डेवलपर के लिए सही हैं, तो इंटिग्रिटी से जुड़े फ़ैसले पर जाएं. इस पेज पर, इंटिग्रिटी से जुड़े फ़ैसले के लिए क्लासिक एपीआई अनुरोध करने के बारे में बताया गया है. ये अनुरोध, Android 4.4 (एपीआई लेवल 19) या इसके बाद के वर्शन पर काम करते हैं.
ज़रूरी बातें
स्टैंडर्ड और क्लासिक अनुरोधों की तुलना करना
आपके पास स्टैंडर्ड अनुरोध, क्लासिक अनुरोध या दोनों का कॉम्बिनेशन करने का विकल्प होता है. यह इस बात पर निर्भर करता है कि आपके ऐप्लिकेशन की सुरक्षा और गलत इस्तेमाल को रोकने के लिए क्या ज़रूरी है. स्टैंडर्ड अनुरोध, सभी ऐप्लिकेशन और गेम के लिए सही होते हैं. इनका इस्तेमाल यह जांचने के लिए किया जा सकता है कि कोई भी कार्रवाई या सर्वर कॉल सही है या नहीं. साथ ही, Google Play को फिर से चलाए जाने और डेटा निकालने से जुड़ी कुछ सुरक्षा भी दी जा सकती है. क्लासिक अनुरोधों को लागू करने की लागत ज़्यादा होती है. साथ ही, डेटा को बाहर ले जाने और कुछ तरह के हमलों से बचाने के लिए, उन्हें सही तरीके से लागू करने की ज़िम्मेदारी आपकी होती है. स्टैंडर्ड अनुरोधों की तुलना में, क्लासिक अनुरोध कम बार किए जाने चाहिए. उदाहरण के लिए, कभी-कभी एक बार यह जांच करने के लिए कि कोई अहम या संवेदनशील कार्रवाई सही है या नहीं.
नीचे दी गई टेबल में, दोनों तरह के अनुरोधों के बीच के मुख्य अंतर हाइलाइट किए गए हैं:
स्टैंडर्ड एपीआई अनुरोध | क्लासिक एपीआई अनुरोध | |
---|---|---|
ज़रूरी शर्तें | ||
Android SDK टूल का ज़रूरी वर्शन | Android 5.0 (एपीआई लेवल 21) या इसके बाद का वर्शन | Android 4.4 (एपीआई लेवल 19) या इसके बाद का वर्शन |
Google Play की ज़रूरी शर्तें | Google Play Store और Google Play services | Google Play Store और Google Play services |
इंटिग्रेशन की जानकारी | ||
एपीआई को वॉर्म अप करना ज़रूरी है | ✔️ (कुछ सेकंड) | ❌ |
अनुरोध के लिए आम तौर पर लगने वाला समय | कुछ सौ मिलीसेकंड | कुछ सेकंड |
अनुरोध की संभावित फ़्रीक्वेंसी | बार-बार (किसी भी कार्रवाई या अनुरोध के लिए, मांग पर जांच) | कम बार (ज़्यादा अहमियत वाली कार्रवाइयों या सबसे संवेदनशील अनुरोधों के लिए एक बार की जाने वाली जांच) |
टाइम आउट की संख्या | ज़्यादातर वार्म अप 10 सेकंड से कम के होते हैं, लेकिन इनमें सर्वर कॉल शामिल होता है. इसलिए, लंबे टाइम आउट (जैसे, एक मिनट) का सुझाव दिया जाता है. नतीजे के अनुरोध, क्लाइंट-साइड पर किए जाते हैं | ज़्यादातर अनुरोध 10 सेकंड से कम समय में पूरे हो जाते हैं.हालांकि, इनमें सर्वर कॉल शामिल होता है. इसलिए, लंबा टाइम आउट (जैसे, एक मिनट) सेट करने का सुझाव दिया जाता है |
पूरी सुरक्षा की जांच का नतीजा बताने वाला टोकन | ||
इसमें डिवाइस, ऐप्लिकेशन, और खाते की जानकारी शामिल होती है | ✔️ | ✔️ |
टोकन कैश मेमोरी में सेव करना | Google Play की मदद से, डिवाइस पर सुरक्षित तरीके से कैश मेमोरी में सेव करना | हम आपको इसका सुझाव नहीं देते हैं |
Google Play सर्वर की मदद से, टोकन को डिक्रिप्ट करना और उसकी पुष्टि करना | ✔️ | ✔️ |
डिक्रिप्ट करने के लिए, सर्वर-टू-सर्वर अनुरोध में लगने वाला सामान्य समय | 99.99% उपलब्धता के साथ 10 सेकंड के मिलीसेकंड | 99.99% उपलब्धता के साथ 10 सेकंड के मिलीसेकंड |
सुरक्षित सर्वर एनवायरमेंट में, स्थानीय तौर पर टोकन को डिक्रिप्ट करना और उसकी पुष्टि करना | ❌ | ✔️ |
क्लाइंट-साइड पर टोकन को डिक्रिप्ट करना और उसकी पुष्टि करना | ❌ | ❌ |
पूरी सुरक्षा की जांच के नतीजे के अपडेट होने की फ़्रीक्वेंसी | Google Play की ओर से कुछ जानकारी अपने-आप कैश मेमोरी में सेव होना और रीफ़्रेश होना | हर अनुरोध पर सभी नतीजों का फिर से हिसाब लगाया जाता है |
सीमाएं | ||
हर ऐप्लिकेशन के लिए हर दिन किए जाने वाले अनुरोध | डिफ़ॉल्ट रूप से 10,000 (इसकी संख्या बढ़ाने का अनुरोध किया जा सकता है) | डिफ़ॉल्ट रूप से 10,000 (इसकी संख्या बढ़ाने का अनुरोध किया जा सकता है) |
हर ऐप्लिकेशन इंस्टेंस के लिए हर मिनट के हिसाब से अनुरोध | वार्म अप: हर मिनट में पांच इंटिग्रिटी टोकन: सार्वजनिक तौर पर कोई सीमा नहीं* |
इंटिग्रिटी टोकन: हर मिनट पांच |
सुरक्षा | ||
डेटा में छेड़छाड़ और मिलते-जुलते हमलों से बचना | requestHash फ़ील्ड का इस्तेमाल करना |
अनुरोध के डेटा के आधार पर, कॉन्टेंट बाइंडिंग के साथ nonce फ़ील्ड का इस्तेमाल करना |
रिप्ले और मिलते-जुलते हमलों को कम करना | Google Play की ओर से, समस्या को अपने-आप कम करना | सर्वर साइड लॉजिक के साथ nonce फ़ील्ड का इस्तेमाल करना |
* सभी अनुरोधों पर, ज़्यादा वैल्यू के लिए, ज़रूरी सुरक्षा से जुड़ी ऐसी सीमाएं लागू होती हैं जो सार्वजनिक नहीं होतीं. इनमें वे अनुरोध भी शामिल हैं जिन पर सार्वजनिक सीमाएं लागू नहीं होतीं
क्लासिक अनुरोध कम ही किए जाते हैं
इंटिग्रिटी टोकन जनरेट करने में समय, डेटा, और बैटरी का इस्तेमाल होता है. साथ ही, हर ऐप्लिकेशन के लिए, हर दिन किए जा सकने वाले क्लासिक अनुरोधों की संख्या तय होती है. इसलिए, आपको सिर्फ़ तब क्लासिक अनुरोध करने चाहिए, जब आपको किसी स्टैंडर्ड अनुरोध के लिए अतिरिक्त गारंटी चाहिए. इससे, आपको यह पता चलेगा कि सबसे ज़्यादा वैल्यू वाली या सबसे संवेदनशील कार्रवाइयां सही हैं या नहीं. आपको ज़्यादा फ़्रीक्वेंसी या कम वैल्यू वाले ऐक्शन के लिए, क्लासिक अनुरोध नहीं करने चाहिए. ऐप्लिकेशन के फ़ोरग्राउंड में आने या बैकग्राउंड में हर कुछ मिनट में, क्लासिक अनुरोध न करें. साथ ही, एक ही समय पर कई डिवाइसों से कॉल करने से बचें. अगर कोई ऐप्लिकेशन बहुत ज़्यादा क्लासिक अनुरोध कॉल करता है, तो उपयोगकर्ताओं को गलत तरीके से लागू होने से बचाने के लिए, ऐप्लिकेशन को सीमित किया जा सकता है.
नतीजों को कैश मेमोरी में सेव करने से बचना
नतीजे को कैश मेमोरी में सेव करने से, डेटा निकालने और फिर से चलाने जैसे हमलों का खतरा बढ़ जाता है. ऐसा तब होता है, जब किसी भरोसेमंद प्लैटफ़ॉर्म से अच्छे नतीजे का फिर से इस्तेमाल किया जाता है. अगर आपको क्लासिक अनुरोध करने के बाद, उसे बाद में इस्तेमाल करने के लिए कैश मेमोरी में सेव करना है, तो हमारा सुझाव है कि आप मांग पर स्टैंडर्ड अनुरोध करें. स्टैंडर्ड अनुरोधों के लिए, डिवाइस पर कुछ कैश मेमोरी का इस्तेमाल किया जाता है. हालांकि, Google Play, रीप्ले अटैक और डेटा निकालने के खतरे को कम करने के लिए, सुरक्षा से जुड़ी अन्य तकनीकों का इस्तेमाल करता है.
क्लासिक अनुरोधों को सुरक्षित रखने के लिए, नॉन्स फ़ील्ड का इस्तेमाल करना
Play Integrity API में nonce
नाम का एक फ़ील्ड होता है. इसका इस्तेमाल, अपने ऐप्लिकेशन को कुछ खास हमलों से बचाने के लिए किया जा सकता है. जैसे, फिर से चलाने और डेटा में बदलाव करने से जुड़े हमले. Play Integrity API, इस फ़ील्ड में सेट की गई वैल्यू को, हस्ताक्षर किए गए इंटिग्रिटी रिस्पॉन्स में दिखाता है. अपने ऐप्लिकेशन को हमलों से सुरक्षित रखने के लिए, नॉन्स जनरेट करने का तरीका ध्यान से अपनाएं.
एक्सपोनेंशियल बैकऑफ़ के साथ क्लासिक अनुरोधों को फिर से भेजना
डिवाइस को पूरी सुरक्षा देने की जांच पूरी न होने की कई वजहें हो सकती हैं. जैसे, इंटरनेट कनेक्शन का अस्थिर होना या डिवाइस पर बहुत ज़्यादा ऐप्लिकेशन इंस्टॉल होना. इस वजह से, भरोसेमंद डिवाइस के लिए कोई लेबल जनरेट नहीं किया जा सकता. इन स्थितियों को कम करने के लिए, एक्सपोनेंशियल बैकऑफ़ के साथ फिर से कोशिश करने का विकल्प शामिल करें.
खास जानकारी
जब उपयोगकर्ता आपके ऐप्लिकेशन में कोई ऐसी अहम कार्रवाई करता है जिसे आपको इंटिग्रिटी जांच की मदद से सुरक्षित रखना है, तो यह तरीका अपनाएं:
- आपके ऐप्लिकेशन का सर्वर-साइड बैकएंड, क्लाइंट-साइड लॉजिक के लिए एक यूनीक वैल्यू जनरेट करता है और उसे भेजता है. बाकी चरणों में, इस लॉजिक को आपके "ऐप्लिकेशन" के तौर पर दिखाया गया है.
- आपका ऐप्लिकेशन, यूनीक वैल्यू और ज़्यादा अहमियत वाली कार्रवाई के कॉन्टेंट से
nonce
बनाता है. इसके बाद, यहnonce
को पास करके, Play Integrity API को कॉल करता है. - आपके ऐप्लिकेशन को Play Integrity API से, हस्ताक्षर किया गया और एन्क्रिप्ट किया गया नतीजा मिलता है.
- आपका ऐप्लिकेशन, हस्ताक्षर किए गए और एन्क्रिप्ट किए गए नतीजे को अपने बैकएंड को भेजता है.
- आपके ऐप्लिकेशन का बैकएंड, Google Play के सर्वर को नतीजा भेजता है. Google Play का सर्वर, नतीजे को डिक्रिप्ट करता है और उसकी पुष्टि करता है. इसके बाद, वह नतीजे आपके ऐप्लिकेशन के बैकएंड को भेजता है.
- टोकन पेलोड में मौजूद सिग्नल के आधार पर, आपके ऐप्लिकेशन का बैकएंड यह तय करता है कि आगे क्या करना है.
- आपके ऐप्लिकेशन का बैकएंड, फ़ैसले के नतीजे आपके ऐप्लिकेशन को भेजता है.
नॉन्स जनरेट करना
Play Integrity API की मदद से, अपने ऐप्लिकेशन में किसी कार्रवाई को सुरक्षित करने पर, nonce
फ़ील्ड का इस्तेमाल करके कुछ तरह के हमलों को कम किया जा सकता है. जैसे, बीच में घुसकर बदलाव करने वाले (पीआईटीएम) हमले और फिर से चलाए जाने वाले हमले. Play Integrity API, इस फ़ील्ड में सेट की गई वैल्यू को, हस्ताक्षर किए गए इंटिग्रिटी रिस्पॉन्स में दिखाता है.
nonce
फ़ील्ड में सेट की गई वैल्यू का फ़ॉर्मैट सही होना चाहिए:
String
- यूआरएल-सेफ़
- Base64 कोड में बदला गया और बिना रैप किए
- कम से कम 16 वर्ण
- ज़्यादा से ज़्यादा 500 वर्ण
Play Integrity API में nonce
फ़ील्ड का इस्तेमाल करने के कुछ सामान्य तरीके यहां दिए गए हैं. nonce
से सबसे ज़्यादा सुरक्षा पाने के लिए, यहां दिए गए तरीकों को एक साथ आज़माएं.
छेड़छाड़ से बचाने के लिए, अनुरोध हैश शामिल करें
क्लासिक एपीआई अनुरोध में nonce
पैरामीटर का इस्तेमाल उसी तरह किया जा सकता है जिस तरह स्टैंडर्ड एपीआई अनुरोध में requestHash
पैरामीटर का इस्तेमाल किया जाता है. इससे अनुरोध के कॉन्टेंट को बदले जाने से बचाया जा सकता है.
पूरी सुरक्षा की जांच का नतीजा पाने का अनुरोध करने पर:
- उपयोगकर्ता की कार्रवाई या सर्वर के अनुरोध से, सभी ज़रूरी अनुरोध पैरामीटर (जैसे, स्थिर अनुरोध के सीरियलाइज़ेशन का SHA256) का डाइजेस्ट कैलकुलेट करें.
nonce
फ़ील्ड को कैलकुलेट किए गए डाइजेस्ट की वैल्यू पर सेट करने के लिए,setNonce
का इस्तेमाल करें.
पूरी सुरक्षा की जांच का नतीजा मिलने पर:
- इंटिग्रिटी टोकन को डिकोड और पुष्टि करें. साथ ही,
nonce
फ़ील्ड से डाइजेस्ट पाएं. - अनुरोध के डाइजेस्ट को उसी तरह से कैलकुलेट करें जिस तरह से ऐप्लिकेशन में किया जाता है. उदाहरण के लिए, स्थिर अनुरोध के सीरियलाइज़ेशन का SHA256.
- ऐप्लिकेशन-साइड और सर्वर-साइड डाइजेस्ट की तुलना करें. अगर वे मेल नहीं खाते हैं, तो इसका मतलब है कि अनुरोध भरोसेमंद नहीं है.
रीप्ले हमलों से बचाने के लिए यूनीक वैल्यू शामिल करना
नुकसान पहुंचाने वाले उपयोगकर्ताओं को, Play Integrity API से मिले पिछले जवाबों का फिर से इस्तेमाल करने से रोकने के लिए, हर मैसेज की खास पहचान करने के लिए nonce
फ़ील्ड का इस्तेमाल किया जा सकता है.
पूरी सुरक्षा की जांच का नतीजा पाने का अनुरोध करने पर:
- दुनिया भर में यूनीक वैल्यू इस तरह से पाएं कि नुकसान पहुंचाने वाले उपयोगकर्ता उसका अनुमान न लगा पाएं. उदाहरण के लिए, सर्वर साइड पर क्रिप्टोग्राफ़िक तरीके से सुरक्षित किया गया कोई रैंडम नंबर या पहले से मौजूद आईडी, जैसे कि सेशन या ट्रांज़ैक्शन आईडी, ऐसी वैल्यू हो सकता है. डिवाइस पर कोई रैंडम नंबर जनरेट करना, आसान और कम सुरक्षित तरीका है. हमारा सुझाव है कि आप 128 बिट या इससे बड़ी वैल्यू बनाएं.
nonce
फ़ील्ड को पहले चरण में मिली यूनीक वैल्यू पर सेट करने के लिए,setNonce()
को कॉल करें.
पूरी सुरक्षा की जांच का नतीजा मिलने पर:
- इंटिग्रिटी टोकन को डिकोड और पुष्टि करें. साथ ही,
nonce
फ़ील्ड से यूनीक वैल्यू पाएं. - अगर पहले चरण में मिली वैल्यू, सर्वर पर जनरेट की गई थी, तो देखें कि मिली यूनीक वैल्यू, जनरेट की गई वैल्यू में से एक है या नहीं. साथ ही, यह भी देखें कि उसका इस्तेमाल पहली बार किया जा रहा है या नहीं. इसके लिए, आपके सर्वर को जनरेट की गई वैल्यू का रिकॉर्ड, तय समय तक रखना होगा. अगर मिली यूनीक वैल्यू का इस्तेमाल पहले ही किया जा चुका है या वह रिकॉर्ड में नहीं दिखती है, तो अनुरोध अस्वीकार करें
- अगर यूनीक वैल्यू डिवाइस पर जनरेट की गई थी, तो देखें कि मिली वैल्यू का इस्तेमाल पहली बार किया जा रहा है या नहीं. इसके लिए, आपके सर्वर को पहले से देखी गई वैल्यू का रिकॉर्ड, तय समय तक रखना होगा. अगर मिली यूनीक वैल्यू का इस्तेमाल पहले ही किया जा चुका है, तो अनुरोध अस्वीकार करें.
बदलाव करने और फिर से चलाने से जुड़े हमलों से सुरक्षा के लिए, दोनों सुरक्षा मोड का इस्तेमाल करें (सुझाया गया)
nonce
फ़ील्ड का इस्तेमाल करके, एक ही समय पर डेटा में बदलाव करने और फिर से चलाए जाने वाले हमलों, दोनों से सुरक्षा मिल सकती है. ऐसा करने के लिए, ऊपर बताए गए तरीके से यूनीक वैल्यू जनरेट करें और उसे अपने अनुरोध में शामिल करें. इसके बाद, अनुरोध हैश का हिसाब लगाएं. पक्का करें कि हैश के हिस्से के तौर पर यूनीक वैल्यू शामिल की गई हो. दोनों तरीकों को मिलाकर लागू करने का तरीका यहां बताया गया है:
पूरी सुरक्षा की जांच का नतीजा पाने का अनुरोध करने पर:
- उपयोगकर्ता, ज़्यादा वैल्यू वाली कार्रवाई शुरू करता है.
- रीप्ले अटैक से बचाने के लिए यूनीक वैल्यू शामिल करें सेक्शन में बताए गए तरीके से, इस कार्रवाई के लिए यूनीक वैल्यू पाएं.
- वह मैसेज तैयार करें जिसे आपको सुरक्षित रखना है. मैसेज में, दूसरे चरण की यूनीक वैल्यू शामिल करें.
- आपका ऐप्लिकेशन, उस मैसेज का डाइजेस्ट कैलकुलेट करता है जिसे उसे सुरक्षित रखना है. इस बारे में मैसेज में बदलाव किए जाने से बचाने के लिए, अनुरोध हैश शामिल करें सेक्शन में बताया गया है. मैसेज में यूनीक वैल्यू शामिल होने की वजह से, वह हैश का हिस्सा बन जाती है.
nonce
फ़ील्ड को पिछले चरण में कैलकुलेट किए गए डाइजेस्ट पर सेट करने के लिए,setNonce()
का इस्तेमाल करें.
पूरी सुरक्षा की जांच का नतीजा मिलने पर:
- अनुरोध से यूनीक वैल्यू पाना
- इंटिग्रिटी टोकन को डिकोड और पुष्टि करें. साथ ही,
nonce
फ़ील्ड से डाइजेस्ट पाएं. - बदलाव किए जाने से बचाने के लिए अनुरोध हैश शामिल करें सेक्शन में बताए गए तरीके के मुताबिक, सर्वर साइड पर डाइजेस्ट को फिर से कैलकुलेट करें. साथ ही, यह देखें कि यह इंटिग्रिटी टोकन से मिले डाइजेस्ट से मेल खाता है या नहीं.
- रीप्ले अटैक से बचाने के लिए यूनीक वैल्यू शामिल करें सेक्शन में बताए गए तरीके से, यूनीक वैल्यू की पुष्टि करें.
नीचे दिए गए क्रम वाले डायग्राम में, सर्वर-साइड nonce
के साथ इन चरणों को दिखाया गया है:
पूरी सुरक्षा की जांच का नतीजा पाने का अनुरोध करना
nonce
जनरेट करने के बाद, Google Play से इंटिग्रिटी से जुड़े नतीजे का अनुरोध किया जा सकता है. ऐसा करने के लिए, यह तरीका अपनाएं:
- नीचे दिए गए उदाहरणों में दिखाए गए तरीके से
IntegrityManager
बनाएं. IntegrityTokenRequest
बनाएं. इसके लिए, उससे जुड़े बिल्डर मेंsetNonce()
तरीके सेnonce
दें. Google Play और SDK टूल के अलावा, सिर्फ़ किसी अन्य प्लैटफ़ॉर्म पर उपलब्ध कराए जाने वाले ऐप्लिकेशन को भीsetCloudProjectNumber()
तरीके से अपना Google Cloud प्रोजेक्ट नंबर बताना होगा. Google Play पर मौजूद ऐप्लिकेशन, Play Console में किसी Cloud प्रोजेक्ट से लिंक होते हैं. इसलिए, अनुरोध में क्लाउड प्रोजेक्ट नंबर सेट करने की ज़रूरत नहीं होती.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());
Unity
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(); }
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) है. JWE और JWS कॉम्पोनेंट को कॉम्पैक्ट सिरीलाइज़ेशन का इस्तेमाल करके दिखाया जाता है .
एन्क्रिप्ट (सुरक्षित) करने / हस्ताक्षर करने वाले एल्गोरिदम, JWT के अलग-अलग लागू करने के तरीकों के साथ अच्छी तरह से काम करते हैं:
Google के सर्वर पर डिक्रिप्ट करना और पुष्टि करना (इसका सुझाव दिया जाता है)
Play Integrity API की मदद से, Google के सर्वर पर इंटिग्रिटी की जांच के नतीजे को डिक्रिप्ट और पुष्टि की जा सकती है. इससे आपके ऐप्लिकेशन की सुरक्षा बेहतर होती है. ऐसा करने के लिए, यह तरीका अपनाएं:
- अपने ऐप्लिकेशन से लिंक किए गए Google Cloud प्रोजेक्ट में, सेवा खाता बनाएं.
अपने ऐप्लिकेशन के सर्वर पर,
playintegrity
स्कोप का इस्तेमाल करके अपने सेवा खाते के क्रेडेंशियल से ऐक्सेस टोकन फ़ेच करें. इसके बाद, यह अनुरोध करें:playintegrity.googleapis.com/v1/PACKAGE_NAME:decodeIntegrityToken -d \ '{ "integrity_token": "INTEGRITY_TOKEN" }'
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));
इसके बाद, इन कुंजियों का इस्तेमाल करके पहले इंटिग्रिटी टोकन (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();
इससे मिलने वाला पेलोड, एक सादा टेक्स्ट टोकन होता है. इसमें इंटिग्रिटी के फ़ैसले शामिल होते हैं.