आँकड़ों और विज्ञापन के लिए कुकीज़
हम आँकड़ों और विज्ञापन के लिए कुकीज़ इस्तेमाल करते हैं, दोनों Google को जाती हैं। मना करने से आपको दिखने वाली किसी चीज़ में कोई फ़र्क़ नहीं पड़ता।निजता पेज पढ़ें
कुछ लिखिए या चिपकाइए और टाइप करते-करते MD5 सामने आ जाएगा। शुरू में ही कह देना ठीक है: सुरक्षा से जुड़ी हर बात के लिए MD5 टूटा हुआ है, और आकस्मिक ख़राबी पकड़ने वाले checksum के तौर पर या cache key के तौर पर वह आज भी ठीक है। यह पन्ना उसे इसलिए निकालता है कि उसकी ज़रूरत के जायज़ कारण मौजूद हैं, और यह भी बताता है कि कौन-से कारण जायज़ नहीं हैं।
कहाँ चलता है
कुछ भी अपलोड नहीं होता, क्योंकि कोई फ़ाइल है ही नहीं — गणना इसी पन्ने में होती है।
न कतार, न खाता
यह उतनी ही तेज़ी से जवाब देता है जितनी आपकी मशीन देती है, और कभी नहीं पूछता कि आप कौन हैं।
जितनी बार चाहें
न कुछ गिना जाता है, न कोई सीमा है — दोबारा जवाब देने में हमारा कुछ ख़र्च नहीं होता।
टूटा हुआ होने का मतलब है कि एक ही hash वाले दो अलग इनपुट गढ़े जा सकते हैं, और सिद्धांत में नहीं: एक लैपटॉप पर, कुछ सेकंड में। इससे हर वह इस्तेमाल ख़त्म हो जाता है जिसमें hash यह कहने के लिए है कि सामग्री बदली नहीं — हस्ताक्षर, प्रमाणपत्र, और ऐसी integrity जाँच जिसके सामने कोई ऐसा हो जो मूल को बदल सकता है।
इसका मतलब यह नहीं है कि hash को उलटा जा सकता है। मान से मूल टेक्स्ट वापस पाने का कोई व्यावहारिक तरीक़ा आज भी नहीं है, और इसीलिए MD5 का एक ईमानदार इस्तेमाल बचा हुआ है: आकस्मिक ख़राबी पकड़ना, जिसके पीछे कोई विरोधी नहीं होता। कॉपी होते समय बिगड़ी फ़ाइल अपना hash चुनकर नहीं बिगड़ती।
ठीक उसी वजह से जो इसकी ख़ूबी है: यह बेहद तेज़ है। एक साधारण ग्राफ़िक्स कार्ड MD5 के सामने प्रति सेकंड अरबों उम्मीदवार आज़मा लेता है, इसलिए इससे hash की गई पासवर्ड की तालिका घंटों में टूट जाती है, और आम पासवर्ड सेकंडों में।
Salt जोड़ना पहले से बनी तालिकाओं के ख़िलाफ़ मदद करता है, रफ़्तार के ख़िलाफ़ नहीं। पासवर्ड के लिए ऐसा algorithm चाहिए जो जान-बूझकर धीमा और स्मृति-महँगा हो — bcrypt, scrypt या Argon2 —, और वह धीमापन दुष्प्रभाव नहीं बल्कि उद्देश्य है। अगर आप यह पन्ना किसी उपयोक्ता-तालिका के चलते देख रहे हैं, तो जवाब कहीं और है।
Cache key के तौर पर यह उपयुक्त है: चाहिए इतना कि एक जैसे इनपुट एक जैसे मान दें और अलग इनपुट लगभग कभी न टकराएँ, और दोनों बातें यह पूरी करता है। जो तेज़ी उसे पासवर्ड के लिए अयोग्य बनाती है, वही यहाँ फ़ायदा है।
यह उन पुराने इंटरफ़ेसों में भी बना हुआ है जो इसी की माँग करते हैं, और उन परियोजनाओं की डाउनलोड-जाँच में जो बीस साल से अपना MD5 प्रकाशित करती आ रही हैं। उस आख़िरी हालत में यह ऐसे mirror से बचाता है जिसने अधूरी फ़ाइल परोस दी, किसी बदनीयत mirror से नहीं — और यही फ़र्क़ लगभग कभी साफ़-साफ़ नहीं कहा जाता।
MD5 128 बिट का होता है, जो 32 hexadecimal अंकों में लिखा जाता है। लंबाई हमेशा वही रहती है, चाहे इनपुट एक अक्षर हो या पूरी किताब, क्योंकि hash परिभाषा से ही तय आकार में सार निकालता है।
इससे एक तेज़ और काम की जाँच निकलती है: जिसे कोई MD5 कह रहा है और वह 32 अक्षरों का नहीं है, वह MD5 नहीं है। चालीस SHA-1 होते हैं और चौंसठ SHA-256। यह लेबल की ग़लती लगने से कहीं ज़्यादा बार होती है, ख़ासकर विरासत में मिले दस्तावेज़ों में।
लगभग हर एडिटर और Unix का हर औज़ार फ़ाइल के आख़िर में एक पंक्ति-विच्छेद लिखता है — POSIX टेक्स्ट की पंक्ति को ऐसी चीज़ मानता है जो उसी पर ख़त्म हो। ब्राउज़र का टेक्स्ट खाना ऐसा नहीं करता। इसीलिए एक शब्द वाली फ़ाइल का MD5 यहाँ लिखे उसी शब्द के MD5 से मेल नहीं खाता।
दो «एक ही सामग्री» के hash न मिलने की यह दूसरी सबसे आम वजह है, और ख़ास तौर पर भारी इसलिए है कि दोनों तरफ़ सब कुछ ज़ाहिरा तौर पर सही दिखता है। जो `md5sum` से मिलान कर रहा है उसे उस एक बाइट का हिसाब रखना होगा, या फिर सामग्री के बजाय फ़ाइल के साथ काम करना होगा।
Hash बाइट पर निकलता है, और यहाँ टेक्स्ट UTF-8 में बाइट बनता है। देवनागरी का हर अक्षर और हर मात्रा तीन बाइट लेती है, इसलिए हिंदी टेक्स्ट में बाइट अक्षरों से तीन गुनी होती हैं और hash उन्हीं ठोस बाइट को दर्शाता है।
अगर कोई दूसरा औज़ार दिखने में एक ही टेक्स्ट के लिए अलग मान देता है, तो encoding पहली जगह है जहाँ देखना चाहिए। भारतीय डेटा में इसका सबसे आम रूप Latin-1 नहीं बल्कि Kruti Dev या Chanakya जैसी फ़ॉन्ट-आधारित सामग्री है: वहाँ बाइट असल में ASCII हैं और देवनागरी सिर्फ़ फ़ॉन्ट के कारण दिखती है, इसलिए उसका hash किसी भी Unicode रूपांतरण से कभी मेल नहीं खाएगा। दोनों में से कोई कार्यक्रम ग़लत नहीं है — वे अलग टेक्स्ट hash कर रहे हैं।
नुक़्ते वाले अक्षर Unicode में दो तरह से लिखे जा सकते हैं। «क़» या तो एक ही code point U+0958 है, या क (U+0915) और नुक़्ता (U+093C) का जोड़ा। स्क्रीन पर दोनों एक जैसे हैं, बाइट अलग हैं, और इसलिए hash भी अलग है — बिना किसी दिखने वाले संकेत के।
यहाँ Unicode का सामान्यीकरण उलटा चलता है: NFC इन अक्षरों को जोड़ता नहीं बल्कि तोड़ता है, क्योंकि U+0958 से U+095F तक वाले रूप composition exclusion सूची में हैं। यानी सामान्यीकृत रूप दो code point वाला जोड़ा है, न कि एकल अक्षर। जो तंत्र hash से मिलान करता है उसे hash करने से पहले सामान्यीकरण करना चाहिए, वरना एक ही नाम कभी-कभी मिलेगा और कभी-कभी नहीं।
इस साइट पर checksum निकालने का अलग पन्ना है और वह फ़ाइल लेता है। दोनों जान-बूझकर अलग हैं क्योंकि वे अलग सवालों के जवाब हैं: वह पूछता है «क्या यह डाउनलोड पूरी आई है?», और यह पूछता है «इस मान का hash क्या है?»।
जोड़ देने पर उसके सामने खींचकर छोड़ने का खाना आ जाता जो एक स्ट्रिंग लिखना चाहता है, और टेक्स्ट का खाना उसके सामने जिसके पास फ़ाइल है, और दोनों के लिए आधा इंटरफ़ेस फ़ालतू होता। Algorithm एक ही है; सवाल एक नहीं।
Cache key को दो गुण चाहिए: एक जैसे इनपुट एक ही मान दें, और अलग इनपुट लगभग कभी न टकराएँ। MD5 में दोनों हैं, और उसकी तेज़ी — जो उसे पासवर्ड के लिए अयोग्य बनाती है — ठीक यहाँ उपयुक्त है।
यह तभी हमले लायक़ बनता है जब किसी को इससे कुछ मिलता हो कि दो अलग रिक्वेस्ट एक ही key पर गिरें, जैसे कैश में रखा किसी और का जवाब पा लेना। जहाँ key उपयोक्ता के भेजे डेटा से बनती हो और कैश सत्रों के बीच साझा हो, वहाँ यह सोचने लायक़ है; जहाँ वह आंतरिक पैरामीटरों से बनती हो, वहाँ नहीं।
MD5 उस पुराने ढाँचे पर बना है जिसमें संदेश टुकड़ों में पढ़ा जाता है और हर टुकड़े के बाद भीतरी अवस्था आगे बढ़ती है, और आख़िरी अवस्था ही नतीजा होती है। इसका मतलब यह है कि किसी के पास `hash(कुंजी + संदेश)` का मान हो तो वह उसी अवस्था से आगे चलकर संदेश के पीछे कुछ और जोड़कर सही hash निकाल सकता है — बिना कुंजी जाने।
यह length extension कहलाता है और यही वजह है कि हाथ से बनाया गया ऐसा MAC टूटा हुआ है, भले hash ख़ुद टकराव-मुक्त होता। यही कमज़ोरी SHA-1 और SHA-256 में भी है, क्योंकि ढाँचा वही है। सही जवाब HMAC है, जो कुंजी को दो बार अलग-अलग तरीक़े से मिलाता है और ठीक इसी हमले को बंद करता है।
ऐसे खाने में आम तौर पर वही मान चिपकता है जिसे हिलना नहीं चाहिए: किसी पंक्ति का कोई डेटा जिसे debug किया जा रहा है, कोई पासवर्ड-उम्मीदवार जिसे मिलाना है, कोई पहचान-संख्या। चूँकि गणना पन्ने पर होती है, उसमें से कुछ भी हम तक नहीं पहुँचता।
साथ ही यह याद रखना ज़रूरी है कि निजी डेटा का hash व्यवहार में निजी डेटा ही रहता है, जब संभव इनपुट का दायरा छोटा हो: किसी ईमेल पते या किसी मोबाइल नंबर का MD5 उम्मीदवार आज़माकर तोड़ लिया जाता है, और दस अंकों के भारतीय मोबाइल नंबरों का पूरा दायरा एक साधारण मशीन पर मिनटों में छाना जा सकता है। Hash करने से डेटा अनाम नहीं होता; वह सिर्फ़ सीधे पढ़ना कठिन बनाता है।
सीधे नहीं: यह फलन उलटा नहीं होता। जो होता है वह यह है कि बहुत तेज़ी से उम्मीदवार आज़माए जाते हैं, और इसीलिए किसी आम पासवर्ड का MD5 सार्वजनिक तालिकाओं में पहले से हल पड़ा है।
नहीं। यह बहुत तेज़ है: एक ग्राफ़िक्स कार्ड प्रति सेकंड अरबों उम्मीदवार आज़मा लेता है। पासवर्ड के लिए bcrypt, scrypt या Argon2 चाहिए, जिनका धीमापन दोष नहीं बल्कि उद्देश्य है।
लगभग हमेशा फ़ाइल के आख़िर वाले उस पंक्ति-विच्छेद के कारण जो Unix के औज़ार लिखते हैं और टेक्स्ट का खाना नहीं लिखता। वह अकेली बाइट पूरा hash बदल देती है।
आकस्मिक ख़राबी के ख़िलाफ़ हाँ: अधूरी फ़ाइल अपना hash चुनकर नहीं बिगड़ती। ऐसे किसी के ख़िलाफ़ नहीं जो फ़ाइल और उसका प्रकाशित योग दोनों बदल सके — उसके लिए SHA-256 चाहिए।
नहीं। गणना इसी पन्ने पर होती है। यह भी ध्यान रखिए कि निजी डेटा का hash उस डेटा तक वापस पहुँचाया जा सकता है, अगर संभव मानों का दायरा छोटा हो।