SHA-1 hash बनाएँ

कुछ लिखिए या चिपकाइए और उसका SHA-1 पाइए: चालीस hexadecimal अक्षर। हस्ताक्षरों और प्रमाणपत्रों के लिए यह 2017 से टूटा हुआ है, और फिर भी रोज़ इसकी ज़रूरत पड़ती है, क्योंकि Git अपने ऑब्जेक्ट इसी से पहचानता है और क्योंकि ऐसे इंटरफ़ेस मौजूद हैं जिन्हें पंद्रह साल से किसी ने छुआ नहीं। यह पन्ना इसी वजह से इसे निकालता है, इसलिए नहीं कि किसी नई चीज़ के लिए यह सुझाने लायक़ विकल्प है।

नतीजा

आप लिखते जाइए, जवाब यहाँ आता जाएगा।

  • कहाँ चलता है

    कुछ भी अपलोड नहीं होता, क्योंकि कोई फ़ाइल है ही नहीं — गणना इसी पन्ने में होती है।

  • न कतार, न खाता

    यह उतनी ही तेज़ी से जवाब देता है जितनी आपकी मशीन देती है, और कभी नहीं पूछता कि आप कौन हैं।

  • जितनी बार चाहें

    न कुछ गिना जाता है, न कोई सीमा है — दोबारा जवाब देने में हमारा कुछ ख़र्च नहीं होता।

काम कैसे करता है

  1. टेक्स्ट खाने में चिपकाइए।
  2. चालीस hexadecimal अक्षर कॉपी कर लीजिए।
  3. कुछ अपलोड नहीं हुआ है।

2017 में टूटा ठीक-ठीक क्या था

Google और ऐम्स्टर्डम के CWI ने एक ही SHA-1 वाले दो अलग PDF प्रकाशित किए। इसमें समांतर चलती लगभग 6,500 CPU-वर्ष की गणना लगी थी, और तब से क़ीमत लगातार गिरी है: आज यह किराए पर ली गई गणना-शक्ति के कुछ दसियों लाख रुपयों का मामला है।

इससे वह क्षमता ख़त्म होती है जो कहती है कि सामग्री बदली नहीं, उस व्यक्ति के सामने जो दूसरी सामग्री गढ़ सकता है। हस्ताक्षर, प्रमाणपत्र और विरोधी वाली integrity जाँच इस दायरे से बाहर हो जाते हैं। जो ख़त्म नहीं होती वह preimage के प्रति प्रतिरोध है: मान से मूल टेक्स्ट वापस पाने का व्यावहारिक तरीक़ा आज भी नहीं है।

Git आज भी इसे क्यों इस्तेमाल करता है

Git के ऑब्जेक्ट की पहचान एक SHA-1 है, और उसे बदलने का मतलब है दुनिया भर के repository का प्रारूप एक साथ बदलना। SHA-256 की ओर संक्रमण विनिर्दिष्ट है और सालों से चल रहा है, और ठीक इसी कारण धीरे चल रहा है।

इस बीच Git टकराव की पहचान करता है, जो ज्ञात हमले के ढाँचे को पहचानकर ऐसे ऑब्जेक्ट मना कर देती है। इससे SHA-1 सुरक्षित नहीं हो जाता; वह उस एक रास्ते को बंद करती है जो प्रदर्शित हुआ था। यह काफ़ी है या नहीं, यह इस पर निर्भर है कि आपके repository में सामग्री डाल पाने वाला कोई है या नहीं।

टूटी हुई योजना में पैबंद नहीं लगता

यह विचार नियमित रूप से लौटता है कि SHA-1 दो बार लगा दिया जाए, उसमें salt मिला दिया जाए या दो algorithm जोड़ दिए जाएँ। इनमें से कुछ भी टकराव की कमज़ोरी नहीं सुधारता: जो दो इनपुट पहली बार में मिलते हैं वे दूसरी बार में भी मिलते हैं, क्योंकि दूसरी बार पहली का नतीजा ही देखती है।

टकराव के प्रतिरोध के लिए सिर्फ़ दूसरा algorithm काम आता है। इसके अलावा घर की बनी रचनाओं का विश्लेषण नहीं हुआ होता और वे कभी-कभी अपने हिस्सों से बुरा बर्ताव करती हैं — HMAC के सावधानी से बने डिज़ाइन होने की और महज़ कुंजी तथा संदेश जोड़कर hash कर देने न होने की एक वजह है।

