एन्कोडिंग, हैशिंग और एन्क्रिप्शन तीन अलग चीज़ें हैं
इस पेज से जुड़ी लगभग हर ग़लतफ़हमी इन्हें एक-दूसरे की जगह इस्तेमाल होने लायक मान लेने से आती है, इसलिए इन्हें ठीक से अलग करके समझना फ़ायदेमंद है।
एन्कोडिंग उलटी जा सकती है और उसमें कोई सीक्रेट नहीं होता। Base64 इसलिए है ताकि बाइनरी डेटा उन रास्तों से जा सके जो सिर्फ़ टेक्स्ट लेते हैं — ईमेल अटैचमेंट, data URI, JSON स्ट्रिंग — हर तीन बाइट को चार कैरेक्टर के रूप में लिखकर, इसीलिए नतीजा हमेशा लगभग एक-तिहाई बड़ा होता है। कोई की नहीं होती। जो भी स्ट्रिंग देखता है, वह एक ही क़दम में उसे डिकोड कर सकता है, इस साइट पर भी। Base64 सुरक्षा नहीं है, ढंग का छिपाव भी नहीं है, और देखने वाले किसी से भी कुछ छिपाने का तरीक़ा नहीं है। पर्सेंट-एन्कोडिंग URL के लिए इसी तरह की चीज़ है, और वहीं दूसरा आम बग रहता है: क्वेरी स्ट्रिंग में जाने वाली एक वैल्यू को एन्कोड करना पूरे बने हुए URL को साफ़ करने से अलग काम है, क्योंकि सिर्फ़ पहला ही उन &, =, ? और / को एस्केप करता है जो URL को उसकी बनावट देते हैं। यह ग़लत हुआ, तो “Smith & Sons” सर्वर तक एक वैल्यू की जगह दो पैरामीटर बनकर पहुंचता है।
हैशिंग एकतरफ़ा है और उसमें भी कोई की नहीं होती। हैश किसी भी इनपुट से एक तय लंबाई का फ़िंगरप्रिंट बनाता है, और इसे उलटा नहीं जा सकता — इसलिए नहीं कि वह एन्क्रिप्टेड है, बल्कि इसलिए कि जानकारी ख़त्म हो चुकी है। आप बस इनपुट का अंदाज़ा लगाकर मिला सकते हैं, और ठीक यही बात MD5, SHA-1 और SHA-256 को पासवर्ड स्टोर करने के लिए ग़लत बनाती है: वे तेज़ हैं, एक ग्राफ़िक्स कार्ड हर सेकंड अरबों हैश निकाल लेता है, और उनकी चोरी हुई टेबल इसी रफ़्तार से क्रैक होती है। पासवर्ड के लिए जान-बूझकर धीमा, सॉल्ट वाला फ़ंक्शन चाहिए — bcrypt, scrypt या Argon2। इससे अलग, MD5 और SHA-1 एक और वजह से टूटे हुए हैं: अब एक ही हैश वाली दो अलग फ़ाइलें जान-बूझकर बनाई जा सकती हैं, इसलिए दोनों में से कोई यह साबित नहीं कर सकता कि फ़ाइल वही है जिसकी आपको उम्मीद थी, हालांकि ग़लती से ख़राब हुए डाउनलोड को पकड़ने के लिए दोनों अब भी ठीक हैं।
एन्क्रिप्शन ही वह है जिसमें की होती है, और इनमें से कोई भी टूल यह नहीं करता। यह कोई चूक नहीं है। एन्क्रिप्शन ठीक से करने के लिए की मैनेजमेंट चाहिए, और वेब पेज किसी की के लिए ग़लत जगह है।
JWT साइन किया जाता है, एन्क्रिप्ट नहीं, और लोग इसमें लगातार फंसते हैं। टोकन का हेडर और पेलोड Base64URL होता है — जिसके पास भी टोकन है, वह इसे बिना किसी की के पढ़ सकता है। सिग्नेचर किसी को टोकन बदलने से रोकता है; उसे पढ़ने से रोकने के लिए कुछ नहीं करता, इसलिए पेलोड में कुछ भी गोपनीय नहीं होना चाहिए। इसका मतलब यह भी है कि टोकन डिकोड करने से उसके बारे में कुछ भी साबित नहीं होता: कोई भी अपनी मर्ज़ी के क्लेम लिखकर उन्हें Base64 कर सकता है। वेरिफ़ाई करने का मतलब है जारी करने वाले की की से सिग्नेचर दोबारा निकालना, जो आपका सर्वर करता है और जिसके लिए किसी वेबसाइट को कभी नहीं पूछना चाहिए। इसलिए हमारा डिकोडर वेरिफ़िकेशन का आभास देने से इनकार करता है, और उन हालात को चिह्नित करता है जो किसी समस्या का इशारा हैं — एक्सपायर हो चुका टोकन, बिना किसी एक्सपायरी वाला टोकन, और “none” एल्गोरिदम, जो कोई अजूबा नहीं, बल्कि दर्ज किया हुआ ऑथेंटिकेशन बायपास है।
JSON में नंबर की सटीकता की एक सीमा है, जिसमें ज़्यादातर फ़ॉर्मैटर चुपचाप फंस जाते हैं। JSON ख़ुद किसी नंबर के साइज़ पर कोई सीमा नहीं लगाता, लेकिन JavaScript का नंबर 64-बिट फ़्लोट होता है, इसलिए पूर्ण संख्याएं सिर्फ़ 9,007,199,254,740,991 तक ही सटीक रहती हैं। Twitter पोस्ट ID, Discord snowflake, 64-बिट डेटाबेस की या बैंक अकाउंट नंबर इससे बड़ा होता है, और इसे आम एक-लाइन फ़ॉर्मैटर — parse, फिर stringify — से गुज़ारने पर इसके आख़िरी अंक बदल जाते हैं। नतीजा फिर भी एक सही-सा नंबर दिखता है, और यही इसे ख़तरनाक बनाता है: 7205759403792793600 चुपचाप 7205759403792793000 बन जाता है। हमारे JSON टूल्स ठीक वही अंक दोबारा लिखते हैं जो आपने पेस्ट किए थे, और बताते हैं कि उन्हें कितने नंबर बचाने पड़े।
UUID का वर्शन बताता है कि वह कैसे बना, यह नहीं कि वह क्या गारंटी देता है। कोई UUID को रजिस्टर नहीं करता और न ही यूनीक होना लागू करता है; यूनीक होना संभावना पर टिका है, और वर्शन बताता है कि बिट्स कहां से आए। वर्शन 4 में ब्राउज़र के क्रिप्टोग्राफ़िक जनरेटर से 122 बिट की रैंडमनेस होती है, जिससे उसका अंदाज़ा नहीं लगाया जा सकता और इसलिए वह रीसेट लिंक, इनवाइट कोड और किसी भी सीक्रेट चीज़ के लिए सही है — और डेटाबेस की के लिए ग़लत, क्योंकि रैंडम की सॉर्ट किए गए इंडेक्स में बिखर जाती हैं और उसे टुकड़ों में बांट देती हैं। वर्शन 7 सबसे पहले 48-बिट मिलीसेकंड टाइमस्टैम्प रखता है, इसलिए की ऑटो-इन्क्रीमेंट होने वाले इंटीजर की तरह इंडेक्स के आख़िर में जुड़ती हैं और फिर भी दुनिया भर में यूनीक रहती हैं। बदले में, v7 UUID जिसके भी पास है उसे साफ़ बता देता है कि वह कब बना था, मिलीसेकंड तक।
कहां ब्राउज़र सचमुच सही टूल नहीं है
इन तेरह में से कोई भी कुछ भी कहीं नहीं भेजता। कोई रिक्वेस्ट नहीं होती, कुछ लॉग नहीं होता, और नेटवर्क डिस्कनेक्ट होने पर भी पेज काम करते रहते हैं — ठीक इसीलिए इन्हें ग्राहकों के रिकॉर्ड से भरे API रिस्पॉन्स या ऐसे टोकन पर इस्तेमाल किया जा सकता है जिसे आप किसी को ईमेल नहीं करेंगे। यह इनके पक्ष में ईमानदार दलील है। और यह रही इनके ख़िलाफ़ ईमानदार दलील।
किसी चालू प्रोडक्शन सीक्रेट को वेब पेज में पेस्ट करना ऐसी आदत है जो न ही हो तो अच्छा — इस पेज में भी। प्राइवेसी का हमारा दावा सच है, लेकिन आपको दावा नहीं बचाता; कोड का बर्ताव बचाता है, और किसी भी वेब पेज के प्रति इकलौता समझदार रवैया भरोसा करने के बजाय जांचना है। जांच में कुछ ख़र्च नहीं होता: पेज लोड होने के बाद इंटरनेट डिस्कनेक्ट करें और देखें कि ये टूल काम करते रहते हैं। जिस टूल को सर्वर चाहिए होता, वह रुक जाता। और अगर कोई क्रेडेंशियल अब भी वैध है और आप उसे पहले ही किसी ऐसी जगह पेस्ट कर चुके हैं जिसकी आप जांच नहीं कर सकते, तो सही क़दम उसे रोटेट करना है, उस पर सोच-विचार करना नहीं। जो टोकन अभी चालू है, उसे लोकल तौर पर डिकोड करना — आपकी भाषा का अपना Base64 फ़ंक्शन, या शेल में दो लाइनें — किसी भी वेबसाइट से बेहतर तरीक़ा है, हमारी वेबसाइट समेत।
स्कीमा वैलिडेशन। हमारे JSON और XML टूल्स जांचते हैं कि डॉक्यूमेंट सही बना है या नहीं, जो इस सवाल से अलग है कि वह किसी स्कीमा से मेल खाता है या नहीं। JSON Schema या XSD के मुक़ाबले वैलिडेट करने का मतलब है स्कीमा फ़ाइल लाना और लागू करना, जो एक नेटवर्क रिक्वेस्ट है और ये पेज जान-बूझकर कभी नहीं करते। JSON Schema के लिए ajv और XSD व DTD के लिए xmllint इस्तेमाल करें; दोनों मुफ़्त हैं और दोनों यह काम किसी वेब पेज से बेहतर करते हैं।
कुछ भी सचमुच बड़ा, या स्ट्रीम होने वाला। डॉक्यूमेंट पूरे के पूरे मेमोरी में रखे जाते हैं, फ़ॉर्मैट करते समय कभी-कभी दो बार, इसलिए सीमा टैब है। कुछ मेगाबाइट तुरंत हो जाते हैं, कुछ सौ नहीं। jq कई गीगाबाइट की ऐसी JSON फ़ाइल स्ट्रीम कर लेता है जिसे कोई ब्राउज़र नहीं खोलेगा, और ripgrep पूरी रिपॉज़िटरी को उससे तेज़ खोज लेता है जितनी देर में आप एक फ़ाइल पेस्ट करें। हैशिंग में यही सीमा और तीखी है: ब्राउज़र की क्रिप्टोग्राफ़ी में इन्क्रीमेंटल डाइजेस्ट नहीं होता, इसलिए पूरी फ़ाइल एक साथ मेमोरी में समानी चाहिए — DVD इमेज फ़ेल हो जाएगी, जबकि sha256sum, shasum या certutil उसे बिना किसी दिक़्क़त के स्ट्रीम कर लेते हैं।
ऑटोमेशन और CI। ये तभी चलते हैं जब कोई व्यक्ति क्लिक करता है। किसी रिपॉज़िटरी की हर फ़ाइल फ़ॉर्मैट करना, किसी फ़िक्स्चर के लिए दस हज़ार UUID बनाना, या पाइपलाइन में JSON जांचना स्क्रिप्ट का काम है: jq, xmllint, uuidgen, openssl और base64 कमांड ज़्यादातर मशीनों पर पहले से इंस्टॉल होते हैं।
साइन की गई किसी भी चीज़ को वेरिफ़ाई करना। सिग्नेचर वेरिफ़िकेशन, सर्टिफ़िकेट चेन और प्राइवेट की की ज़रूरत वाली कोई भी चीज़ आपके सर्वर पर, किसी मेंटेन की जा रही लाइब्रेरी से होनी चाहिए। यह पेज आपको बताएगा कि टोकन क्या दावा करता है; यह कभी नहीं बताएगा कि टोकन असली है, और जो भी साइट आपकी की के बिना ऐसा कर पाने का दावा करे, उस पर भरोसा न करें।
एक जैसे सुनाई देने वाले टूल्स में से कैसे चुनें
JSON फ़ॉर्मैटर बनाम JSON वैलिडेटर। पार्सर वही, सवाल अलग। फ़ॉर्मैटर उस डॉक्यूमेंट को पढ़ने और नया रूप देने के लिए है जो पहले से पार्स होता है — इंडेंट करें, मिनिफ़ाई करें, बड़े नंबर सही-सलामत रखें। वैलिडेटर उस डॉक्यूमेंट के लिए है जो पार्स नहीं होता, और उसका आउटपुट है लाइन, कॉलम, ग़लत कैरेक्टर जिसके नीचे एक कैरेट (^) लगा होता है, और यह कि चार आम वजहों में से कौन-सी थी। अगर आप “Unexpected token” को घूर रहे हैं, तो आपको वैलिडेटर चाहिए। यही बंटवारा “XML फ़ॉर्मैटर” और “XML वैलिडेटर” पर भी लागू होता है।
Base64 डिकोड करें बनाम JWT डिकोडर। JWT तीन Base64URL हिस्सों से बना होता है, इसलिए सामान्य डिकोडर आपको टुकड़े दिखा देगा। JWT पेज उन्हें आपके लिए अलग करता है, JSON को फ़ॉर्मैट करता है, एक्सपायरी, issued-at और not-before क्लेम को Unix टाइमस्टैम्प से आपके टाइमज़ोन की असली तारीख़ों में बदलता है, रजिस्टर्ड क्लेम पर लेबल लगाता है, और एक्सपायरी तथा “none” एल्गोरिदम के बारे में चेतावनी देता है। Base64 के किसी ब्लॉब के लिए सामान्य डिकोडर और टोकन के लिए JWT पेज इस्तेमाल करें।
Base64 एन्कोड करें बनाम URL एन्कोड करें। अलग-अलग काम, जो दोनों “सुरक्षित” टेक्स्ट बनाते हैं। Base64 किसी भी बाइट को 33 प्रतिशत बड़े साइज़ की क़ीमत पर टेक्स्ट में बदलता है, और स्टैंडर्ड Base64 URL में बिल्कुल सुरक्षित नहीं है — उसके +, / और = वहां कुछ और मतलब रखते हैं, इसीलिए Base64URL मौजूद है। पर्सेंट-एन्कोडिंग पढ़ने लायक टेक्स्ट को पढ़ने लायक रहने देती है और सिर्फ़ उसे एस्केप करती है जो URL को तोड़ देता, और सर्च टर्म, ईमेल पते या रीडायरेक्ट टारगेट के लिए आपको यही चाहिए। क्वेरी स्ट्रिंग के लिए पूरी फ़ाइल एन्कोड करना आमतौर पर इस बात का संकेत है कि उसे रिक्वेस्ट बॉडी होना चाहिए था।
हैश जनरेटर बनाम UUID जनरेटर। हैश अपने इनपुट से निकलता है, इसलिए एक ही इनपुट हमेशा एक ही वैल्यू देता है — यही उसे फ़िंगरप्रिंट बनाता है, जो डाउनलोड वेरिफ़ाई करने या एक जैसे कंटेंट के डुप्लिकेट हटाने के लिए अच्छा है। UUID ताज़ा रैंडमनेस है जिसका किसी चीज़ से कोई संबंध नहीं, इसलिए वह कभी दोहराता नहीं। अगर आपको एक ही कंटेंट के लिए एक ही आइडेंटिफ़ायर चाहिए, तो उसका हैश निकालें। अगर नया आइडेंटिफ़ायर चाहिए, तो UUID बनाएं।
QR कोड बनाएं बनाम बारकोड बनाएं। QR एक दो-आयामी ग्रिड है जिसमें कोई भी टेक्स्ट आ सकता है — URL, Wi-Fi क्रेडेंशियल, फ़ोन नंबर — और उसे फ़ोन का कैमरा पढ़ता है। बारकोड पेज रिटेल और लॉजिस्टिक्स वाले एक-आयामी कोड बनाता है: EAN-13, EAN-8, UPC-A, ITF-14, Code 128 और Code 39, रिटेल चेक डिजिट की गणना के साथ, और ग़लत या छोटा नंबर चुपचाप भरकर किसी दूसरे प्रोडक्ट का वैध बारकोड बनाने के बजाय मना कर दिया जाता है।