एक लाइन में
HMAC एक क्रिप्टोग्राफ़िक हैंडशेक है जो एक शेयर्ड सीक्रेट की (shared secret key) का उपयोग करके यह साबित करता है कि कोई मैसेज असली है और उसके साथ कोई छेड़छाड़ नहीं की गई है।
यह कौन सी समस्या हल करता है
इंटरनेट के शुरुआती, वाइल्ड-वेस्ट वाले दिनों में, मैसेज भेजना एक पोस्टकार्ड भेजने जैसा था। जो कोई भी इसे बीच में पकड़ लेता, वह इसे पढ़ सकता था, और शायद आगे भेजने से पहले उस पर कुछ लिख भी सकता था। अगर आपको एक पोस्टकार्ड मिलता जिसमें लिखा हो "आधी रात को मिलो, कैश ले आना," तो आप कैसे सुनिश्चित हो सकते थे कि यह सच में आपके सीक्रेट एजेंट कॉन्टैक्ट से आया है, न कि उसकी दुश्मन, शैतान ईव (Evil Eve) से? और आप यह कैसे सुनिश्चित कर सकते थे कि इसमें मूल रूप से "दोपहर में एक दोस्ताना लंच के लिए मिलो" नहीं लिखा था?
यह दोहरी समस्या है ऑथेंटिसिटी (क्या यह सच में منك भेजा गया है?) और इंटेग्रिटी (क्या इसे बदला गया है?) की।
एक सरल क्रिप्टोग्राफ़िक हैश फ़ंक्शन (जैसे SHA-256) पहले कदम के तौर पर अच्छा लगता है। आप अपने मैसेज को हैश कर सकते हैं, मैसेज और हैश दोनों भेज सकते हैं, और रिसीवर यह देखने के लिए मैसेज को फिर से हैश कर सकता है कि क्या वे मेल खाते हैं। बहुत बढ़िया! इससे इंटेग्रिटी की समस्या हल हो गई। अगर मैसेज का एक भी बाइट बदला गया, तो हैश मेल नहीं खाएंगे।
लेकिन यह ऑथेंटिसिटी को हल नहीं करता है। शैतान ईव बस मैसेज बदल सकती है, अपने नए मैसेज के लिए एक नया हैश कैलकुलेट कर सकती है, और दोनों को आगे भेज सकती है। रिसीवर देखेगा कि हैश मैसेज से मेल खाता है, लेकिन उसके पास यह जानने का कोई तरीका नहीं है कि पूरा पैकेज ही नकली है।
यहीं पर HMAC (हैश-बेस्ड मैसेज ऑथेंटिकेशन कोड) सीन में आता है। हैशिंग प्रक्रिया में एक शेयर्ड सीक्रेट की (shared secret key) को शामिल करके, HMAC एक ऐसा सिग्नेचर बनाता है जिसे केवल वही व्यक्ति बना सकता है जिसके पास वह सीक्रेट की हो। यह एक साधारण मोम की मुहर (जिसे कोई भी बना सकता है) और एक अनोखी राजसी अंगूठी से बनी मोम की मुहर (जो केवल राजा के पास होती है) के बीच का अंतर है। HMAC हमें इंटेग्रिटी और ऑथेंटिसिटी दोनों देता है।
यह अंदर से कैसे काम करता है
HMAC कोई नया हैश फ़ंक्शन नहीं है; यह एक रेसिपी है जो मौजूदा हैश फ़ंक्शन (जैसे SHA-256) का एक चालाक, खास तरीके से उपयोग करती है। आधिकारिक स्पेक RFC 2104 है, लेकिन चलिए इसे सरल भाषा में समझते हैं।
सामग्री
एक HMAC पकाने के लिए, आपको तीन चीजों की आवश्यकता है:
- मैसेज: वह डेटा जिसे आप सुरक्षित करना चाहते हैं। यह एक वेबहुक के लिए JSON पेलोड, URL पैरामीटर की एक स्ट्रिंग, या बाइनरी डेटा का कोई भी टुकड़ा हो सकता है।
- सीक्रेट की: बाइट्स की एक स्ट्रिंग जो केवल भेजने वाले और पाने वाले को पता होती है। यह जादुई सामग्री है। अगर यह लीक हो गई, तो पूरा सिस्टम टूट जाता है।
- हैश फ़ंक्शन: एक मानक एल्गोरिथ्म जैसे SHA-1, SHA-256, या SHA-512। हैश फ़ंक्शन का चुनाव अंतिम HMAC सिग्नेचर की लंबाई निर्धारित करता है (उदाहरण के लिए, HMAC-SHA256 एक 256-बिट सिग्नेचर बनाता है)।
रेसिपी (HMAC एल्गोरिथ्म)
आप सोच सकते हैं कि आप बस hash(key + message) कर सकते हैं। यह सरल लगता है, लेकिन यह कंस्ट्रक्शन कुछ चालाक क्रिप्टो तिकड़मों, जिन्हें "लेंथ एक्सटेंशन अटैक" (length extension attacks) कहा जाता है, के प्रति असुरक्षित है। आधिकारिक HMAC कंस्ट्रक्शन थोड़ा अधिक जटिल है, विशेष रूप से इन हमलों को रोकने के लिए। यह एक डबल-हैशिंग प्रक्रिया का उपयोग करता है।
यहाँ स्टेप्स का एक सरल रूप दिया गया है:
की (Key) तैयार करें: हैश फ़ंक्शन डेटा के निश्चित आकार के ब्लॉक पर काम करता है (जैसे, SHA-256 के लिए 64 बाइट्स)। की को इस ब्लॉक साइज में फिट होने के लिए तैयार करने की आवश्यकता है।
- यदि की ब्लॉक साइज से लंबी है, तो आप की को ही हैश करते हैं और उस परिणाम को नई की के रूप में उपयोग करते हैं।
- यदि की ब्लॉक साइज से छोटी है, तो आप इसे शून्य बाइट्स के साथ पैड करते हैं जब तक कि यह ब्लॉक साइज तक न पहुंच जाए।
इनर और आउटर की (Keys) बनाएं: इस तैयार की से, हम दो अलग-अलग की निकालते हैं।
ipad(इनर पैड): एक स्थिर बाइट (0x36) जिसे ब्लॉक साइज भरने के लिए दोहराया जाता है।opad(आउटर पैड): एक अलग स्थिर बाइट (0x5C) जिसे ब्लॉक साइज भरने के लिए दोहराया जाता है।
हम अपनी तैयार की को
ipadके साथ XOR करके एकinner_padded_keyबनाते हैं। हम तैयार की कोopadके साथ XOR करके एकouter_padded_keyबनाते हैं।डबल हैश करें: अब मुख्य कार्यक्रम का समय है।
- इनर हैश:
inner_padded_keyको मूल मैसेज के साथ मिलाएं, और इसे हैश फ़ंक्शन से गुजारें। - आउटर हैश:
outer_padded_keyको इनर हैश के परिणाम के साथ मिलाएं, और उसे हैश फ़ंक्शन से गुजारें।
- इनर हैश:
इस आउटर हैश का अंतिम परिणाम आपका HMAC सिग्नेचर है!
स्यूडोकोड में, यह ऐसा दिखता है:
function hmac(key, message, hash_function, block_size) {
// 1. की तैयार करें
if (key.length > block_size) {
key = hash_function(key);
}
if (key.length < block_size) {
key = pad_with_zeros(key, block_size);
}
// 2. इनर और आउटर पैडेड की बनाएं
o_key_pad = key XOR (0x5C repeated to block_size);
i_key_pad = key XOR (0x36 repeated to block_size);
// 3. डबल हैश करें
inner_hash_result = hash_function(i_key_pad + message);
final_hmac = hash_function(o_key_pad + inner_hash_result);
return final_hmac;
}
डबल हैश क्यों?
यह इनर-फिर-आउटर संरचना ही असली सीक्रेट सॉस है। इनर हैश सीक्रेट और मैसेज को मिलाता है। फिर आउटर हैश अनिवार्य रूप से पहले ऑपरेशन के परिणाम को सीक्रेट के साथ फिर से हैश करता है। यह इनर हैश को "सील" कर देता है। यह एक हमलावर के लिए की जाने बिना मध्यवर्ती हैश परिणाम में हेरफेर करना कम्प्यूटेशनली असंभव बना देता है, इस प्रकार लेंथ एक्सटेंशन अटैक और अन्य संभावित क्रिप्टोग्राफ़िक ब्रेक्स को विफल कर देता है। यह एक सिद्ध, मजबूत कंस्ट्रक्शन है जो समय की कसौटी पर खरा उतरा है।
असल दुनिया की कहानियाँ
गिटहब वेबहुक का रक्षक
एक स्टार्टअप टीम ने अपना कंटीन्यूअस इंटीग्रेशन (CI) सर्वर इस तरह से सेट किया था कि जब भी कोई main ब्रांच में पुश करता, तो उनका ऐप अपने आप प्रोडक्शन में डिप्लॉय हो जाता। इसका ट्रिगर गिटहब से एक वेबहुक था: गिटहब के सर्वर से उनके CI सर्वर पर एक पब्लिक URL पर भेजा गया POST रिक्वेस्ट। एक रात, उनके शरारती इंटर्न को वह पब्लिक URL मिल गया और एक साधारण cURL कमांड का उपयोग करके, उसने नकली वेबहुक पेलोड भेजना शुरू कर दिया, जिससे दर्जनों बेकार, रिसोर्स खाने वाले डिप्लॉयमेंट शुरू हो गए।
सीनियर डेवलपर ने इसे 15 मिनट में ठीक कर दिया। गिटहब की वेबहुक सेटिंग्स में, उसने एक लंबा, रैंडम "सीक्रेट" जनरेट किया। उसने इस सीक्रेट को कॉपी किया और इसे अपने CI सर्वर पर एक एनवायरनमेंट वेरिएबल के रूप में कॉन्फ़िगर किया। अब गिटहब हर वेबहुक पेलोड के लिए HMAC-SHA256 सिग्नेचर बनाने के लिए इस सीक्रेट का उपयोग करने लगा, और इसे X-Hub-Signature-256 हेडर में भेजने लगा। CI सर्वर के कोड को अपडेट किया गया ताकि वह प्राप्त हुए रॉ रिक्वेस्ट बॉडी पर उसी सीक्रेट का उपयोग करके वही HMAC कैलकुलेशन करे। यदि उसका कैलकुलेटेड सिग्नेचर हेडर वाले सिग्नेचर से मेल खाता, तो रिक्वेस्ट को प्रोसेस किया जाता। यदि नहीं, तो इसे 403 Forbidden के साथ रिजेक्ट कर दिया जाता। शरारतें तुरंत बंद हो गईं।
सबक: हमेशा अपने वेबहुक को HMAC सिग्नेचर वेरिफिकेशन से सुरक्षित करें। किसी भी आने वाले रिक्वेस्ट पर तब तक भरोसा न करें जब तक वह प्रमाणित न हो जाए।
API कुकी जार को सुरक्षित करना
एक डेवलपर एक ऐसी सर्विस बना रहा था जो ऑथेंटिकेशन के लिए एक सरल, साइन्ड कुकी का उपयोग करती थी। जब कोई यूजर लॉग इन करता, तो सर्वर उनकी user_id और एक expiry टाइमस्टैम्प वाली कुकी जारी करता। यूजर्स को अपनी कुकी एडिट करके कोई दूसरा यूजर बनने से रोकने के लिए (जैसे user_id=123 को user_id=1 में बदलना), डेवलपर ने एक HMAC सिग्नेचर शामिल किया।
कुकी पेलोड कुछ इस तरह दिखता था: user_id=123&expiry=1678886400। सर्वर इस सटीक स्ट्रिंग को सर्वर पर संग्रहीत एक सीक्रेट की से साइन करता। ब्राउज़र को भेजी गई अंतिम कुकी थी data="user_id=123&expiry=1678886400"&signature="sha1=2a8b..."।
जब यूजर ने बाद में कोई रिक्वेस्ट किया, तो उनके ब्राउज़र ने कुकी वापस भेजी। सर्वर data वाला हिस्सा लेता, अपनी सीक्रेट की का उपयोग करके HMAC सिग्नेचर को फिर से कैलकुलेट करता, और इसकी तुलना कुकी के signature वाले हिस्से से करता। यदि वे मेल खाते, तो सर्वर जानता था कि यूजर आईडी और एक्सपायरी डेट वैध हैं और उनके साथ छेड़छाड़ नहीं की गई है।
सबक: HMAC छेड़छाड़-रोधी, "स्टेटलेस" टोकन या कुकी बनाने का एक शानदार तरीका है, जो JSON वेब टोकन (JWTs) सहित कई ऑथेंटिकेशन सिस्टम का आधार बनता है।
बैंक ट्रांसफर जो हाईजैक नहीं हुआ
एक ई-कॉमर्स प्लेटफॉर्म ने अपने वेंडर्स को भुगतान शुरू करने के लिए एक पेमेंट प्रोसेसर के API के साथ इंटीग्रेट किया। API कॉल एक साधारण JSON मैसेज था: {"vendor_id": "ven_abc", "amount": 500.00, "currency": "USD"}। प्लेटफॉर्म को मैन-इन-द-मिडल (MITM) अटैक का डर था। HTTPS पर भी, जो ट्रैफिक को एन्क्रिप्ट करता है, एक परिष्कृत हमलावर (कुछ सैद्धांतिक परिदृश्यों में, जैसे कि एक समझौता किए गए सर्टिफिकेट अथॉरिटी के साथ) रिक्वेस्ट को रोककर संशोधित कर सकता था। वे amount को 50000.00 में या vendor_id को अपने में बदल सकते थे।
पेमेंट प्रोसेसर के API को हर रिक्वेस्ट को HMAC-SHA512 के साथ साइन करने की आवश्यकता थी। प्लेटफॉर्म JSON पेलोड को एक कैनोनिकल स्ट्रिंग में सीरियलाइज करता, अपनी निजी API की के साथ सिग्नेचर की गणना करता, और इसे Authorization हेडर में भेजता। पेमेंट प्रोसेसर के सर्वर बिल्कुल वही कदम उठाते। यदि उनका कैलकुलेटेड सिग्नेचर हेडर में भेजे गए सिग्नेचर से मेल खाता, तो वे दो बातें निश्चित रूप से जानते थे: रिक्वेस्ट वैध प्लेटफॉर्म से आया था (ऑथेंटिसिटी) और vendor_id और amount को रास्ते में बदला नहीं गया था (इंटेग्रिटी)।
सबक: उच्च-दांव वाले ऑपरेशनों के लिए, HMAC सुरक्षा की एक महत्वपूर्ण परत प्रदान करता है ताकि यह गारंटी दी जा सके कि संदेश का प्रेषक और सामग्री वही है जो आप उम्मीद करते हैं।
आम गलतियाँ और जाल
- सीक्रेट की लीक करना। की (key) ही सब कुछ है। यदि आप इसे क्लाइंट-साइड जावास्क्रिप्ट में उजागर करते हैं, इसे एक पब्लिक गिट रिपॉजिटरी में कमिट करते हैं, या इसे प्लेन टेक्स्ट में लॉग करते हैं, तो आपकी सुरक्षा खत्म हो जाती है। इसे एक पासवर्ड की तरह मानें।
- नॉन-कांस्टेंट-टाइम कंपेरिजन का उपयोग करना। जब आप जांचते हैं कि यूजर द्वारा प्रदान किया गया सिग्नेचर आपके कैलकुलेटेड सिग्नेचर से मेल खाता है या नहीं, तो
if (a === b)जैसा एक मानक स्ट्रिंग कंपेरिजन एक सुरक्षा छेद हो सकता है। यह अक्सर जैसे ही एक बेमेल कैरेक्टर पाता है,falseलौटाता है। यह एक छोटा सा समय अंतर बनाता है जिसे हमलावर एक-एक करके सिग्नेचर का अनुमान लगाने के लिए माप सकते हैं। यह एक "टाइमिंग अटैक" है। हमेशा एक समर्पित, "कांस्टेंट-टाइम" कंपेरिजन फ़ंक्शन का उपयोग करें जो एक क्रिप्टो लाइब्रेरी से आता है, जो इस बात की परवाह किए बिना समान समय लेता है कि बेमेल कहाँ होता है। - गलत डेटा पर साइन करना। भेजने वाले और पाने वाले को बाइट्स के बिल्कुल समान क्रम पर HMAC की गणना करनी चाहिए। एक आम बग यह है कि एक पक्ष एक सुंदर बनाए गए JSON ऑब्जेक्ट पर साइन करता है जबकि दूसरा कॉम्पैक्ट, एक-लाइन वाले संस्करण पर साइन करता है। या एक पक्ष एक ट्रेलिंग न्यूलाइन शामिल करता है और दूसरा नहीं। आपको एक कैनोनिकल मैसेज फॉर्मेट पर सहमत होना चाहिए और उस पर टिके रहना चाहिए।
- रिप्ले अटैक के बारे में भूल जाना। HMAC खुद एक हमलावर को एक वैध, हस्ताक्षरित संदेश को पकड़ने और उसे बार-बार भेजने से नहीं रोकता है। यदि वह संदेश "बॉब को $10 का भुगतान करें" है, तो आप नहीं चाहेंगे कि हमलावर उस भुगतान को 1000 बार ट्रिगर कर सके। इसे रोकने के लिए, एक मान शामिल करें जो प्रत्येक अनुरोध के साथ बदलता है—जैसे एक टाइमस्टैम्प या एक "नॉन्स" (एक बार उपयोग की जाने वाली संख्या)—साइन किए जा रहे डेटा के अंदर। सर्वर तब पुराने अनुरोधों को अस्वीकार करने के लिए टाइमस्टैम्प की जांच कर सकता है या डुप्लिकेट को अस्वीकार करने के लिए उपयोग किए गए नॉन्स की एक सूची रख सकता है।
यह आपके रडार पर क्यों होना चाहिए
आपको HMAC के बारे में तब सोचना चाहिए जब आप ऐसे संचार से निपट रहे हों जिस पर भरोसा करने की आवश्यकता हो। यह डेटा को गुप्त रखने के बारे में नहीं है (यह एन्क्रिप्शन का काम है), बल्कि यह सुनिश्चित करने के बारे में है कि डेटा वैध है।
- APIs बना रहे हैं या उनका उपयोग कर रहे हैं? विशेष रूप से वेबहुक (Stripe, GitHub, Twilio जैसी सेवाओं से) के साथ, HMAC यह सत्यापित करने के लिए उद्योग मानक है कि अनुरोध प्रामाणिक है।
- ऑथेंटिकेशन के साथ काम कर रहे हैं? कई टोकन-आधारित सिस्टम, सबसे प्रसिद्ध JWTs, टोकन के पेलोड पर हस्ताक्षर करने के लिए HMAC (जैसे, 'HS256' एल्गोरिथ्म) का उपयोग करते हैं, जिससे उपयोगकर्ता अपनी अनुमतियों को संशोधित करने से बचते हैं।
- डेटा इंटेग्रिटी को सत्यापित करने की आवश्यकता है? यदि आप डेटा को एक अविश्वसनीय वातावरण (जैसे उपयोगकर्ता के ब्राउज़र में एक कुकी) के माध्यम से पारित कर रहे हैं और यह सुनिश्चित करने की आवश्यकता है कि यह बिना संशोधित हुए वापस आए, तो HMAC आपका टूल है।
यह एक वेब डेवलपर के सुरक्षा टूलबॉक्स में एक मौलिक आदिम है। यह समझना कि यह कैसे काम करता है, आपको एक बेहतर, अधिक सुरक्षा-सचेत इंजीनियर बनाएगा।
और गहराई में जाएँ
- RFC 2104: HMAC: Keyed-Hashing for Message Authentication: मूल तकनीकी विनिर्देश। यह घना है, लेकिन यह सत्य का अंतिम स्रोत है।
- Wikipedia: HMAC: इतिहास, डिजाइन सिद्धांतों और कार्यान्वयन विवरणों का एक शानदार, उच्च-स्तरीय अवलोकन।
- OWASP: Replay Attack: रिप्ले अटैक पर ओपन वेब एप्लीकेशन सिक्योरिटी प्रोजेक्ट का पेज, HMAC का उपयोग करते समय समझने के लिए एक महत्वपूर्ण अवधारणा।
- Stripe Docs: Checking webhook signatures: एक ऐसी कंपनी से एक वास्तविक दुनिया, व्यावहारिक गाइड जो अरबों डॉलर के लेनदेन को सुरक्षित करने के लिए HMAC पर बहुत अधिक निर्भर करती है।
- Crypto 101: HMAC: HMAC के डिजाइन के पीछे क्रिप्टोग्राफ़िक सिद्धांतों का थोड़ा अधिक सुलभ स्पष्टीकरण।