HMAC-SHA1 अब भी क्यों चला आ रहा है

HMAC को टकराव के प्रतिरोध की ज़रूरत नहीं होती, इसलिए HMAC-SHA1 उस अर्थ में टूटा हुआ नहीं है जिसमें SHA-1 वाला हस्ताक्षर टूटा हुआ है। यही वजह है कि वह अब भी चालू तंत्रों में मिलता है: OAuth 1.0a के हस्ताक्षर, कुछ पुराने भुगतान-गेटवे के callback, और TOTP, जिसका डिफ़ॉल्ट RFC 6238 में HMAC-SHA1 ही है — यानी हर वह ऐप जो छह अंकों का OTP दिखाती है।

यह इसे नई चीज़ों के लिए सही चुनाव नहीं बना देता, बस समझा देता है कि उसे हर जगह से हटाने की भागदौड़ क्यों नहीं मची। जो अंतर याद रखने लायक़ है वह यह है: टकराव की कमज़ोरी वहाँ चोट करती है जहाँ hash अकेले खड़े होकर सामग्री की गवाही देता है, वहाँ नहीं जहाँ वह किसी गुप्त कुंजी के भीतर लिपटा हो।

छोटा रूप, और वह कब टकराता है

Git पहचानें छोटी करके दिखाता है, परंपरागत रूप से सात अक्षरों में। वह 28 बिट है, यानी 26,84,35,456 संभावनाएँ, और जन्मदिन-विरोधाभास के चलते टकराव तब संभावित होने लगते हैं जब repository लगभग 16,000 ऑब्जेक्ट के आसपास पहुँचती है। कोई मँझोली परियोजना वहाँ बिना मेहनत पहुँच जाती है।

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

चालीस अक्षर

SHA-1 160 बिट का है और 40 hexadecimal अंकों में लिखा जाता है, लंबाई हमेशा वही। MD5 के 32 और SHA-256 के 64 के साथ मिलकर यह एक नज़र में पहचानने देता है कि सामने कौन-सा मान है।

यह जाँच तब समय बचाती है जब कोई पुराना दस्तावेज़ बस «hash» लिखकर छोड़ देता है। अक्षर गिन लेना बाक़ी दस्तावेज़ पढ़ने से पहले ही सवाल का जवाब दे देता है, और अलग-अलग algorithm से निकले मानों को आपस में मिलाने से बचा लेता है।

Git की ऑब्जेक्ट-पहचान फ़ाइल का hash नहीं है

Git हर ऑब्जेक्ट के आगे उसका प्रकार और उसकी लंबाई लगाता है, बीच में एक शून्य बाइट के साथ, और उसी का hash निकालता है। इसलिए किसी फ़ाइल की शुद्ध सामग्री का SHA-1 उसकी ऑब्जेक्ट-पहचान नहीं होता — और इस नतीजे को अक्सर ग़लती समझ लिया जाता है, जबकि वह ग़लती नहीं है।

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

वही पंक्ति-विच्छेद, एक बार और

बाक़ी दोनों की तरह: Unix का औज़ार फ़ाइल के आख़िर में पंक्ति-विच्छेद लिखता है और टेक्स्ट का खाना नहीं लिखता, इसलिए एक शब्द वाली फ़ाइल का `sha1sum` यहाँ लिखे उसी शब्द के SHA-1 से मेल नहीं खाता।

यह तीनों पन्नों पर दोहराया जाता है क्योंकि दो मानों के न मिलने की यह सबसे आम वजह है, और क्योंकि जो एक पन्ने पर आता है उसने बाक़ी दो शायद ही पढ़े हों। एक अदृश्य बाइट जो पूरा नतीजा बदल देती है, हर बार कहे जाने लायक़ है।

कब इस्तेमाल कीजिए और कब नहीं

इसे तब इस्तेमाल कीजिए जब कोई बाहरी चीज़ इसकी माँग करे और आप उसे बदल न सकते हों: कोई Git पहचान, किसी पुराने तंत्र से जुड़ाव, बीस साल पहले तय हुआ कोई फ़ाइल-प्रारूप। उन हालात में विकल्प SHA-256 नहीं है, विकल्प यह है कि जुड़ाव ही न हो।

