टोकन, की और PII के लिए Kotlin सुरक्षित स्टोरेज चेकलिस्ट
Kotlin के लिए सुरक्षित स्टोरेज चेकलिस्ट — Android Keystore, EncryptedSharedPreferences और डेटाबेस एन्क्रिप्शन में से कैसे चुनें ताकि टोकन, की और व्यक्तिगत जानकारी सुरक्षा में रहें।

आप क्या सुरक्षित करने की कोशिश कर रहे हैं (साधारण भाषा में)
एक बिज़नेस ऐप में सुरक्षित स्टोरेज का मतलब एक चीज़: अगर कोई फोन (या आपके ऐप की फाइलें) हासिल कर लेता है, तब भी उसे जो आपने सेव किया है पढ़ने या फिर से उपयोग करने में सक्षम नहीं होना चाहिए। इसमें डिस्क पर डेटा (at rest) और साथ ही बैकअप, लॉग्स, क्रैश रिपोर्ट, या डिबग टूल के माध्यम से सीक्रेट्स का लीक होना भी शामिल है।
एक सरल मानसिक टेस्ट: अगर कोई अजनबी आपका ऐप का स्टोरेज फ़ोल्डर खोल दे तो वह क्या कर सकता है? कई ऐप्स में सबसे मूल्यवान चीज़ें फ़ोटो या सेटिंग्स नहीं होतीं—वे छोटे स्ट्रिंग्स होते हैं जो एक्सेस खोल देते हैं।
डिवाइस पर अक्सर स्टोर होने वाली चीज़ों में सेशन टोकन (ताकि यूज़र साइन-इन रहें), रिफ्रेश टोकन, API कीज़, एन्क्रिप्शन कीज़, व्यक्तिगत डेटा (PII) जैसे नाम और ईमेल, और ऑफ़लाइन उपयोग के लिए कैश किए गए बिज़नेस रिकॉर्ड (ऑर्डर, टिकट, ग्राहक नोट्स) शामिल हैं।
यहाँ सामान्य वास्तविक दुनिया की विफलताएँ हैं:
- खोया या चोरी हुआ डिवाइस जांचा जाता है, और टोकन कॉपी करके किसी यूज़र की नकल की जाती है।
- मालवेयर या एक “हेल्पर” ऐप रूटेड डिवाइस पर लोकल फाइलें पढ़ता है या एक्सेसिबिलिटी ट्रिक्स से जानकारी निकालता है।
- ऑटोमैटिक डिवाइस बैकअप आपके ऐप का डेटा कहीं भेज देता है जहां आपने योजना नहीं बनाई थी।
- डिबग बिल्ड्स टोकन लॉग करते हैं, उन्हें क्रैश रिपोर्ट में लिखते हैं, या सिक्योरिटी चेक्स को डिसेबल कर देते हैं।
इसलिए "सिर्फ SharedPreferences में स्टोर कर दो" कुछ भी ऐसा के लिए ठीक नहीं है जो एक्सेस देता हो (टोकन) या उपयोगकर्ताओं और आपकी कंपनी के लिए नुकसानदेह हो सकता है (PII)। Plain SharedPreferences ऐसे है जैसे ऐप के अंदर सीक्रेट्स को पोस्ट-इट नोट पर लिख देना: सुविधाजनक, और अगर किसी को मौका मिल जाए तो पढ़ना आसान।
सबसे उपयोगी शुरुआत यह है कि आप हर स्टोर आइटम का नाम लें और दो सवाल पूछें: क्या यह कुछ अनलॉक करता है, और अगर यह सार्वजनिक हो जाये तो क्या समस्या होगी? बाकी (Keystore, encrypted preferences, encrypted database) वहीं से तय होता है।
अपने डेटा को वर्गीकृत करें: टोकन, कीज़, और PII
सभी "सेंसिटिव डेटा" को एक जैसा मानना बंद कर दें—सुरक्षित स्टोरेज आसान हो जाता है। सबसे पहले लिखें कि ऐप क्या सेव करता है और लीक होने पर क्या होगा।
टोकन पासवर्ड जैसे नहीं होते। एक्सेस टोकन और रिफ्रेश टोकन स्टोर करने के लिए होते हैं ताकि यूज़र साइन-इन रहे, पर वे अभी भी हाई-वैल्यू सीक्रेट्स हैं। पासवर्ड कभी स्टोर नहीं करने चाहिए। अगर लॉगिन की ज़रूरत है, तो केवल वही स्टोर करें जो सेशन बनाए रखने के लिए आवश्यक हो (आम तौर पर टोकन) और पासवर्ड चेक सर्वर पर भरोसा करें।
कीज़ अलग श्रेणी हैं। API कीज़, साइनिंग कीज़, और एन्क्रिप्शन कीज़ पूरे सिस्टम को अनलॉक कर सकती हैं, न कि सिर्फ़ एक यूज़र अकाउंट को। अगर कोई इन्हें डिवाइस से निकाल लेता है, तो वह बड़े पैमाने पर दुरुपयोग कर सकता है। एक अच्छा नियम: अगर कोई वैल्यू ऐप के बाहर उपयोग करके ऐप की नकल कर सकती है या डेटा डिक्रिप्ट कर सकती है, तो उसे यूज़र टोकन की तुलना में उच्च जोखिम मानें।
PII वह सब कुछ है जो किसी व्यक्ति की पहचान कर सके: ईमेल, फोन, घर का पता, ग्राहक नोट्स, सरकारी आईडी, स्वास्थ्य संबंधी डेटा। जो फ़ील्ड निर्दोष लगती हैं वे संयोजन में संवेदनशील बन सकती हैं।
एक त्वरित लेबलिंग सिस्टम जो व्यवहार में अच्छा काम करता है:
- Session secrets: access token, refresh token, session cookie
- App secrets: API keys, signing keys, encryption keys (जहां संभव हो डिवाइस पर रखने से बचें)
- User data (PII): प्रोफ़ाइल विवरण, पहचानकर्ता, दस्तावेज़, मेडिकल या वित्तीय जानकारी
- Device and analytics IDs: advertising ID, device ID, install ID (कई नीतियों में अभी भी संवेदनशील)
Android Keystore: इसे कब उपयोग करें
Android Keystore सबसे अच्छा है जब आपको उन सीक्रेट्स की रक्षा करनी हो जो कभी डिवाइस से plain form में बाहर नहीं निकलने चाहिए। यह क्रिप्टोग्राफिक कीज़ के लिए एक सेफ है, आपके वास्तविक डेटा का डेटाबेस नहीं।
यह किसमें अच्छा है: कीज़ जनरेट और होल्ड करना जिनका उपयोग एन्क्रिप्शन, डिक्रिप्शन, साइनिंग, या वेरिफाइ करने में होता है। आप आमतौर पर किसी टोकन या ऑफ़लाइन डेटा को कहीं और एन्क्रिप्ट करते हैं, और Keystore की वही चीज़ अनलॉक करती है।
हार्डवेयर-बैक्ड कीज़: असल में इसका क्या मतलब है
कई डिवाइसेज़ पर Keystore कीज़ हार्डवेयर-बैक्ड हो सकती हैं। इसका मतलब है कि की ऑपरेशन्स एक सुरक्षित एनवायरनमेंट के अंदर होते हैं और की मटेरियल एक्स्ट्रैक्ट नहीं किया जा सकता। यह उन मालवेयर से जोखिम कम करता है जो ऐप फाइलें पढ़ सकते हैं।
हार्डवेयर-बैक्ड हर डिवाइस पर गारंटीड नहीं होता और व्यवहार मॉडल और Android वर्ज़न के अनुसार बदलता है। ऐसे डिजाइन करें मान कर कि की ऑपरेशन्स फेल भी हो सकते हैं।
उपयोगकर्ता प्रमाणीकरण गेट्स
Keystore यह मांग सकता है कि की का उपयोग करने से पहले उपयोगकर्ता मौजूद हो। इससे आप बायोमेट्रिक्स या डिवाइस क्रेडेंशियल के साथ एक्सेस बाँध सकते हैं। उदाहरण के लिए, आप किसी export token को एन्क्रिप्ट कर सकते हैं और केवल तभी डिक्रिप्ट कर सकते हैं जब यूज़र फिंगरप्रिंट या PIN से पुष्टि करे।
Keystore अच्छा विकल्प है जब आप नॉन-एक्सपोर्टेबल की चाहते हैं, जब आप संवेदनशील क्रियाओं के लिए बायोमेट्रिक या डिवाइस-क्रेडेंशियल अनुमोदन चाहते हैं, और जब आप पर-दिवाइस सीक्रेट्स चाहते हैं जो बैकअप या सिंक के साथ ना जाएँ।
पिटफॉल की योजना बनाएं: कीज़ लॉक स्क्रीन परिवर्तन, बायोमेट्रिक बदलाव, या सुरक्षा घटनाओं के बाद इनवैलिडेट हो सकती हैं। फेल्यर की उम्मीद करें और एक साफ़ बैकअप रखें: इनवैलिड कीज़ का पता लगाएँ, एन्क्रिप्टेड ब्लॉब्स मिटाएँ, और उपयोगकर्ता से फिर से साइन-इन करने के लिए कहें।
EncryptedSharedPreferences: कब यह पर्याप्त है
EncryptedSharedPreferences छोटे सेट के secrets के लिए एक अच्छा डिफ़ॉल्ट है जो key-value फॉर्म में होते हैं। यह "SharedPreferences, पर एन्क्रिप्टेड" है ताकि कोई फ़ाइल खोलकर मान नहीं पढ़ सके।
अंदरूनी तौर पर यह वैल्यूज़ एन्क्रिप्ट/डिक्रिप्ट करने के लिए एक मास्टर की का उपयोग करता है। वह मास्टर की Android Keystore द्वारा सुरक्षित रहती है, इसलिए आपका ऐप कच्ची एनक्रिप्शन की सीधे नहीं स्टोर कर रहा होता।
यह आमतौर पर उन कुछ छोटे आइटम्स के लिए काफी है जिन्हें आप अक्सर पढ़ते हैं, जैसे access और refresh tokens, session IDs, device IDs, environment flags, या last sync time जैसे छोटे स्टेट बिट्स। अगर आपको सच में छोटे टुकड़े PII स्टोर करना ही है तो यह ठीक है, पर इसे PII का dumping ground न बनाएं।
यह बड़े या संरचित डेटा के लिए अच्छा नहीं है। अगर आपको ऑफ़लाइन सूचियाँ, सर्च, या फील्ड के आधार पर क्वेरी चाहिए (customers, tickets, orders), तो EncryptedSharedPreferences धीमा और अजीब लगने लगेगा। ऐसे में आपको एन्क्रिप्टेड डेटाबेस चाहिए।
एक सरल नियम: अगर आप हर स्टोर की गई कुंजी को एक स्क्रीन पर सूचीबद्ध कर सकते हैं, तो EncryptedSharedPreferences शायद ठीक है। अगर आपको rows और queries चाहिए, तो आगे बढ़ें।
डेटाबेस एन्क्रिप्शन: जब इसकी ज़रूरत होती है
जब आप एक छोटे setting या एक टोकन से अधिक स्टोर करते हैं तो डेटाबेस एन्क्रिप्शन मायने रखता है। अगर आपका ऐप डिवाइस पर बिज़नेस डेटा रखता है, तो मान लें कि खोए हुए फोन से उसे निकाला जा सकता है जब तक आप उसकी सुरक्षा नहीं करते।
एक डेटाबेस समझ में आता है जब आपको रिकॉर्ड्स तक ऑफ़लाइन एक्सेस चाहिए, लोकल कैशिंग परफॉर्मेंस के लिए, हिस्ट्री/ऑडिट ट्रेल्स, या लंबे नोट्स और अटैचमेंट्स।
दो सामान्य एन्क्रिप्शन दृष्टिकोण
फुल डेटाबेस एन्क्रिप्शन (अक्सर SQLCipher-स्टाइल) पूरी फ़ाइल को रेस्ट पर एन्क्रिप्ट कर देता है। आपका ऐप इसे एक की के साथ खोलता है। यह आसान है क्योंकि आपको यह याद नहीं रखना पड़ता कि कौन से कॉलम प्रोटेक्टेड हैं।
एप-लेयर फील्ड एन्क्रिप्शन केवल कुछ फ़ील्ड्स को लिखने से पहले एन्क्रिप्ट करता है, फिर पढ़ने पर डिक्रिप्ट करता है। यह तब काम कर सकता है जब ज़्यादातर रिकॉर्ड संवेदनशील न हों, या आप बिना फ़ाइल फॉर्मेट बदले किसी डेटाबेस सेटअप को बनाए रखना चाह रहे हों।
ट्रेडऑफ: गोपनीयता बनाम सर्च और सॉर्ट
फुल डेटाबेस एन्क्रिप्शन डिस्क पर सबकुछ छिपा देता है, पर एक बार डेटाबेस अनलॉक होने पर आपका ऐप सामान्य रूप से क्वेरी कर सकता है।
फील्ड एन्क्रिप्शन कुछ कॉलमों की रक्षा करता है, लेकिन आपको एनक्रिप्टेड वैल्यूज़ पर आसान सर्च और सॉर्टिंग खोनी पड़ती है। एन्क्रिप्टेड उपनाम के आधार पर सॉर्ट करना भरोसेमंद नहीं होगा, और सर्च या तो "डिक्रिप्ट करने के बाद सर्च" (धीमा) या "अतिरिक्त इंडेक्स स्टोर करें" (ज़्यादा जटिलता और संभावित लीक) बन जाता है।
की मैनेजमेंट बेसिक्स
डेटाबेस की कभी भी हार्डकोड या ऐप में शिप नहीं करनी चाहिए। एक सामान्य पैटर्न है: एक रैंडम डेटाबेस की जनरेट करें, फिर उसे किसी Keystore–बैक्ड की से रैप करके स्टोर करें। लॉगआउट पर आप रैप की हटा सकते हैं और लोकल डेटाबेस को डिस्पोजेबल मान सकते हैं, या अगर ऐप को ऑफ़लाइन across sessions काम करना है तो उसे रखें।
कैसे चुनें: एक व्यावहारिक तुलना
आप सामान्य रूप से "सबसे सुरक्षित" विकल्प नहीं चुन रहे होते—आप वह सबसे सुरक्षित विकल्प चुन रहे हैं जो आपके डेटा उपयोग के तरीके के साथ मेल खाता हो।
वो प्रश्न जो सही विकल्प तय करते हैं:
- डेटा कितनी बार पढ़ा जाता है (हर लॉन्च पर या शायद ही)?
- कितना डेटा है (कुछ बाइट्स या हजारों रिकॉर्ड)?
- अगर लीक हो जाए तो क्या होगा (कष्टप्रद, महंगा, कानूनी रिपोर्टिंग)?
- क्या आपको ऑफ़लाइन एक्सेस, सर्च, या सॉर्ट चाहिए?
- क्या आपके पास अनुपालन आवश्यकताएँ हैं (रिटेंशन, ऑडिट, एन्क्रिप्शन नियम)?
एक व्यवहार्य मैपिंग:
- Tokens (OAuth access और refresh tokens) आम तौर पर
EncryptedSharedPreferencesमें होने चाहिए क्योंकि वे छोटे हैं और अक्सर पढ़े जाते हैं। - Key material जहां संभव हो Android Keystore में रहना चाहिए ताकि इसे डिवाइस से कॉपी किए जाने की संभावना कम रहे।
- PII और ऑफ़लाइन बिज़नेस डेटा अक्सर डेटाबेस एन्क्रिप्शन की ज़रूरत होती है जब आप कुछ फ़ील्ड से ज़्यादा स्टोर करते हैं या ऑफ़लाइन लिस्ट और फ़िल्टरिंग चाहिए होते हैं।
मिक्स्ड डेटा बिज़नेस ऐप्स में सामान्य है। एक व्यावहारिक पैटर्न है कि आप अपने लोकल डेटाबेस या फाइल के लिए एक रैंडम डेटा एन्क्रिप्शन की (DEK) जेनरेट करें, केवल रैप्ड DEK को Keystore–बैक्ड की से स्टोर करें, और आवश्यकता पर उसे रोटेट करें।
अगर आप अनिश्चित हैं, तो आसान सुरक्षित मार्ग चुनें: कम स्टोर करें। ऑफ़लाइन PII से बचें जब तक वास्तव में इसकी ज़रूरत न हो, और कीज़ को Keystore में रखें।
चरण-दर-चरण: Kotlin ऐप में सुरक्षित स्टोरेज लागू करना
सबसे पहले वे सभी वैल्यू लिखें जिन्हें आप डिवाइस पर स्टोर करने की योजना बना रहे हैं और हर एक का सटीक कारण। यह "बस किसी भी हालत में" स्टोरिंग को रोकने का सबसे तेज़ तरीका है।
कोड लिखने से पहले अपने नियम तय करें: प्रत्येक आइटम कितनी देर रहेगा, कब बदलना चाहिए, और "लॉगआउट" का क्या मतलब है। एक एक्सेस टोकन 15 मिनट में एक्सपायर हो सकता है, एक रिफ्रेश टोकन लंबा चल सकता है, और ऑफ़लाइन PII के लिए सख्त "30 दिनों के बाद डिलीट" नियम की ज़रूरत हो सकती है।
रख-रखाव में रहने वाली इम्प्लिमेंटेशन:
- एक अकेला "SecureStorage" रैपर बनाएं ताकि बाकी ऐप सीधे SharedPreferences, Keystore, या डेटाबेस को ना छुए।
- प्रत्येक आइटम को सही जगह पर रखें: टोकन
EncryptedSharedPreferencesमें, एन्क्रिप्शन कीज़ Android Keystore द्वारा सुरक्षित, और बड़े ऑफ़लाइन डेटासेट एन्क्रिप्टेड डेटाबेस में। - जानबूझकर फेल्यर्स को हैंडल करें। अगर secure storage फेल हो, तो फेल क्लोज़ रखें। चुपचाप plain स्टोरेज पर फॉल बैक न करें।
- डेटा लीक न करने वाले डायग्नोस्टिक्स जोड़ें: इवेंट प्रकार और एरर कोड लॉग करें, कभी भी टोकन, कीज़, या यूज़र डिटेल्स लॉग न करें।
- डिलीशन पाथ्स को वायर करें: लॉगआउट, अकाउंट रिमूवल, और "clear app data" को एक ही वाइप रूटीन में डालें।
फिर उन बोरिंग केसों का परीक्षण करें जो प्रोडक्शन में secure storage तोड़ते हैं: बैकअप से रिस्टोर, पुरानी ऐप वर्ज़न से अपग्रेड, डिवाइस लॉक सेटिंग बदलना, नए फोन पर माइग्रेशन। सुनिश्चित करें कि उपयोगकर्ता ऐसे लूप में फंस न जाएँ जहाँ स्टोर किया गया डेटा डिक्रिप्ट न हो पाए पर ऐप बार-बार कोशिश करता रहे।
अंत में, निर्णयों को एक पेज पर लिख दें जिसे पूरी टीम फॉलो कर सके: क्या कहाँ स्टोर होता है, रिटेंशन अवधि, और डिक्रिप्शन फेल होने पर क्या होना चाहिए।
सामान्य गलतियाँ जो secure storage तोड़ देती हैं
ज्यादातर विफलताएँ गलत लाइब्रेरी चुनने की वजह से नहीं होतीं। वे तब होती हैं जब एक छोटा शॉर्टकट चुपचाप सीक्रेट्स को उन जगहों पर कॉपी कर देता है जहां आपने स्टोर करने का इरादा नहीं किया था।
सबसे बड़ा रेड फ्लैग है कोई भी रिफ्रेश टोकन (या लंबी-आयु वाला सेशन टोकन) प्लेनटेक्स्ट में कहीं सेव होना: SharedPreferences, कोई फाइल, एक "टेम्पररी" कैश, या लोकल डेटाबेस कॉलम। अगर कोई बैकअप लेता है, रूटेड डिवाइस डंप करता है, या डिबग बिल्ड आर्टिफैक्ट निकलता है, तो वह टोकन पासवर्ड से भी लंबा जी सकता है।
सीक्रेट्स visibility के जरिए भी लीक होते हैं, न कि केवल स्टोरेज से। फुल रिक्वेस्ट हेडर्स लॉग करना, डिबग के दौरान टोकन प्रिंट करना, या क्रैश रिपोर्ट्स और एनालिटिक्स इवेंट्स में "हेल्पफुल" संदर्भ जोड़ना क्रेडेंशियल्स को डिवाइस के बाहर उजागर कर सकता है। लॉग्स को सार्वजनिक मानें।
की हैंडलिंग में भी अक्सर गैप होता है। सब कुछ के लिए एक ही की का उपयोग ब्लास्ट रेडियस बढ़ा देता है। की रोटेशन न करने का मतलब पुरानी समझौते मान्य बने रहते हैं। की वर्ज़निंग, रोटेशन, और पुराने एन्क्रिप्टेड डेटा के साथ क्या करना है—इसका प्लान शामिल करें।
"वॉल्ट के बाहर" पाथ्स को मत भूलें
एन्क्रिप्शन लोकल ऐप डेटा के क्लाउड बैकअप द्वारा कॉपी होने को नहीं रोकता। यह स्क्रीनशॉट या स्क्रीन रिकॉर्डिंग को नहीं रोकता जो PII कैप्चर कर सकती है। यह डिबग बिल्ड्स जिनमें सिक्योरिटी रिलीक्स होती हैं या एक्सपोर्ट फीचर (CSV/share sheets) से संवेदनशील फ़ील्ड लीक होने को नहीं रोकता। क्लिपबोर्ड उपयोग भी वन-टाइम कोड्स या अकाउंट नंबर लीक कर सकता है।
साथ ही, एन्क्रिप्शन ऑथराइज़ेशन को ठीक नहीं करता। अगर आपका ऐप लॉगआउट के बाद भी PII दिखाता है, या कैश्ड डेटा बिना रिइथेंटिकेट किए एक्सेस किया जा सकता है, तो यह एक्सेस कंट्रोल बग है। UI लॉक करें, लॉगआउट पर संवेदनशील कैशेस वाइप करें, और प्रोटेक्टेड डेटा दिखाने से पहले अनुमति फिर से जाँचें।
ऑपरेशनल विवरण: लाइफलाइकल, लॉगआउट, और एज केस
सुरक्षित स्टोरेज केवल वहां रखना नहीं है जहां आप सीक्रेट्स रखते हैं—यह यह भी है कि वे समय के साथ कैसे बर्ताव करते हैं: जब ऐप सोता है, जब उपयोगकर्ता लॉगआउट करता है, और जब डिवाइस लॉक होता है।
टोकन्स के लिए पूरा लाइफलाइकल प्लान करें। एक्सेस टोकन को शॉर्ट-लाइव रखें। रिफ्रेश टोकन को पासवर्ड की तरह माना जाना चाहिए। अगर टोकन एक्सपायर हो गया है, तो उसे शांतिपूर्वक रिफ्रेश करें। अगर रिफ्रेश विफल होता है (रिवोकेड, पासवर्ड बदला गया, डिवाइस हटाया गया), तो रिट्री लूप बंद करें और साफ साइन-इन फोर्स करें। सर्वर-साइड रिवोकेशन का समर्थन भी रखें। लोकल स्टोरेज अकेला चोरी किए गए क्रेडेंशियल्स को बेअसर नहीं कर सकता—रिवोकेशन जरूरी है।
बायोमेट्रिक्स का उपयोग रिइथ के लिए करें, हर चीज के लिए नहीं। उस समय प्रम्प्ट करें जब क्रिया का असली जोखिम हो (PII देखना, डेटा एक्सपोर्ट करना, पेआउट डिटेल बदलना, वन-टाइम की दिखाना)। हर ऐप ओपन पर प्रम्प्ट न करें।
लॉगआउट पर सख्त और पूर्वानुमेय बनें:
- पहले इन-मेमोरी कॉपियाँ स्पष्ट करें (सिंगलटन्स, इंटरसेप्टर्स, या ViewModels में कैश किए गए टोकन)।
- स्टोर किए गए टोकन और सेशन स्टेट वाइप करें (रिफ्रेश टोकन सहित)।
- लोकल एन्क्रिप्शन कीज़ हटाएँ या इनवैलिडेट करें अगर आपका डिज़ाइन इसका समर्थन करता है।
- ऑफ़लाइन PII और कैश्ड API प्रतिक्रियाएँ डिलीट करें।
- पृष्ठभूमि जॉब्स बंद करें जो डेटा फिर से फ़ेच कर सकते हैं।
एज केस बिज़नेस ऐप्स में मायने रखते हैं: एक ही डिवाइस पर मल्टीपल अकाउंट्स, वर्क प्रोफाइल्स, बैकअप/रिस्टोर, डिवाइस-टू-डिवाइस ट्रांसफर, और आंशिक लॉगआउट (कंपनी/वर्कस्पेस बदलना बजाय पूरा साइन-आउट के)। फोर्स स्टॉप, OS अपग्रेड्स, और क्लॉक चेंजेस का भी परीक्षण करें क्योंकि समय का अंतर एक्सपायरी लॉजिक तोड़ सकता है।
टैम्परिंग डिटेक्शन एक ट्रेडऑफ़ है। बेसिक चेक (debuggable बिल्ड्स, emulator फ्लैग्स, सरल रूट सिग्नल्स, Play Integrity verdicts) आकस्मिक दुरुपयोग को कम कर सकते हैं, पर दृढ़ अटैकर उन्हें बायपास कर सकता है। टैम्पर सिग्नल्स को रिस्क इनपुट मानें: ऑफ़लाइन एक्सेस सीमित करें, रि-ऑथ आवश्यक करें, और घटना लॉग करें।
शिप करने से पहले त्वरित चेकलिस्ट
रिलीस से पहले यह उपयोग करें। यह उन जगहों को लक्षित करता है जहाँ वास्तविक बिज़नेस ऐप्स में secure storage अक्सर फेल होता है।
- मान लें कि डिवाइस होस्टाइल हो सकता है। अगर अटैकर के पास रूटेड डिवाइस या पूरा डिवाइस इमेज है, क्या वे ऐप फाइलों, प्रेफरेंसेज़, लॉग्स, या स्क्रीनशॉट्स से टोकन, कीज़, या PII पढ़ सकते हैं? अगर जवाब "शायद" है, तो Keystore–बैक्ड सुरक्षा पर रहकर पेलोड एन्क्रिप्ट रखें।
- बैकअप और डिवाइस ट्रांसफ़र्स चेक करें। संवेदनशील फाइलों को Android Auto Backup, क्लाउड बैकअप्स, और डिवाइस-टू-डिवाइस ट्रांसफ़र से बाहर रखें। अगर रिस्टोर पर कोई की गायब हो तो डिक्रिप्शन टूट जाएगा, तो रिकवरी फ्लो प्लान करें (री-ऑथ और री-डownload बनाम डिक्रिप्ट करने की कोशिश)।
- डिस्क पर आकस्मिक प्लेनटेक्स्ट की तलाश करें। टेम्प फाइलें, HTTP कैश, क्रैश रिपोर्ट्स, एनालिटिक्स इवेंट्स, और इमेज कैश्स देखें जो PII या टोकन रख सकते हैं। डिबग लॉगिंग और JSON डंप्स की जाँच करें।
- एक्सपायर और रोटेट करें। एक्सेस टोकन शॉर्ट-लाइव होने चाहिए, रिफ्रेश टोकन सुरक्षित रहने चाहिए, और सर्वर-साइड सेशन रिवोकेबल होने चाहिए। की रोटेशन पर परिभाषा रखें और ऐप तब क्या करे जब टोकन रिजेक्ट हो (क्लियर, री-ऑथ, एक बार रिट्राई)।
- रीइंस्टॉल और डिवाइस-चेंज व्यवहार। अनइंस्टॉल और रीइंस्टॉल टेस्ट करें, फिर ऑफ़लाइन खोलें। अगर Keystore कीज़ गायब हैं, तो ऐप को सुरक्षित तरीके से फेल होना चाहिए (एन्क्रिप्टेड डेटा वाइप करें, साइन-इन दिखाएँ, आंशिक पढ़ाई से बचें जो स्टेट को करप्ट कर दे)।
एक तेज़ मान्यता "बुरा दिन" टेस्ट है: एक उपयोगकर्ता लॉगआउट करता है, पासवर्ड बदलता है, बैकअप को नए फोन पर रिस्टोर करता है, और प्लेन में ऐप खोलता है। परिणाम पूर्वानुमेय होना चाहिए: या तो डेटा सही उपयोगकर्ता के लिए डिक्रिप्ट होता है, या वह वाइप होकर साइन-इन के बाद फिर से फ़ेच हो जाता है।
उदाहरण परिदृश्य: एक बिज़नेस ऐप जो ऑफ़लाइन PII स्टोर करता है
एक फ़ील्ड सेल्स ऐप की कल्पना करें जो कमजोर सिग्नल वाले क्षेत्रों में उपयोग होता है। रेप्स सुबह एक बार लॉगिन करते हैं, असाइन किए गए कस्टमर्स को ऑफ़लाइन ब्राउज़ करते हैं, मीटिंग नोट्स जोड़ते हैं, और बाद में सिंक करते हैं। यह वह जगह है जहाँ स्टोरेज चेकलिस्ट सिद्धांत से वास्तविक लीक रोकने लगती है।
एक व्यावहारिक विभाजन:
- Access token: शॉर्ट-लाइव रखें और
EncryptedSharedPreferencesमें स्टोर करें। - Refresh token: अधिक कड़ाई से सुरक्षित रखें और एक्सेस को Android Keystore से गेट करें।
- Customer PII (नाम, फोन, पते): एन्क्रिप्टेड लोकल डेटाबेस में स्टोर करें।
- Offline नोट्स और अटैचमेंट्स: एन्क्रिप्टेड डेटाबेस में स्टोर करें, और एक्सपोर्ट/शेयर के मामलों में अतिरिक्त सावधानी बरतें।
अब दो फीचर जोड़ें और रिस्क बदल जाता है।
अगर आप "remember me" जोड़ते हैं, तो रिफ्रेश टोकन मुख्य दरवाज़ा बन जाता है जो अकाउंट में वापस जाता है। इसे पासवर्ड की तरह ट्रीट करें। आपके उपयोगकर्ताओं के अनुसार आप डिक्रिप्शन से पहले डिवाइस अनलॉक (PIN/pattern/biometric) आवश्यक कर सकते हैं।
अगर आप ऑफ़लाइन मोड जोड़ते हैं, तो आप केवल सेशन की रक्षा नहीं कर रहे—आप पूरे ग्राहक सूची की रक्षा कर रहे हैं जो अपने आप में मूल्यवान हो सकती है। यह आम तौर पर आपको डेटाबेस एन्क्रिप्शन की ओर धकेलता है साथ ही स्पष्ट लॉगआउट नियम: लोकल PII वाइप करें, केवल अगली लॉगिन के लिए आवश्यक चीज़ रखें, और बैकग्राउंड सिंक रद्द करें।
वास्तविक डिवाइसेज़ पर टेस्ट करें, सिर्फ़ एमुलेटर पर नहीं। कम से कम लॉक/अनलॉक व्यवहार, रीइंस्टॉल व्यवहार, बैकअप/रिस्टोर, और मल्टी-यूज़र या वर्क प्रोफ़ाइल अलगाव की जाँच करें।
अगले कदम: इसे टीम की आदत बनाएं
सुरक्षित स्टोरेज तभी काम करता है जब यह एक आदत बन जाए। एक छोटा सा स्टोरेज पॉलिसी लिखें जिसे आपकी टीम फॉलो कर सके: क्या कहाँ जाता है (Keystore, EncryptedSharedPreferences, encrypted database), क्या कभी स्टोर नहीं होना चाहिए, और लॉगआउट पर क्या वाइप होना चाहिए।
इसे रोज़मर्रा की डिलीवरी का हिस्सा बनाएं: definition of done, कोड रिव्यू, और रिलीज़ चेक्स।
एक हल्का रिव्युअर चेकलिस्ट:
- हर स्टोर की गई आइटम को लेबल किया गया है (token, key material, या PII)।
- स्टोरेज का चुनाव कोड कमेंट्स में justified है।
- लॉगआउट और अकाउंट स्विच सही डेटा हटा देते हैं (और केवल वही डेटा)।
- एरर और लॉग्स कभी भी सीक्रेट्स या पूर्ण PII प्रिंट नहीं करते।
- कोई व्यक्ति पॉलिसी का मालिक है और उसे अपडेट रखता है।
अगर आपकी टीम AppMaster (appmaster.io) का उपयोग करके बिज़नेस ऐप बनाती है और Android क्लाइंट के लिए Kotlin सोर्स एक्सपोर्ट करती है, तो वही SecureStorage रैपर अप्रोच रखें ताकि जेनरेटेड और कस्टम कोड एक सुसंगत पॉलिसी फॉलो करे।
एक छोटा POC से शुरू करें
एक छोटा POC बनाएं जो एक auth token और एक PII रिकॉर्ड (उदाहरण के लिए ऑफ़लाइन ज़रूरी ग्राहक फोन नंबर) स्टोर करे। फिर फ्रेस इंस्टॉल, अपग्रेड, लॉगआउट, लॉक स्क्रीन बदलाव, और क्लियर ऐप डाटा टेस्ट करें। केवल तभी विस्तार करें जब वाइप व्यवहार सही और दोहराने योग्य हो।
सामान्य प्रश्न
शुरुआत में वो सभी चीजें लिखें जो आप डिवाइस पर संग्रहीत करने जा रहे हैं और क्यों। छोटे सेशन सीक्रेट्स जैसे एक्सेस और रिफ्रेश टोकन EncryptedSharedPreferences में रखें, क्रिप्टोग्राफिक कीज़ Android Keystore में रखें, और जब आप कुछ फ़ील्ड से ज़्यादा PII या ऑफ़लाइन रिकॉर्ड स्टोर कर रहे हों तो एक एन्क्रिप्टेड डेटाबेस का उपयोग करें।
साधारण SharedPreferences फ़ाइल के रूप में मानक टेक्स्ट में सेव करता है, जिसे बैकअप, रूटेड डिवाइस, या डिबग आर्टिफैक्ट से पढ़ा जा सकता है। अगर वह वैल्यू टोकन या कोई PII है, तो इसे सामान्य सेटिंग की तरह रखना उसे ऐप के बाहर कॉपी और पुन: उपयोग करना आसान कर देता है।
Android Keystore का उपयोग उन क्रिप्टोग्राफिक कीज़ को जनरेट और होल्ड करने के लिए करें जिन्हें एक्स्ट्रैक्ट नहीं किया जाना चाहिए। आप आम तौर पर इन कीज़ का उपयोग अन्य डेटा (टोकन, डेटाबेस कीज़, फाइलें) को एन्क्रिप्ट करने के लिए करते हैं, और चाहें तो की उपयोग पर बायोमेट्रिक्स या डिवाइस क्रेडेंशियल की माँग भी कर सकते हैं।
इसका मतलब है कि की ऑपरेशन्स प्रोटेक्टेड हार्डवेयर में हो सकते हैं, इसलिए की मटेरियल निकालना मुश्किल होता है—यहां तक कि अगर कोई अटैकर ऐप फाइलें पढ़ भी ले। इसे हमेशा उपलब्ध मानने की गलती न करें; फेल्यर के लिए डिजाइन करें और रिकवरी फ्लो रखें।
EncryptedSharedPreferences आमतौर पर अक्सर पढ़े जाने वाले छोटे key-value सीक्रेट्स के लिए काफी है, जैसे कि access/refresh tokens, session IDs, और छोटे स्टेट बिट्स। यह बड़े डेटा, संरचित ऑफ़लाइन रिकॉर्ड, या क्वेरी/फ़िल्टरिंग की ज़रूरत वाले मामलों के लिए उपयुक्त नहीं है।
जब आप बड़े पैमाने पर ऑफ़लाइन बिज़नेस डेटा या PII स्टोर करते हैं, क्वेरी/सर्च/सोर्ट की ज़रूरत होती है, या आपको ऑफ़लाइन इतिहास रखना है, तो एन्क्रिप्टेड डेटाबेस चुनें। यह खोए हुए फोन से पूरे ग्राहक सूचियों या नोट्स के उजागर होने के जोखिम को कम करता है और ऑफ़लाइन काम करने की क्षमता देता है।
पूर्ण डेटाबेस एन्क्रिप्शन पूरे फ़ाइल को रेस्ट पर सुरक्षित रखता है और समझने में आसान है क्योंकि आपको यह ट्रैक नहीं करना पड़ता कि कौन से कॉलम संवेदनशील हैं। फ़ील्ड-स्तरीय एन्क्रिप्शन कुछ कॉलम के लिए काम कर सकता है पर सर्च और सॉर्ट मुश्किल बन जाते हैं और इंडेक्स या व्युत्पन्न फ़ील्ड के जरिए लीक आसान हो सकता है।
एक सामान्य पैटर्न: एक रैंडम डेटाबेस की (DEK) जनरेट करें, फिर उसे केवल wrapped (एन्क्रिप्टेड) रूप में स्टोर करें, जिसे Android Keystore–बैक्ड की से एनक्रिप्ट किया गया हो। कीज़ को हार्डकोड न करें और न ही ऐप में शिप करें। लॉगआउट या की इनवैलिडेशन पर आप wrapped key हटा सकते हैं और लोकल डेटा को डिस्पोजेबल मान सकते हैं।
कीज़ लॉक स्क्रीन या बायोमेट्रिक बदलाव, OS सुरक्षा घटनाओं, या रिकवरी/माइग्रेशन पर इनवैलिडेट हो सकती हैं। इसे स्पष्ट रूप से हैंडल करें: डीक्रिप्शन फेल्यर का पता लगाएं, एन्क्रिप्टेड ब्लॉब्स या लोकल डेटाबेस को सुरक्षित रूप से वाइप करें, और उपयोगकर्ता को फिर से साइन-इन करने के लिए संकेत दें—बिना plaintext पर वापस गिरने के।
अधिकांश लीक "वॉल्ट के बाहर" होते हैं: लॉग, क्रैश रिपोर्ट, एनालिटिक्स इवेंट्स, डिबग प्रिंट्स, HTTP कैश, स्क्रीनशॉट, क्लिपबोर्ड, और बैकअप/रिस्टोर पाथ। लॉग्स को सार्वजनिक मानें, कभी भी टोकन या पूर्ण PII रिकॉर्ड न करें, एक्सपोर्ट पाथ्स बंद करें, और लॉगआउट पर स्टोर्ड डेटा और इन-मेमोरी कॉपियाँ दोनों वाइप करें।


