उपयोग कैसे करें
- “एल्गोरिदम” चुनें। HMAC-SHA256 डिफ़ॉल्ट रूप से चुना रहता है, और ज़्यादातर वेबहुक और API यही इस्तेमाल करते हैं।
- “सीक्रेट कुंजी” दर्ज करें और “कुंजी का फ़ॉर्मैट” को “टेक्स्ट” (UTF-8 के रूप में पढ़ा जाता है), “हेक्स” या “Base64” पर सेट करें। जब कुंजी पासवर्ड जैसी स्ट्रिंग के बजाय रॉ बाइट हो, तब “हेक्स” या “Base64” चुनें।
- “संदेश” टाइप या पेस्ट करें, रॉ बाइट के लिए इनपुट को “हेक्स” पर करें, या “फ़ाइल खोलें” से कोई फ़ाइल चुनें। टाइप करते ही HMAC अपडेट हो जाता है।
- “आउटपुट प्रकार” में “hex (छोटे अक्षर)”, “HEX (बड़े अक्षर)” या “Base64” चुनें और परिणाम कॉपी करें, या मिला हुआ सिग्नेचर “इससे तुलना करें” में पेस्ट करके देखें कि “मेल खाता है” दिखता है या “मेल नहीं खाता”।
HMAC कैसे काम करता है
HMAC (hash-based message authentication code, यानी हैश-आधारित संदेश प्रमाणीकरण कोड, RFC 2104) एक क्रिप्टोग्राफ़िक हैश को एक सीक्रेट कुंजी के साथ जोड़ता है। किसी संदेश के लिए सही मान केवल वही बना सकता है जो कुंजी जानता हो, इसलिए मेल खाता HMAC एक साथ दो बातें साबित करता है: संदेश बदला नहीं गया, और वह कुंजी रखने वाले किसी व्यक्ति से आया है।
इसकी बनावट H((K ⊕ opad) ‖ H((K ⊕ ipad) ‖ message)) है। अगर कुंजी हैश के ब्लॉक आकार (MD5, SHA-1 और SHA-256 के लिए 64 बाइट, SHA-384 और SHA-512 के लिए 128) से लंबी हो, तो पहले उसका हैश लिया जाता है; फिर उसे शून्यों से उस आकार तक भरा जाता है, और संदेश पर अंदरूनी हैश के लिए उसे ipad (0x36 बाइट) से, तथा अंदरूनी परिणाम पर बाहरी हैश के लिए opad (0x5c बाइट) से XOR किया जाता है। सीधे-सादे SHA-256(key ‖ message) में कोई बाहरी हैश नहीं होता, इसलिए एक टैग देख लेने वाला कोई भी व्यक्ति कुंजी के बिना संदेश में डेटा जोड़कर नया मान्य टैग बना सकता है (लेंथ-एक्सटेंशन हमला)।
आउटपुट की लंबाई मूल हैश जितनी होती है: HMAC-SHA256 के लिए 32 बाइट, यानी 64 हेक्स अक्षर। RFC 2104 कम से कम इतनी लंबी कुंजी की सलाह देता है, और रैंडम Base64 जनरेटर उपयुक्त कुंजियाँ बनाता है।
HMAC सिग्नेचर कहाँ उपयोग होते हैं
- GitHub वेबहुक।
X-Hub-Signature-256हेडर मेंsha256=के बाद रॉ अनुरोध बॉडी का हेक्स HMAC-SHA256 होता है, जिसकी कुंजी वेबहुक सीक्रेट होती है। आप पूरे हेडर मान को “इससे तुलना करें” में पेस्ट कर सकते हैं;sha256=प्रीफ़िक्स अनदेखा कर दिया जाता है। - Stripe वेबहुक।
Stripe-Signatureहेडर में एक टाइमस्टैम्पtऔर एक सिग्नेचरv1होता है: टाइमस्टैम्प, एक बिंदु और रॉ बॉडी का हेक्स HMAC-SHA256, जिसकी कुंजी टेक्स्ट के रूप में इस्तेमाल किया गया एंडपॉइंट सीक्रेट (whsec_...) होता है। - Shopify वेबहुक।
X-Shopify-Hmac-Sha256में रॉ बॉडी का HMAC-SHA256 Base64 में होता है, जिसकी कुंजी ऐप का क्लाइंट सीक्रेट होता है, इसलिए Base64 आउटपुट चुनें या हेडर मान को “इससे तुलना करें” में पेस्ट करें। - AWS Signature Version 4। साइनिंग कुंजी HMAC-SHA256 की एक शृंखला से निकाली जाती है: पहले तारीख, जिसकी कुंजी
AWS4और सीक्रेट एक्सेस कुंजी को जोड़कर बनती है, फिर रीजन, सेवा औरaws4_request, जिनमें से हर एक की कुंजी पिछला परिणाम होता है। एक चरण के आउटपुट को अगले चरण में देने के लिए “कुंजी का फ़ॉर्मैट” “हेक्स” पर सेट करें। - JSON Web Token। HS256, HS384 और HS512 का मतलब है एनकोड किए गए हेडर, एक बिंदु और एनकोड किए गए पेलोड पर HMAC-SHA256, -384 और -512। टोकन का तीसरा भाग वही HMAC है, URL-सुरक्षित Base64 में, जिसे “इससे तुलना करें” जैसे का तैसा स्वीकार करता है। JWT डिकोडर पूरे टोकन सत्यापित करता है।
HMAC की गणना हमेशा रॉ बॉडी पर ठीक उसी रूप में करें जिसमें वह मिली थी। JSON को पार्स करके दोबारा सीरियलाइज़ करने से स्पेसिंग या फ़ील्ड का क्रम बदल जाता है, और एक अतिरिक्त न्यूलाइन भी बिल्कुल अलग HMAC दे देती है।
कोड में HMAC
# Python
import hmac, hashlib
sig = hmac.new(b'key', b'message', hashlib.sha256).hexdigest()
hmac.compare_digest(sig, received) # कॉन्स्टेंट-टाइम तुलना
// Node.js
const crypto = require('crypto');
const sig = crypto.createHmac('sha256', 'key').update('message').digest('hex');
// लंबाई अलग होने पर timingSafeEqual त्रुटि देता है, इसलिए पहले लंबाई जाँचें
crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(received));
// PHP: संदेश कुंजी से पहले आता है
$sig = hash_hmac('sha256', 'message', 'key');
hash_equals($sig, $received);
# OpenSSL: टेक्स्ट कुंजी, फिर वही कुंजी हेक्स के रूप में
printf '%s' 'message' | openssl dgst -sha256 -hmac 'key'
printf '%s' 'message' | openssl dgst -sha256 -mac HMAC -macopt hexkey:6b6579
# टेस्ट वेक्टर: कुंजी "key", संदेश "The quick brown fox jumps over the lazy dog"
# HMAC-SHA256 = f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8
जब आप अपने कोड में सिग्नेचर सत्यापित करें, तो ऊपर दिए गए उदाहरणों की तरह कॉन्स्टेंट-टाइम तुलना का उपयोग करें। साधारण == पहले अलग अक्षर पर ही रुक जाता है, और समय का यह अंतर हमलावर को बाइट-दर-बाइट एक मान्य सिग्नेचर खोजने का मौक़ा दे सकता है। Stripe जैसी टाइमस्टैम्प वाली योजनाओं में उन अनुरोधों को भी अस्वीकार करें जिनका टाइमस्टैम्प कुछ मिनट से ज़्यादा पुराना हो; इससे रीप्ले हमले रुकते हैं।
अक्सर पूछे जाने वाले प्रश्न
क्या HMAC-MD5 या HMAC-SHA1 अब भी सुरक्षित है?
कॉलिज़न हमले MD5 और SHA-1 को सादे हैश के रूप में तोड़ देते हैं, लेकिन उनसे HMAC की जालसाज़ी का कोई व्यावहारिक तरीक़ा नहीं मिलता, क्योंकि HMAC हैश के दूसरे गुणों और एक सीक्रेट कुंजी पर निर्भर करता है (RFC 6151 में HMAC-MD5 पर चर्चा की गई है)। जिन इंटीग्रेशन में इनकी ज़रूरत है, जैसे HMAC-SHA1 पर आधारित TOTP कोड, उन्हें बनाए रखना ठीक है। नए डिज़ाइन के लिए HMAC-SHA256 का उपयोग करें।
मेरा HMAC वेबहुक सिग्नेचर से मेल क्यों नहीं खाता?
आम कारण हैं: रॉ बॉडी के बजाय पार्स करके दोबारा सीरियलाइज़ किए गए JSON का हैश लेना, संदेश के अंत में एक न्यूलाइन, ग़लत सीक्रेट या कुंजी का फ़ॉर्मैट (Base64 या हेक्स सीक्रेट को “टेक्स्ट” के रूप में दर्ज करना, या इसका उल्टा), और ग़लत एल्गोरिदम। हेक्स बनाम Base64 यहाँ कोई समस्या नहीं है: “इससे तुलना करें” किसी भी केस का हेक्स, मानक Base64 और URL-सुरक्षित Base64 स्वीकार करता है।
HMAC और सादे हैश में क्या अंतर है?
क्या HMAC डिजिटल सिग्नेचर जैसा ही है?
नहीं। HMAC के दोनों पक्ष एक ही सीक्रेट साझा करते हैं, इसलिए जो भी किसी टैग को सत्यापित कर सकता है, वह उसे बना भी सकता है। RSA या ECDSA जैसे सिग्नेचर (JWT में RS256 या ES256) निजी कुंजी से बनाए जाते हैं और सार्वजनिक कुंजी से जाँचे जाते हैं, इसलिए उन्हें सत्यापित करने वाले उनकी जालसाज़ी नहीं कर सकते।
क्या मेरी सीक्रेट कुंजी किसी सर्वर पर भेजी जाती है?
नहीं। HMAC-SHA1 और SHA-2 वेरिएंट की गणना आपके ब्राउज़र के Web Crypto API से होती है, और HMAC-MD5 की गणना पेज पर मौजूद JavaScript से। कुंजी और संदेश कभी आपके डिवाइस से बाहर नहीं जाते। फिर भी, प्रोडक्शन सीक्रेट को सावधानी से सँभालें, और अगर किसी कुंजी के उजागर होने की आशंका हो तो उसे बदल दें।