android - अनुप्रयोगों में निजी एपीआई कुंजी भंडारण और सुरक्षा के लिए सबसे अच्छा अभ्यास




reverse-engineering proguard (8)

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

मान लीजिए मेरे पास ऐसा कुछ है, मैं गुप्त कुंजी की रक्षा कैसे कर सकता हूं:

public class DropboxService  {

    private final static String APP_KEY = "jk433g34hg3";
    private final static String APP_SECRET = "987dwdqwdqw90";
    private final static AccessType ACCESS_TYPE = AccessType.DROPBOX;

    // SOME MORE CODE HERE

}

आपकी राय में निजी कुंजी को स्टोर करने का सबसे अच्छा और सबसे सुरक्षित तरीका क्या है? Obfuscation, एन्क्रिप्शन, आपको क्या लगता है?


ऐप-सीक्रेट कुंजी को निजी रखा जाना चाहिए - लेकिन ऐप को रिलीज़ करते समय उन्हें कुछ लोगों द्वारा उलट किया जा सकता है।

उन लोगों के लिए यह छिपाना नहीं होगा, या तो ProGuard कोड को लॉक करें। यह एक रिफैक्टर है और कुछ भुगतान किए गए obfuscators jk433g34hg3 स्ट्रिंग को वापस पाने के लिए कुछ bitwise ऑपरेटरों को सम्मिलित कर रहे हैं। यदि आप 3 दिन काम करते हैं तो आप 5 -15 मिनट हैकिंग कर सकते हैं :)

सबसे अच्छा तरीका यह है कि इसे रखना है, इमो।

यहां तक ​​कि यदि आप सर्वर साइड (अपने पीसी) पर स्टोर करते हैं तो भी कुंजी को हैक किया जा सकता है और मुद्रित किया जा सकता है। शायद यह सबसे लंबा लगता है? किसी भी तरह यह सर्वोत्तम मामले में कुछ मिनट या कुछ घंटों का मामला है।

एक सामान्य उपयोगकर्ता आपके कोड को संकुचित नहीं करेगा।


एपीआई / गुप्त कुंजी को सुरक्षित करने के लिए 3 सरल चरणों का पालन करें

हम एपीआई कुंजी या गुप्त कुंजी को सुरक्षित करने के लिए ग्रैडल का उपयोग कर सकते हैं।

1. gradle.properties (परियोजना गुण): कुंजी के साथ चर बनाएँ।

GoolgeAPIKey = "Your API/Secret Key"

2. build.gradle (मॉड्यूल: ऐप): गतिविधि या खंड में इसे एक्सेस करने के लिए build.gradle में चर सेट करें। बिल्ड टाइप टाइप करने के लिए नीचे कोड जोड़ें {}।

buildTypes.each {
    it.buildConfigField 'String', 'GoogleSecAPIKEY', GoolgeAPIKey
}

3. एप के BuildConfig द्वारा गतिविधि / टुकड़े में इसे एक्सेस करें:

BuildConfig.GoogleSecAPIKEY

इन निजी को रखने का एकमात्र सही तरीका है उन्हें अपने सर्वर पर रखना, और ऐप को सर्वर पर जो कुछ भी भेजना है, और सर्वर ड्रॉपबॉक्स के साथ इंटरैक्ट करता है। इस तरह आप किसी भी प्रारूप में अपनी निजी कुंजी कभी वितरित नहीं करते हैं।


इस उदाहरण में इसके कई अलग-अलग पहलू हैं। मैं कुछ बिंदुओं का उल्लेख करूंगा जो मुझे नहीं लगता कि स्पष्ट रूप से कहीं और शामिल किया गया है।

पारगमन में रहस्य की रक्षा

नोट करने वाली पहली बात यह है कि ड्रॉप ऐप को अपने ऐप प्रमाणीकरण तंत्र का उपयोग करके एक्सेस करने के लिए आपको अपनी कुंजी और गुप्त संचारित करने की आवश्यकता होती है। कनेक्शन HTTPS है जिसका अर्थ है कि आप टीएलएस प्रमाण पत्र को जानने के बिना यातायात को रोक नहीं सकते हैं। यह किसी व्यक्ति को मोबाइल डिवाइस से सर्वर पर अपनी यात्रा पर पैकेट को अवरुद्ध करने और पढ़ने से रोकने के लिए है। सामान्य उपयोगकर्ताओं के लिए यह उनके यातायात की गोपनीयता सुनिश्चित करने का एक अच्छा तरीका है।

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

आप pinning कर सकते हैं जो जांचता है कि सर्वर से प्राप्त टीएलएस प्रमाण पत्र वह है जिसे आप उम्मीद करते हैं। यह ग्राहक को एक चेक जोड़ता है और यातायात को रोकने में और अधिक कठिन बनाता है। इससे उड़ान में यातायात का निरीक्षण करना मुश्किल हो जाएगा, लेकिन ग्राहक में पिनिंग जांच होती है, इसलिए संभवतः पिनिंग परीक्षण को अक्षम करना संभव होगा। हालांकि यह कठिन बना देता है।

आराम से रहस्य की रक्षा