किसी नई चीज़ के लिए इसे मत चुनिए। अगर आप आज तय कर रहे हैं कि हस्ताक्षर कैसे करना है, integrity कैसे जाँचनी है या पहचान कैसे बनानी है, तो SHA-256 वही काम बिना इस उधार के करता है — और SHA-1 का ऐसा कोई फ़ायदा नहीं है जो उस उधार को ढोने के लायक़ हो।

टकराव और preimage दो अलग बातें हैं

टकराव का मतलब है दो ऐसे इनपुट गढ़ लेना जिनका hash एक हो, और उन दोनों को हमलावर ख़ुद चुनता है। Preimage का मतलब है किसी दिए हुए hash के लिए कोई ऐसा इनपुट ढूँढ़ लेना जो वह hash देता हो, और यहाँ हमलावर के हाथ में कुछ नहीं होता। SHA-1 में पहला टूट चुका है, दूसरा नहीं।

यह भेद तय करता है कि कौन-सा इस्तेमाल असल में ख़तरे में है। जहाँ कोई फ़ाइल के दोनों रूप ख़ुद बनाकर आपको एक थमा सकता है — कोई हस्ताक्षरित दस्तावेज़, कोई प्रमाणपत्र — वहाँ SHA-1 बेकार है। जहाँ मान पहले से मौजूद है और हमलावर उस तक पहुँचने की कोशिश कर रहा है, वहाँ वह अब भी टूटा नहीं है। दोनों को एक ही साँस में «टूटा हुआ» कह देना उन फ़ैसलों को उलझा देता है जो अलग-अलग हैं।

DPDP Act के लिहाज़ से इसका क्या मतलब है

ऐसे खाने में hash होने वाली चीज़ आम तौर पर असली डेटा से आती है: किसी पंक्ति का कोई मान, किसी जुड़ाव की कोई पहचान, कोई सामग्री जिसे किसी पुराने तंत्र से मिलाना है। चूँकि गणना पन्ने पर ही होती है, उसमें से कुछ भी हम तक नहीं पहुँचता।

और बाक़ी दोनों की तरह: निजी डेटा को hash कर देने से वह अनाम नहीं हो जाता, जब संभव इनपुट का दायरा सीमित हो। SHA-1 के साथ यह दोगुना लागू होता है, क्योंकि उसकी रफ़्तार उम्मीदवार आज़माना SHA-256 से भी सस्ता बना देती है।

SHA-1 hash बनाएँ: आम सवाल

क्या मैं SHA-1 इस्तेमाल करता रह सकता हूँ?

सिर्फ़ तब जब कोई बाहरी चीज़ इसकी माँग करे और आप उसे बदल न सकें: कोई Git पहचान, कोई पुराना जुड़ाव, दशकों पहले तय हुआ कोई प्रारूप। किसी भी नई चीज़ के लिए SHA-256।

अगर यह टूटा हुआ है तो Git इसे क्यों इस्तेमाल करता है?

क्योंकि इसे बदलने का मतलब है दुनिया भर के repository का प्रारूप एक साथ बदलना। SHA-256 की ओर संक्रमण मौजूद है और इसी वजह से धीरे चल रहा है। इस बीच Git ज्ञात हमले के ढाँचे वाले ऑब्जेक्ट पहचानकर मना कर देता है।

क्या इसे दो बार लगाने या salt के साथ लगाने से फ़ायदा है?

नहीं। जो दो इनपुट पहली बार में टकराते हैं वे दूसरी बार में भी टकराते हैं, क्योंकि दूसरी बार पहली का नतीजा ही देखती है। टकराव के ख़िलाफ़ सिर्फ़ दूसरा algorithm काम आता है।

यह मेरे commit की ऑब्जेक्ट-पहचान से मेल क्यों नहीं खाता?

क्योंकि Git ऑब्जेक्ट के प्रकार और लंबाई को आगे लगाता है, बीच में एक शून्य बाइट के साथ, और उसी का hash निकालता है। शुद्ध सामग्री का SHA-1 वह पहचान नहीं होता।

क्या टेक्स्ट मेरे डिवाइस से बाहर जाता है?

नहीं। गणना इसी पन्ने पर होती है। और यह ध्यान में रखिए कि निजी डेटा को hash कर देना उसे अनाम नहीं बनाता, अगर संभव मानों का दायरा छोटा हो।

और टूल्स