Bytecode Array Encoding कुंजी
vmBytecodeArrayEncodingKey से अपनी खुद की VM बाइटकोड एन्क्रिप्शन कुंजी दें और रनटाइम पर कुंजी-गेटर के ज़रिए उसे वापस सौंपें: बंडल से बाहर रखकर, क्लाइंट स्टोरेज से पढ़कर, या अपने बैकएंड से लाकर।
देखें
Obfuscator.io Async Executor: Async Bytecode Key Getter and Async-Only VM Virtualization
Obfuscator.io Custom Bytecode Key: Compile-Time Key and Runtime Key Getter (Cookie, Fetch, Decoy Key)
ये विकल्प क्या करते हैं
vmBytecodeArrayEncoding VM बाइटकोड ऐरे को एन्क्रिप्ट करता है, ताकि वह
आउटपुट में सादे टेक्स्ट के रूप में न पड़ा रहे। डिफ़ॉल्ट रूप से एन्क्रिप्शन कुंजी वातावरण से व्युत्पन्न होती है और क्लाइंट पर
दोबारा बनाई जाती है, इसलिए आपको उसे कभी संभालना नहीं पड़ता। यह सुविधाजनक है, लेकिन कुंजी की सामग्री फिर भी बंडल में ही रहती है।
दो विकल्प आपको कुंजी को बंडल से बाहर निकालने और उसे खुद नियंत्रित करने देते हैं:
vmBytecodeArrayEncodingKey: वह कुंजी जो आप कंपाइल के समय देते हैं। सेट होने पर डिफ़ॉल्ट, वातावरण से व्युत्पन्न कुंजी की जगह इसका उपयोग होता है, और यह ऑब्फ़स्केटेड आउटपुट में एम्बेड नहीं की जाती।vmBytecodeArrayEncodingKeyGetter: एक JavaScript एक्सप्रेशन जो रनटाइम पर वही कुंजी लौटाता है। यह ज्यों का त्यों एम्बेड होता है और ऑब्फ़स्केटेड कोड लोड होने पर ब्राउज़र में मूल्यांकित होता है।
असली बात अलगाव की है: चूँकि कुंजी कोड में नहीं है, बंडल का केवल स्टैटिक स्कैन उसे वापस नहीं पा सकता। कोड चलने के लिए रनटाइम पर कुंजी का मौजूद होना फिर भी ज़रूरी है, इसलिए वह सचमुच गुप्त नहीं है, लेकिन यह आप तय करते हैं कि वह कहाँ से आए और उसे कौन देख सके।
ये दोनों विकल्प एक जोड़ी हैं, और ऑब्फ़स्केटर इसे लागू करता है: एक को दूसरे के बिना सेट करना बिल्ड के समय की वैलिडेशन एरर है
(अकेले vmBytecodeArrayEncodingKey के पास रनटाइम पर कुंजी पाने का कोई रास्ता नहीं होता; अकेले गेटर के पास मिलान करने के लिए
कोई कंपाइल-टाइम कुंजी नहीं होती)। ये तब तक कुछ नहीं करते जब तक बाइटकोड ऐरे वास्तव में एन्क्रिप्ट न हो रहा हो, इसलिए
vmBytecodeArrayEncoding: true भी चालू होना चाहिए - या vmSelfDefending: true, जो आंतरिक रूप से vmBytecodeArrayEncoding
को चालू कर देता है। दोनों कुंजियों को इनमें से किसी एक के साथ सेट करें।
दोनों कुंजियाँ कैसे मिलती हैं
आपकी कुंजी कभी अकेले इस्तेमाल नहीं होती। दोनों तरफ़ वह ऑब्फ़स्केटर द्वारा नियंत्रित एक आंतरिक कुंजी के साथ मिलाई जाती है:
- कंपाइल के समय।
vmBytecodeArrayEncodingKeyको ऑब्फ़स्केटर द्वारा व्युत्पन्न आंतरिक कुंजी के साथ जोड़ा जाता है, और बाइटकोड ऐरे को इससे बनी मिश्रित कुंजी से एन्कोड किया जाता है। - रनटाइम पर। आपका
vmBytecodeArrayEncodingKeyGetterजिस मान पर हल होता है, उसे उसी आंतरिक कुंजी के साथ जोड़ा जाता है, जो क्लाइंट पर कई रनटाइम कारकों से दोबारा बनाई जाती है, और फिर बाइटकोड डिकोड होता है।
चूँकि दोनों तरफ़ आपकी कुंजी आंतरिक कुंजी के साथ मिलाई जाती है, गेटर को ठीक वही स्ट्रिंग लौटानी चाहिए जो आपने
vmBytecodeArrayEncodingKey के रूप में दी थी। कोई भी हिस्सा अकेले पर्याप्त नहीं है: आंतरिक कुंजी के बिना आपकी कुंजी बाइटकोड
डिकोड नहीं कर सकती, और आपकी कुंजी के बिना आंतरिक कुंजी बेकार है। इसीलिए यह नियंत्रित करना कि आपकी कुंजी किसे मिले, वही चीज़ है
जो असल में कोड की रक्षा करती है।
रनटाइम पर कुंजी देना
डिफ़ॉल्ट रूप से गेटर सिंक्रोनस होता है: ऑब्फ़स्केटेड कोड लोड होते ही एक्सप्रेशन को तुरंत कुंजी लौटानी होती है। इसे
किसी भी ऐसे स्रोत से पढ़ें जो क्लाइंट पर पहले से मौजूद हो: कुकी, localStorage, कोई ग्लोबल वेरिएबल, या सर्वर द्वारा
डाला गया कोई DOM एलिमेंट।
ऑब्फ़स्केटेड कोड चलने से पहले कुंजी मौजूद होनी चाहिए:
दूसरे सिंक्रोनस स्रोत भी इसी तरह काम करते हैं। जिसे आपका ऐप पहले से भरता हो, उसे चुनें:
कुंजी को ऑब्फ़स्केटेड कोड वाली फ़ाइल या स्क्रिप्ट में न रखें। उसे वहीं इनलाइन करने से पूरा उद्देश्य ही खत्म हो जाता है:
बंडल का स्टैटिक स्कैन कोड और उसकी कुंजी दोनों पा लेगा। इसे किसी अलग स्रोत में रखें, और कंपाइल-टाइम
vmBytecodeArrayEncodingKey को कमिट करने के बजाय किसी एनवायरनमेंट वेरिएबल या सीक्रेट से डालें।
अपने बैकएंड से कुंजी लाना (async)
vmAsyncExecutor ज़रूरी · v7.3.0+सिंक्रोनस गेटर केवल वही पढ़ सकता है जो क्लाइंट पर पहले से मौजूद है। कुंजी को अपने सर्वर से लाने के लिए, ताकि आप उसे
ऑथेंटिकेशन के पीछे रख सकें और रद्द कर सकें, गेटर का एसिंक्रोनस होना ज़रूरी है, और इसके लिए
vmAsyncExecutor चाहिए। Async Executor चालू होने पर गेटर एक
Promise लौटा सकता है, और VM चलने से पहले उसके पूरा होने की प्रतीक्षा करता है।
vmAsyncExecutor चालू करने से यह भी सीमित हो जाता है कि क्या वर्चुअलाइज़ होता है: इस मोड में केवल सबसे बाहरी async फ़ंक्शन्स
VM में कंपाइल होते हैं, और सिंक्रोनस कोड वर्चुअलाइज़ नहीं होता (बाकी ऑब्फ़स्केशन फिर भी लागू होता है)। अगर आपका प्रोग्राम ज़्यादातर सिंक्रोनस है, तो जिस कोड को
सुरक्षित करना है उसे किसी async फ़ंक्शन में रैप करें ताकि उसे फिर भी कवरेज मिले - पूरे नियम के लिए
vmAsyncExecutor देखें।
Promise लौटाने वाले गेटर के लिए vmAsyncExecutor ज़रूरी है। बिल्ड के समय इसकी जाँच नहीं हो सकती, इसलिए
vmAsyncExecutor बंद होने पर Promise गेटर रनटाइम पर विफल होता है।
सर्वर पर, कौन-सी कुंजी लौटानी है यह उस आधार पर तय करें जिस पर आपका एप्लिकेशन भरोसा करता है: सत्यापित सेशन, लाइसेंस जाँच,
इत्यादि। केवल Origin या Referer किसी कॉलर को प्रमाणित नहीं करते, और same-origin GET अनुरोध में
Origin छूट सकता है। खास तरकीब यह है: अविश्वसनीय कॉलर को अस्वीकार करने के बजाय एक गलत कुंजी लौटाएँ (नीचे
VM_DECOY_KEY)। तब सुरक्षित कोड अपने आप विफल हो जाता है (एरर, गलत नतीजे, या ऐसा पेज जो प्रतिक्रिया देना बंद कर देता है), जो किसी स्पष्ट 401
से ज़्यादा छिपा हुआ तरीका है, क्योंकि 401 हमलावर को ठीक-ठीक बता देता है कि किसे बायपास करना है।
रिस्पॉन्स कैशिंग बंद करें, ताकि एक कॉलर की कुंजी कभी किसी दूसरे को न परोसी जाए। कुंजियों को सही बिल्ड संस्करण से बाँधें और कुंजियाँ व बंडल एक साथ डिप्लॉय करें। जिस क्लाइंट को असली कुंजी मिलती है, वह रनटाइम पर उसे फिर भी देख सकता है।
इस एंडपॉइंट से ठीक वही स्ट्रिंग परोसें जो आपने बिल्ड के समय vmBytecodeArrayEncodingKey के रूप में दी थी। ऊपर
वाला गेटर एक रिलेटिव URL (/api/vm-key) लाता है, इसलिए किसी दूसरे origin पर होस्ट की गई बंडल की कॉपी /api/vm-key
उसी origin से माँगती है, और उसे आपकी कुंजी कभी नहीं मिलती; डिकॉय कुंजी वह है जो किसी कॉलर को तब मिलती है जब वह आपके एंडपॉइंट तक पहुँचता है
लेकिन भरोसेमंद सेशन के बिना (बिना ऑथेंटिकेशन वाला अनुरोध, आपके origin के ज़रिए प्रॉक्सी किया गया चोरी का बंडल)। दोनों ही
स्थितियों में असली कुंजी कभी नहीं पहुँचती और सुरक्षित कोड नहीं चलता।
"वैध" क्या माना जाए, यह पूरी तरह एप्लिकेशन पर निर्भर है: प्रमाणित सेशन, हस्ताक्षरित लाइसेंस, या इनका कोई भी संयोजन।
कुंजी जो भी बनाए, उसे एक Promise में लपेटें और Async Executor VM चलाने से पहले उसकी प्रतीक्षा करेगा।
जब कुंजी मेल नहीं खाती
ऑब्फ़स्केटेड कोड तभी काम करता है जब गेटर ठीक वही कुंजी लौटाए जो ऑब्फ़स्केशन के दौरान इस्तेमाल हुई थी। अगर कुंजियाँ
अलग हों, या गेटर undefined, null या खाली स्ट्रिंग लौटाए, तो कोड रनटाइम पर विफल हो जाता है: वह गलत
नतीजे देता है, कोई सामान्य रनटाइम एरर फेंकता है, या प्रतिक्रिया देना बंद कर देता है।
जानबूझकर कोई अलग, कुंजी-विशिष्ट एरर संदेश नहीं है: गलत कुंजी किसी भी दूसरी रनटाइम खराबी से अलग पहचानी नहीं जा सकती। इसलिए जब कोई VM-सुरक्षित बंडल केवल इस विकल्प के लागू होने पर ही एरर फेंके, गलत नतीजे दे या अटक जाए, तो सबसे पहले कुंजी का रास्ता जाँचें: कि गेटर पेज पर हल होता है, खाली न होने वाली स्ट्रिंग लौटाता है, और वही मान लौटाता है जिससे आपने बिल्ड किया था।