पहले चरण के रूप में, proguard जैसे कुछ का उपयोग करने से यह कम स्पष्ट हो जाएगा कि कोई रहस्य कहाँ है। आप कुंजी और गुप्त स्टोर करने और सीधे अनुरोध भेजने के लिए एनडीके का उपयोग भी कर सकते हैं, जो जानकारी निकालने के लिए उपयुक्त कौशल वाले लोगों की संख्या को बहुत कम कर देगा। किसी भी समय के लिए स्मृति में सीधे मूल्यों को संग्रहीत न करके आगे obfuscation प्राप्त किया जा सकता है, आप उन्हें एन्क्रिप्ट कर सकते हैं और किसी अन्य उत्तर द्वारा सुझाए गए उपयोग से पहले उन्हें डिक्रिप्ट कर सकते हैं।

अधिक उन्नत विकल्प

यदि अब आप अपने ऐप में कहीं भी रहस्य डालने के बारे में पागल हैं, और आपके पास अधिक व्यापक समाधानों में निवेश करने के लिए समय और पैसा है, तो आप अपने सर्वर पर प्रमाण-पत्र संग्रहीत करने पर विचार कर सकते हैं (मान लें कि आपके पास कोई है)। यह एपीआई को किसी भी कॉल की विलंबता में वृद्धि करेगा, क्योंकि इसे आपके सर्वर के माध्यम से संवाद करना होगा, और बढ़ी हुई डेटा थ्रूपुट के कारण आपकी सेवा चलाने की लागत में वृद्धि हो सकती है।

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

मुझे कितना करना चाहिए?

इस तरह की किसी भी सुरक्षा सलाह के साथ आपको लागत / लाभ निर्णय लेने की आवश्यकता है कि आप इसे किसी के लिए तोड़ने के लिए कितना कठिन बनाना चाहते हैं। अगर आप लाखों ग्राहकों की रक्षा करने वाले बैंक हैं तो आपका बजट किसी ऐप का समर्थन करने वाले किसी व्यक्ति के लिए बिल्कुल अलग है खाली समय। किसी को आपकी सुरक्षा तोड़ने से रोकने के लिए लगभग असंभव है, लेकिन व्यवहार में कुछ लोगों को सभी घंटियां और सीटी की आवश्यकता होती है और कुछ बुनियादी सावधानी के साथ आप एक लंबा सफर तय कर सकते हैं।


एक और तरीका डिवाइस पर गुप्त स्थान नहीं है! मोबाइल एपीआई सुरक्षा तकनीक देखें (विशेष रूप से भाग 3)।

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

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

इसलिए यदि आप अपने रहस्य की रक्षा करना चाहते हैं, तो इसे अपने ऐप में पहले स्थान पर नहीं रखना एक अच्छा तरीका है।


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

// "the real string is: "mypassword" "; 
//encoded 2 times with an algorithm or you can encode with other algorithms too
public String getClientSecret() {
    return Utils.decode(Utils
            .decode("Ylhsd1lYTnpkMjl5WkE9PQ=="));
}

एक प्रोजेक्ट किए गए ऐप का डिकंपील्ड सोर्स कोड यह है:

 public String c()
 {
    return com.myrpoject.mypackage.g.h.a(com.myrpoject.mypackage.g.h.a("Ylhsd1lYTnpkMjl5WkE9PQ=="));
  }

कम से कम यह मेरे लिए काफी जटिल है। यह वही तरीका है जब मेरे पास कोई विकल्प नहीं है लेकिन मेरे आवेदन में एक मूल्य स्टोर करता है। बेशक हम सभी जानते हैं कि यह सबसे अच्छा तरीका नहीं है लेकिन यह मेरे लिए काम करता है।

/**
 * @param input
 * @return decoded string
 */
public static String decode(String input) {
    // Receiving side
    String text = "";
    try {
        byte[] data = Decoder.decode(input);
        text = new String(data, "UTF-8");
        return text;
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    }
    return "Error";
}

विघटित संस्करण:

 public static String a(String paramString)
  {
    try
    {
      str = new String(a.a(paramString), "UTF-8");
      return str;
    }
    catch (UnsupportedEncodingException localUnsupportedEncodingException)
    {
      while (true)
      {
        localUnsupportedEncodingException.printStackTrace();
        String str = "Error";
      }
    }
  }

और आप Google में थोड़ी सी खोज के साथ इतने सारे एन्क्रिप्टर कक्षाएं पा सकते हैं।


गुप्त रूप से firebase database में रखें और ऐप शुरू होने पर इससे प्राप्त करें, यह वेब सेवा को कॉल करने से कहीं बेहतर है।


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

इसलिए जब तक कोई उपयोगकर्ता पिन या वाक्यांश में प्रवेश नहीं करता है, तब तक कुंजी को छिपाने का कोई तरीका नहीं है। लेकिन ऐसा करने के लिए आपको बैंड से होने वाले पिन प्रबंधित करने की योजना बनाना होगा, जिसका अर्थ है एक अलग चैनल के माध्यम से। Google एपीआई जैसी सेवाओं के लिए कुंजी सुरक्षित करने के लिए निश्चित रूप से व्यावहारिक नहीं है।





api-key