Python HMAC — hmac.new() SHA-256 गाइड + कोड उदाहरण
मुफ़्त HMAC Generator को सीधे अपने ब्राउज़र में उपयोग करें — इंस्टॉलेशन की ज़रूरत नहीं।
HMAC Generator ऑनलाइन आज़माएं →हर webhook कॉलबैक, हर हस्ताक्षरित API अनुरोध, हर Stripe या GitHub इवेंट अधिसूचना एक HMAC हस्ताक्षर का उपयोग करती है यह सिद्ध करने के लिए कि पेलोड के साथ छेड़छाड़ नहीं हुई। Python का hmac मॉड्यूल Python में HMAC-SHA256 को एक फ़ंक्शन कॉल में संभालता है: hmac.new(key, msg, hashlib.sha256). कोई pip install नहीं, कोई C एक्सटेंशन नहीं, कोई तृतीय-पक्ष निर्भरता नहीं। बिना कोड लिखे त्वरित एकबारगी हस्ताक्षर जांच के लिए, ऑनलाइन HMAC जनरेटर तुरंत परिणाम देता है। यह गाइड hmac.new(), hmac.digest(), hmac.compare_digest(), Base64 एन्कोडिंग, webhook सत्यापन, API अनुरोध हस्ताक्षरण, और SHA-1 से SHA-512 तक हर हैश एल्गोरिदम को कवर करती है। सभी उदाहरण Python 3.7+ को लक्षित करते हैं।
- ✓hmac.new(key, msg, hashlib.sha256) मानक प्रवेश बिंदु है — key और msg bytes होने चाहिए, Python 3.4 से digestmod अनिवार्य है।
- ✓hmac.digest(key, msg, "sha256") Python 3.7 में जोड़ा गया तेज़ one-shot विकल्प है — raw bytes लौटाता है, कोई intermediate object नहीं।
- ✓हस्ताक्षर सत्यापन के लिए हमेशा hmac.compare_digest() उपयोग करें — टाइमिंग हमलों से बचाव के लिए HMAC तुलना में कभी == न उपयोग करें।
- ✓HTTP हेडर और webhook हस्ताक्षरों के लिए कच्चे .digest() आउटपुट को Base64 में एन्कोड करें: base64.b64encode(h.digest())।
- ✓hmac मॉड्यूल कोई भी hashlib एल्गोरिदम स्वीकार करता है: sha1, sha256, sha384, sha512, md5, blake2b।
HMAC क्या है?
HMAC (Hash-based Message Authentication Code) RFC 2104 में परिभाषित एक संरचना है जो एक गोपनीय कुंजी को हैश फ़ंक्शन के साथ मिलाकर एक निश्चित आकार का प्रमाणीकरण टैग उत्पन्न करती है। सामान्य हैश (जिसे कोई भी उत्पन्न कर सकता है) के विपरीत, HMAC के लिए गोपनीय कुंजी का ज्ञान आवश्यक है। इसका अर्थ है कि आप इसका उपयोग संदेश की अखंडता और प्रामाणिकता दोनों सत्यापित करने के लिए कर सकते हैं। यदि संदेश या कुंजी का एक भी बाइट बदले, तो आउटपुट पूरी तरह भिन्न हो जाता है। यह संरचना कुंजी को दो अलग-अलग पैडिंग स्थिरांक (ipad और opad) के साथ XOR करके, संदेश को दो हैश संचालनों के बीच लपेटकर काम करती है। Python का hmac मॉड्यूल इस RFC को सीधे लागू करता है।
# सामान्य SHA-256 हैश — कोई गोपनीय कुंजी नहीं, कोई भी उत्पन्न कर सकता है hashlib.sha256(b"payment:9950:USD").hexdigest() # "7a3b1c..." (निर्धारणात्मक, सार्वजनिक)
# HMAC-SHA256 — उत्पन्न करने के लिए गोपनीय कुंजी आवश्यक है hmac.new(b"api_secret", b"payment:9950:USD", hashlib.sha256).hexdigest() # "e4f2a8..." (केवल कुंजी धारक उत्पन्न कर सकता है)
hmac.new() — मानक लाइब्रेरी प्रवेश बिंदु
hmac मॉड्यूल Python मानक लाइब्रेरी का हिस्सा है। दो आयात और आप तैयार हैं: import hmac, hashlib. मॉड्यूल में तीन मुख्य फ़ंक्शन हैं: hmac.new() (HMAC ऑब्जेक्ट बनाता है), hmac.digest() (एकबारगी, Python 3.7+), और hmac.compare_digest() (स्थिर-समय तुलना)। pip install की आवश्यकता नहीं।
hmac.new(key, msg, digestmod) तीन तर्क लेता है। key और msg दोनों bytes-like ऑब्जेक्ट होने चाहिए ( bytes, bytearray, या memoryview)।digestmod तर्क Python 3.4 से अनिवार्य है और कोई भी hashlib निर्माणकर्ता (जैसे hashlib.sha256) या स्ट्रिंग नाम जैसे "sha256" स्वीकार करता है।
import hmac
import hashlib
key = b"webhook_signing_key_2026"
message = b'{"event":"invoice.paid","invoice_id":"inv_8f3a","amount":19900}'
# HMAC ऑब्जेक्ट बनाएं और हेक्स हस्ताक्षर प्राप्त करें
signature = hmac.new(key, message, hashlib.sha256).hexdigest()
print(signature)
# "b4e74f6c9a1d3e5f8b2a7c0d4e6f1a3b5c7d9e0f2a4b6c8d0e1f3a5b7c9d0e2f"HMAC ऑब्जेक्ट दो आउटपुट मेथड प्रदान करता है। .digest() कच्चे बाइट्स लौटाता है (SHA-256 के लिए 32 बाइट, SHA-512 के लिए 64)। .hexdigest() लोअरकेस हेक्स स्ट्रिंग लौटाता है। हेक्स स्ट्रिंग एक सामान्य Python str है — कोई डीकोडिंग चरण आवश्यक नहीं।
import hmac import hashlib key = b"service_auth_key" msg = b"GET /api/v2/orders 2026-03-28T14:30:00Z" h = hmac.new(key, msg, hashlib.sha256) raw_bytes = h.digest() print(type(raw_bytes), len(raw_bytes)) # <class 'bytes'> 32 hex_string = h.hexdigest() print(type(hex_string), len(hex_string)) # <class 'str'> 64 # दोनों समान डेटा दर्शाते हैं — हेक्स बाइट्स की स्ट्रिंग एन्कोडिंग मात्र है assert raw_bytes.hex() == hex_string
यदि आपकी कुंजी या संदेश Python स्ट्रिंग है, तो उसे hmac.new() को पास करने से पहले bytes में बदलने के लिए .encode() कॉल करें। यह लगभग हर किसी को पहली बार उलझाता है — Python 3 की स्ट्रिंग Unicode होती हैं, bytes नहीं, और hmac मॉड्यूल उन्हें अस्वीकार करता है।
import hmac
import hashlib
# स्ट्रिंग कुंजी और संदेश — .encode() UTF-8 bytes में बदलता है
api_key = "sk_live_9f3a2b7c4d8e"
request_body = '{"customer_id":"cust_4421","plan":"enterprise"}'
signature = hmac.new(
api_key.encode(),
request_body.encode(),
hashlib.sha256
).hexdigest()
print(signature)
# "3a9f1b..." — सुसंगत हेक्स स्ट्रिंग आउटपुटdigestmod पैरामीटर का Python 3.4 से कोई डिफ़ॉल्ट नहीं है। बिना इसके hmac.new(key, msg) कॉल करने पर TypeError उठती है। 3.4 से पहले यह MD5 पर डिफ़ॉल्ट था, इसीलिए Python अनुरक्षकों ने डिफ़ॉल्ट हटाया — आपको स्पष्ट, सुरक्षित विकल्प चुनने पर बाध्य करने के लिए।HMAC-SHA256 Base64, SHA-1, SHA-512, और MD5
hmac.new() फ़ंक्शन hashlib में उपलब्ध किसी भी हैश एल्गोरिदम के साथ काम करता है। अधिकांश webhook प्रदाता और API गेटवे HMAC-SHA256 उपयोग करते हैं, लेकिन OAuth 1.0a में SHA-1, कुछ प्रोटोकॉल में SHA-512, और पुराने सिस्टम में MD5 भी मिलते हैं।
Base64 आउटपुट के साथ HMAC-SHA256
कई webhook प्रदाता हस्ताक्षर को HTTP हेडर में Base64-एन्कोडेड स्ट्रिंग के रूप में भेजते हैं। समान प्रारूप उत्पन्न करने के लिए, कच्चे .digest() बाइट्स को base64.b64encode() को पास करें।
import hmac
import hashlib
import base64
key = b"whsec_MbkP7x9yFqHGn3tRdWz5"
payload = b'{"id":"evt_1Nq","type":"charge.succeeded","data":{"amount":4200}}'
# कच्चा डाइजेस्ट → Base64 (Authorization हेडर और webhook हस्ताक्षरों के लिए सामान्य)
raw_digest = hmac.new(key, payload, hashlib.sha256).digest()
b64_signature = base64.b64encode(raw_digest).decode("ascii")
print(b64_signature)
# "dGhpcyBpcyBhIHNhbXBsZSBzaWduYXR1cmU="
# यह वह मान है जिसे X-Signature हेडर से तुलना करेंगे
header_value = f"sha256={b64_signature}"
print(header_value)
# "sha256=dGhpcyBpcyBhIHNhbXBsZSBzaWduYXR1cmU="HMAC-SHA1 — पुरानी प्रोटोकॉल संगतता
नए डिज़ाइन के लिए SHA-1 को कमज़ोर माना जाता है, लेकिन OAuth 1.0a और कुछ पुराने webhook कार्यान्वयन में HMAC-SHA1 आवश्यक है। कोड बिल्कुल वही है — केवल एल्गोरिदम बदलें।
import hmac
import hashlib
consumer_secret = b"oauth_consumer_secret_2026"
token_secret = b"oauth_token_secret_2026"
# OAuth 1.0a signing key के रूप में consumer_secret&token_secret उपयोग करता है
signing_key = consumer_secret + b"&" + token_secret
base_string = b"GET&https%3A%2F%2Fapi.service.com%2Fv1%2Forders&oauth_nonce%3D7f3a91bc"
sig = hmac.new(signing_key, base_string, hashlib.sha1).digest()
import base64
oauth_signature = base64.b64encode(sig).decode("ascii")
print(oauth_signature)
# "Tza3R9sE..." — Authorization हेडर के लिए इसे URL-एन्कोड करेंHMAC-SHA512 — लंबा आउटपुट
import hmac
import hashlib
key = b"high_security_signing_key_64_bytes_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
msg = b'{"transfer_id":"xfr_9c2e","amount":500000,"currency":"EUR"}'
h = hmac.new(key, msg, hashlib.sha512)
print(len(h.digest())) # 64 बाइट (512 बिट)
print(len(h.hexdigest())) # 128 हेक्स वर्ण
print(h.hexdigest()[:40] + "...")
# "8e3a1f9b2c4d6e7f0a1b3c5d7e9f0a2b4c6d8e0f..."HMAC-MD5 — केवल पुरानी प्रणालियों के लिए
import hmac import hashlib # MD5 क्रिप्टोग्राफ़िक रूप से टूटा है — केवल पुरानी प्रोटोकॉल संगतता के लिए उपयोग करें key = b"legacy_api_key" msg = b"action=charge&amount=1500&merchant=store_42" sig = hmac.new(key, msg, hashlib.md5).hexdigest() print(sig) # 32-वर्ण हेक्स स्ट्रिंग # "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6"
hmac.new() पैरामीटर संदर्भ
निर्माणकर्ता का हस्ताक्षर है hmac.new(key, msg=None, digestmod). मॉड्यूल के तीनों फ़ंक्शन कुंजी और एल्गोरिदम तर्कों के लिए समान पैटर्न साझा करते हैं।
hmac.new() निर्माणकर्ता
hmac.digest() एकबारगी (Python 3.7+)
digestmod पैरामीटर callable (जैसे hashlib.sha256) या स्ट्रिंग नाम (जैसे "sha256") दोनों स्वीकार करता है। callable रूप को प्राथमिकता दी जाती है क्योंकि इसे आयात के समय सत्यापित किया जाता है — स्ट्रिंग रूप में टाइपो केवल रनटाइम पर विफल होता है।
hmac.digest() — तेज़ एकबारगी HMAC (Python 3.7+)
Python 3.7 ने hmac.digest(key, msg, digest) को मॉड्यूल-स्तर फ़ंक्शन के रूप में जोड़ा। यह मध्यवर्ती HMAC ऑब्जेक्ट बनाए बिना एक ही कॉल में HMAC उत्पन्न करता है। वापसी मान कच्चे बाइट्स हैं (ऑब्जेक्ट पर .digest() कॉल करने के समान)। यह फ़ंक्शन CPython पर अनुकूलित C कार्यान्वयन उपयोग करता है और ऑब्जेक्ट आवंटन ओवरहेड से बचता है, जिससे सघन लूप में यह मापनीय रूप से तेज़ होता है।
import hmac
import hashlib
key = b"batch_signing_key_2026"
messages = [
b'{"order_id":"ord_001","total":4500}',
b'{"order_id":"ord_002","total":8900}',
b'{"order_id":"ord_003","total":2200}',
]
# एकबारगी डाइजेस्ट — कोई मध्यवर्ती HMAC ऑब्जेक्ट नहीं
signatures = [hmac.digest(key, msg, hashlib.sha256) for msg in messages]
# प्रदर्शन के लिए हेक्स में बदलें
for msg, sig in zip(messages, signatures):
print(f"{msg[:30]}... -> {sig.hex()[:24]}...")सीमा: hmac.digest() केवल कच्चे बाइट्स लौटाता है। यदि आपको सीधे हेक्स स्ट्रिंग चाहिए, तो आपको अभी भी hmac.new() की .hexdigest() मेथड की आवश्यकता है, या bytes result पर .hex() chain करें।
hmac.digest() incremental .update() calls support नहीं करता। अगर आप किसी बड़ी file को chunks में पढ़ रहे हैं और उसका HMAC चाहिए, तो hmac.new() उपयोग करें और लूप में .update(chunk) कॉल करें।Webhook और API प्रतिक्रिया से HMAC हस्ताक्षर सत्यापित करें
Python में HMAC का सबसे सामान्य उपयोग webhook हस्ताक्षर सत्यापन है। हर प्रमुख प्रदाता (Stripe, GitHub, Shopify, Twilio) पेलोड पर HMAC-SHA256 से हस्ताक्षर करता है और हस्ताक्षर एक हेडर में भेजता है। पैटर्न हमेशा समान है: कच्चे अनुरोध बॉडी पर HMAC पुनः उत्पन्न करें, फिर hmac.compare_digest() से तुलना करें।
Webhook हस्ताक्षर सत्यापन
import hmac
import hashlib
from flask import Flask, request, abort
app = Flask(__name__)
WEBHOOK_SECRET = b"whsec_MbkP7x9yFqHGn3tRdWz5"
@app.route("/webhooks/payments", methods=["POST"])
def handle_payment_webhook():
# कच्चा बॉडी प्राप्त करें — हस्ताक्षरित सामग्री से बिल्कुल मेल खाना चाहिए
raw_body = request.get_data()
# हेडर से हस्ताक्षर प्राप्त करें
received_sig = request.headers.get("X-Signature-256", "")
# कच्चे बॉडी पर HMAC पुनः उत्पन्न करें
expected_sig = hmac.new(WEBHOOK_SECRET, raw_body, hashlib.sha256).hexdigest()
# स्थिर-समय तुलना — टाइमिंग हमलों से बचाव
if not hmac.compare_digest(f"sha256={expected_sig}", received_sig):
abort(403, "Invalid signature")
# हस्ताक्षर सत्यापित — इवेंट संसाधित करें
event = request.get_json()
print(f"Verified event: {event['type']} for {event['data']['amount']}")
return "", 200hmac.compare_digest() फ़ंक्शन दो स्ट्रिंग या बाइट अनुक्रमों की स्थिर समय में तुलना करता है। सामान्य == तुलना पहले असमान बाइट पर शॉर्ट-सर्किट करती है। आक्रमणकर्ता अनेक अनुरोधों में प्रतिक्रिया समय मापकर अपेक्षित हस्ताक्षर को बाइट-दर-बाइट पुनर्निर्मित कर सकता है। स्थिर-समय तुलना इस साइड चैनल को समाप्त करती है।
GitHub Webhook सत्यापन
GitHub का webhook प्रारूप पूर्ण पैटर्न को दर्शाता है। यह एक X-Hub-Signature-256 हेडर भेजता है जिसमें sha256= के बाद आपके रिपॉज़िटरी सेटिंग में कॉन्फ़िगर किए गए webhook गोपनीय से हस्ताक्षरित कच्चे अनुरोध बॉडी का हेक्स-एन्कोडेड HMAC-SHA256 होता है। सामान्य webhook सत्यापन से मुख्य अंतर यह है कि तुलना से पहले आपको sha256= उपसर्ग हटाना होगा, और आपको अनुरोध बॉडी के कच्चे बाइट्स पढ़ने होंगे — पहले JSON पार्स करने से बाइट प्रतिनिधित्व बदल जाता है और सत्यापन विफल हो जाता है।
import hmac
import hashlib
from flask import Flask, request, abort
app = Flask(__name__)
GITHUB_WEBHOOK_SECRET = b"your_github_webhook_secret"
@app.route("/webhooks/github", methods=["POST"])
def handle_github_webhook():
# GitHub भेजता है: X-Hub-Signature-256: sha256=<hex_digest>
sig_header = request.headers.get("X-Hub-Signature-256", "")
if not sig_header.startswith("sha256="):
abort(403, "Missing or malformed signature header")
received_hex = sig_header[len("sha256="):]
raw_body = request.get_data() # कच्चे बाइट्स — इससे पहले JSON पार्स न करें
expected_hex = hmac.new(
GITHUB_WEBHOOK_SECRET, raw_body, hashlib.sha256
).hexdigest()
if not hmac.compare_digest(expected_hex, received_hex):
abort(403, "Signature mismatch — payload may have been tampered with")
event_type = request.headers.get("X-GitHub-Event", "unknown")
payload = request.get_json()
print(f"Verified GitHub {event_type} event: {payload.get('action', '')}")
return "", 200यही पैटर्न Shopify (X-Shopify-Hmac-SHA256) और Twilio (X-Twilio-Signature) पर भी लागू होता है, केवल हेडर नाम और हस्ताक्षर हेक्स है या Base64-एन्कोडेड यह अंतर होता है। एन्कोडिंग प्रारूप की पुष्टि के लिए हमेशा प्रदाता के दस्तावेज़ देखें — हेक्स और Base64 को मिलाना हस्ताक्षर बेमेल त्रुटियों का सबसे सामान्य कारण है।
HMAC से API अनुरोध प्रमाणीकरण
कुछ API क्लाइंट से प्रत्येक अनुरोध पर HMAC से हस्ताक्षर करने की आवश्यकता होती है। हस्ताक्षरित स्ट्रिंग में सामान्यतः HTTP मेथड, पथ, टाइमस्टैंप और अनुरोध बॉडी शामिल होते हैं। यह internal service-to-service auth के लिए मैं यही pattern use करता हूँ।
import hmac
import hashlib
import time
import json
def sign_request(secret: bytes, method: str, path: str, body: str) -> dict:
"""API अनुरोध के लिए HMAC-SHA256 हस्ताक्षर उत्पन्न करें।"""
timestamp = str(int(time.time()))
# हस्ताक्षरण स्ट्रिंग बनाएं — method + path + timestamp + body
signing_string = f"{method}\n{path}\n{timestamp}\n{body}"
signature = hmac.new(
secret,
signing_string.encode(),
hashlib.sha256
).hexdigest()
return {
"X-Timestamp": timestamp,
"X-Signature": signature,
}
# उपयोग
api_secret = b"sk_hmac_9f3a2b7c4d8e1a6f"
body = json.dumps({"customer_id": "cust_4421", "action": "suspend_account"})
headers = sign_request(api_secret, "POST", "/api/v2/customers/actions", body)
print(headers)
# {"X-Timestamp": "1711612200", "X-Signature": "a3f1b9c0..."}requests लाइब्रेरी से HTTP अनुरोध हस्ताक्षरित करना
import hmac
import hashlib
import time
import json
import requests
API_SECRET = b"sk_hmac_9f3a2b7c4d8e1a6f"
BASE_URL = "https://api.billing-service.internal"
def make_signed_request(method: str, path: str, payload: dict) -> requests.Response:
body = json.dumps(payload, separators=(",", ":")) # संक्षिप्त JSON, निर्धारणात्मक
timestamp = str(int(time.time()))
signing_string = f"{method}\n{path}\n{timestamp}\n{body}"
signature = hmac.new(API_SECRET, signing_string.encode(), hashlib.sha256).hexdigest()
headers = {
"Content-Type": "application/json",
"X-Timestamp": timestamp,
"X-Signature": f"hmac-sha256={signature}",
}
try:
return requests.request(method, f"{BASE_URL}{path}", data=body, headers=headers)
except requests.RequestException as e:
raise RuntimeError(f"Signed request failed: {e}") from e
# हस्ताक्षरित POST अनुरोध भेजें
resp = make_signed_request("POST", "/api/v2/invoices", {
"customer_id": "cust_4421",
"line_items": [
{"description": "Pro plan - March 2026", "amount": 4900},
{"description": "Extra seats (3)", "amount": 2100},
],
})
print(resp.status_code, resp.json())एक त्वरित टिप्पणी: हस्ताक्षरण के लिए बॉडी क्रमबद्ध करते समय separators=(",", ":") उपयोग करें। डिफ़ॉल्ट json.dumps() विभाजकों के बाद रिक्त स्थान जोड़ता है, जिससे बाइट प्रतिनिधित्व बदल जाता है और सर्वर के भिन्न क्रमबद्धता पर हस्ताक्षर सत्यापन विफल हो जाता है। संक्षिप्त JSON एक विहित रूप देता है।
कमांड-लाइन से HMAC उत्पन्न करना
कभी-कभी स्क्रिप्ट लिखे बिना HMAC उत्पन्न करना होता है। Python का -c फ़्लैग और openssl दोनों टर्मिनल से यह कार्य संभालते हैं।
python3 -c " import hmac, hashlib print(hmac.new(b'my_secret', b'message_to_sign', hashlib.sha256).hexdigest()) " # आउटपुट: 64-वर्ण हेक्स स्ट्रिंग
echo -n "message_to_sign" | openssl dgst -sha256 -hmac "my_secret" # SHA2-256(stdin)= 7d11... # openssl HMAC से फ़ाइल पाइप करें openssl dgst -sha256 -hmac "my_secret" < payload.json
# शेल इतिहास में उजागर होने से बचाने के लिए कुंजी को env var में संग्रहीत करें
export HMAC_KEY="sk_live_9f3a2b"
echo -n '{"event":"test"}' | python3 -c "
import hmac, hashlib, sys, os
key = os.environ['HMAC_KEY'].encode()
msg = sys.stdin.buffer.read()
print(hmac.new(key, msg, hashlib.sha256).hexdigest())
"echo -n फ़्लैग अनिवार्य है — इसके बिना echo संदेश में नई लाइन वर्ण जोड़ता है, जिससे HMAC आउटपुट बदल जाता है। टर्मिनल से डीबग करते समय हस्ताक्षर बेमेल का यह सबसे सामान्य कारण है।उच्च-प्रदर्शन विकल्प — cryptography लाइब्रेरी
अधिकांश अनुप्रयोगों के लिए, मानक hmac मॉड्यूल पर्याप्त तेज़ है। यदि आप TLS या प्रमाणपत्र प्रबंधन के लिए पहले से cryptography लाइब्रेरी उपयोग कर रहे हैं, तो यह OpenSSL-समर्थित HMAC भी प्रदान करती है। stdlib से मुख्य व्यावहारिक अंतर नीचे वर्णित अपवाद-आधारित .verify() API है — यह बेमेल पर बूलियन लौटाने के बजाय अपवाद उठाता है जिसे डेवलपर भूलकर अनदेखा कर सकता है।
pip install cryptography
from cryptography.hazmat.primitives import hashes, hmac as crypto_hmac
key = b"webhook_signing_key_2026"
message = b'{"event":"subscription.renewed","plan":"enterprise"}'
h = crypto_hmac.HMAC(key, hashes.SHA256())
h.update(message)
signature = h.finalize() # कच्चे बाइट्स
print(signature.hex())
# "9c4e2a..."
# सत्यापन मोड — बेमेल पर InvalidSignature उठाता है
h_verify = crypto_hmac.HMAC(key, hashes.SHA256())
h_verify.update(message)
h_verify.verify(signature) # गलत होने पर cryptography.exceptions.InvalidSignature उठाता हैcryptography लाइब्रेरी की .verify() मेथड विशेष रूप से उपयोगी है: बूलियन लौटाने के बजाय बेमेल पर अपवाद उठाती है। इससे सत्यापन विफलता को गलती से अनदेखा करना कठिन हो जाता है। मानक लाइब्रेरी का hmac.compare_digest() True/ False लौटाता है, जिसे डेवलपर वापसी मान जांचना भूल जाने पर चुपचाप अनदेखा किया जा सकता है।
सिंटैक्स हाइलाइटिंग के साथ टर्मिनल आउटपुट
यदि आप टर्मिनल में HMAC हस्ताक्षर डीबग कर रहे हैं और रंगीन आउटपुट चाहते हैं, तो rich इसे अच्छी तरह संभालता है।
pip install rich
import hmac
import hashlib
from rich.console import Console
from rich.table import Table
console = Console()
key = b"debug_signing_key"
messages = {
"/api/v2/orders": b'{"status":"active"}',
"/api/v2/invoices": b'{"status":"pending"}',
"/api/v2/customers": b'{"status":"verified"}',
}
table = Table(title="HMAC-SHA256 Signatures")
table.add_column("Endpoint", style="cyan")
table.add_column("Signature (first 32 chars)", style="green")
for endpoint, body in messages.items():
sig = hmac.new(key, body, hashlib.sha256).hexdigest()
table.add_row(endpoint, sig[:32] + "...")
console.print(table)बड़ी फ़ाइलों के साथ कार्य — वृद्धिशील HMAC
लगभग 50 MB से बड़ी files के लिए, सिर्फ HMAC के लिए पूरी file को memory में load करना wasteful है। HMAC ऑब्जेक्ट पर .update() मेथड आपको खंडों में डेटा फ़ीड करने देता है। इससे फ़ाइल आकार चाहे कितना भी हो, मेमोरी उपयोग स्थिर रहता है।
import hmac
import hashlib
def hmac_file(key: bytes, filepath: str, chunk_size: int = 8192) -> str:
"""फ़ाइल को पूरी तरह मेमोरी में लोड किए बिना उसका HMAC-SHA256 उत्पन्न करें।"""
h = hmac.new(key, digestmod=hashlib.sha256)
try:
with open(filepath, "rb") as f:
while True:
chunk = f.read(chunk_size)
if not chunk:
break
h.update(chunk)
except OSError as e:
raise OSError(f"Cannot read file '{filepath}': {e}") from e
return h.hexdigest()
# 2 GB डेटाबेस निर्यात पर हस्ताक्षर करें
signing_key = b"backup_integrity_key_2026"
signature = hmac_file(signing_key, "/var/backups/db-export-2026-03.sql.gz")
print(f"HMAC-SHA256: {signature}")import hmac
import hashlib
def verify_file_hmac(key: bytes, filepath: str, expected_hex: str) -> bool:
"""किसी फ़ाइल का HMAC-SHA256 हस्ताक्षर सत्यापित करें।"""
h = hmac.new(key, digestmod=hashlib.sha256)
with open(filepath, "rb") as f:
for chunk in iter(lambda: f.read(65536), b""):
h.update(chunk)
return hmac.compare_digest(h.hexdigest(), expected_hex)
# डाउनलोड किए गए आर्टिफ़ैक्ट को सत्यापित करें
is_valid = verify_file_hmac(
key=b"release_signing_key",
filepath="/tmp/release-v3.2.0.tar.gz",
expected_hex="8e3a1f9b2c4d6e7f0a1b3c5d7e9f0a2b4c6d8e0f1a2b3c4d5e6f7a8b9c0d1e2f",
)
print(f"File integrity: {'valid' if is_valid else 'CORRUPTED'}").update() दृष्टिकोण फ़ाइल आकार की परवाह किए बिना निश्चित chunk_size मेमोरी उपयोग करता है। मैं 64 KB खंड डिफ़ॉल्ट रखता हूँ — सिस्टम कॉल ओवरहेड को संतुलित करने के लिए पर्याप्त बड़ा, अधिकांश हार्डवेयर पर L2 कैश के भीतर रहने के लिए पर्याप्त छोटा।Python में क्रिप्टोग्राफ़िक रूप से सुरक्षित HMAC कुंजी उत्पन्न करें
कमज़ोर या अनुमानित कुंजी पूरी HMAC संरचना को कमज़ोर कर देती है। secrets मॉड्यूल (Python 3.6+) क्रिप्टोग्राफ़िक रूप से मज़बूत यादृच्छिक बाइट्स प्रदान करता है। HMAC-SHA256 के लिए 32-बाइट कुंजी उपयोग करें। HMAC-SHA512 के लिए 64 बाइट उपयोग करें। ये RFC 2104 के अनुसार संबंधित हैश एल्गोरिदम के आंतरिक ब्लॉक आकार से मेल खाते हैं जो इष्टतम कुंजी लंबाई है।
import secrets
# हैश एल्गोरिदम के ब्लॉक आकार से मेल खाती कुंजियाँ उत्पन्न करें
sha256_key = secrets.token_bytes(32) # 256 बिट — HMAC-SHA256 के लिए
sha512_key = secrets.token_bytes(64) # 512 बिट — HMAC-SHA512 के लिए
# हेक्स प्रतिनिधित्व — कॉन्फ़िगरेशन फ़ाइलों और पर्यावरण चर के लिए सुरक्षित
print(f"HMAC-SHA256 key: {sha256_key.hex()}")
# उदाहरण: "a3f1b9c04e7d2f8a1b3c5d7e9f0a2b4c6d8e0f1a2b3c4d5e6f7a8b9c0d1e2f"
print(f"HMAC-SHA512 key: {sha512_key.hex()}")
# 128-वर्ण हेक्स स्ट्रिंग
# URL-सुरक्षित Base64 — संक्षिप्त, HTTP हेडर के लिए उपयुक्त
import base64
b64_key = base64.urlsafe_b64encode(sha256_key).decode("ascii")
print(f"Base64 key: {b64_key}")
# उदाहरण: "o_G5wE59L4obPF1-nwortG2ODwobPExdXnqLnA0dLi8="random मॉड्यूल से random.random() या random.randbytes() कभी उपयोग न करें। डिफ़ॉल्ट random मॉड्यूल Mersenne Twister PRNG उपयोग करता है जो 624 आउटपुट देखने के बाद अनुमानित हो जाता है। सुरक्षा-संवेदनशील यादृच्छिकता के लिए हमेशा secrets.token_bytes() उपयोग करें।कुंजी लंबाई और RFC 2104 की आवश्यकताएं
RFC 2104 निर्दिष्ट करता है कि HMAC कुंजी किसी भी लंबाई की हो सकती है, लेकिन न्यूनतम L बाइट की कुंजी अनुशंसित है — जहाँ L अंतर्निहित हैश फ़ंक्शन की आउटपुट लंबाई है। HMAC-SHA256 के लिए यह 32 बाइट (256 बिट) है। L बिट से छोटी कुंजियाँ आनुपातिक रूप से सुरक्षा मार्जिन कम करती हैं। हैश के ब्लॉक आकार (SHA-256 के लिए 64 बाइट, SHA-512 के लिए 128 बाइट) से लंबी कुंजियाँ पहले ब्लॉक आकार तक हैश कर दी जाती हैं, इसलिए ब्लॉक आकार से लंबी कुंजियाँ उपयोग करने का कोई लाभ नहीं। HMAC-SHA256 के लिए 32 बाइट और HMAC-SHA512 के लिए 64 बाइट पर बने रहें।
सुरक्षित कुंजी भंडारण और रोटेशन
HMAC कुंजियाँ कभी स्रोत कोड में हार्डकोड न करें। उत्पादन परिनियोजन के लिए मानक दृष्टिकोण स्टार्टअप पर पर्यावरण चर से कुंजी लोड करना है: os.environ["HMAC_SECRET"].encode(). उच्च-आश्वासन वातावरण के लिए, AWS Secrets Manager, HashiCorp Vault, या GCP Secret Manager जैसी गोपनीय प्रबंधन प्रणाली में कुंजियाँ संग्रहीत करें और उन्हें रनटाइम पर प्राप्त करें। ये सिस्टम ऑडिट लॉग, अभिगम नियंत्रण और कोड परिनियोजन के बिना स्वचालित रोटेशन प्रदान करते हैं।
शुरू से ही कुंजी रोटेशन की योजना बनाएं। जब कुंजी रोटेट होती है, तो एक समय-खिड़की होती है जब उड़ान में अनुरोध पुरानी कुंजी से हस्ताक्षरित थे और नई कुंजी से सत्यापन में विफल होंगे। मानक समाधान एक संक्षिप्त ओवरलैप अवधि है: थोड़े समय (मिनटों से घंटों तक) के लिए पुरानी और नई दोनों कुंजियों से हस्ताक्षर स्वीकार करें, फिर पुरानी कुंजी सेवानिवृत्त करें। यदि कोई कुंजी समझौता हो — लॉग में उजागर, git कमिट में लीक, या किसी घटना में प्रकट — तो तुरंत रोटेट करें और समझौता की गई कुंजी से उत्पन्न सभी हस्ताक्षरों को अविश्वसनीय मानें। कैश किए गए verification results को फिर से validate करें और key change के बारे में downstream consumers को notify करें।
hmac.new() के साथ bytearray और memoryview का उपयोग
hmac.new() फ़ंक्शन key और msg दोनों पैरामीटर के लिए कोई भी bytes-like ऑब्जेक्ट स्वीकार करता है। इसका अर्थ है कि आप प्रतिलिपि या रूपांतरण के बिना सीधे bytes, bytearray, या memoryview पास कर सकते हैं। यह दो परिदृश्यों में सबसे अधिक मायने रखता है: नेटवर्क प्रोटोकॉल कार्यान्वयन जहाँ socket.recv_into() पूर्व-आवंटित bytearray बफ़र में डेटा लिखता है, और उच्च-थ्रूपुट सिस्टम जहाँ मध्यवर्ती प्रतिलिपियाँ हटाने से GC दबाव कम होता है। memoryview खंड शून्य-प्रतिलिपि है: यह नई मेमोरी आवंटित किए बिना मूल बफ़र में एक खिड़की उजागर करता है। प्रति सेकंड दसियों हज़ार संदेशों पर, वे आवंटन हटाने से विलंबता और थ्रूपुट में मापनीय अंतर आता है।
import hmac
import hashlib
# bytearray — परिवर्तनीय बाइट्स, बाइनरी प्रोटोकॉल बफ़र के लिए उपयोगी
key = bytearray(b"protocol_signing_key")
frame = bytearray(b'\x01\x02\x03\x04payload_data_here')
sig = hmac.new(key, frame, hashlib.sha256).hexdigest()
print(f"Frame signature: {sig[:32]}...")
# memoryview — बड़े बफ़र का शून्य-प्रतिलिपि खंड
large_buffer = bytearray(4096)
large_buffer[:20] = b"sensor_reading_12345"
# प्रतिलिपि किए बिना केवल पहले 20 बाइट का HMAC
view = memoryview(large_buffer)[:20]
sig = hmac.new(key, view, hashlib.sha256).hexdigest()
print(f"Sensor signature: {sig[:32]}...")सामान्य गलतियाँ
पहली दो गलतियाँ मुझे webhook हैंडलर संबंधी लगभग हर कोड समीक्षा में दिखती हैं। समय दबाव में इन्हें करना आसान और बिना जाने खोजना कठिन है।
समस्या: == संचालक पहले बाइट बेमेल पर शॉर्ट-सर्किट करता है, टाइमिंग जानकारी लीक करता है जिससे आक्रमणकर्ता अपेक्षित हस्ताक्षर को क्रमिक रूप से पुनर्निर्मित कर सकता है।
समाधान: हस्ताक्षर तुलना के लिए हमेशा hmac.compare_digest() उपयोग करें — यह बेमेल चाहे कहीं भी हो, स्थिर समय में चलता है।
received_sig = request.headers["X-Signature"]
expected_sig = hmac.new(key, body, hashlib.sha256).hexdigest()
if received_sig == expected_sig: # टाइमिंग हमले के प्रति असुरक्षित
process_webhook(body)received_sig = request.headers["X-Signature"]
expected_sig = hmac.new(key, body, hashlib.sha256).hexdigest()
if hmac.compare_digest(received_sig, expected_sig): # स्थिर-समय
process_webhook(body)समस्या: hmac.new() को bytes-like ऑब्जेक्ट आवश्यक है। Python str पास करने पर TypeError उठती है: "key: expected bytes or bytearray, but got 'str'".
समाधान: hmac.new() को पास करने से पहले स्ट्रिंग कुंजियों और संदेशों पर .encode() कॉल करें।
key = "my_api_secret" # str, bytes नहीं
msg = '{"event":"test"}' # str, bytes नहीं
sig = hmac.new(key, msg, hashlib.sha256) # TypeError!key = "my_api_secret"
msg = '{"event":"test"}'
sig = hmac.new(key.encode(), msg.encode(), hashlib.sha256)समस्या: तीसरे तर्क के बिना hmac.new(key, msg) कॉल करने पर TypeError उठती है। Python 3.4 से पहले यह MD5 पर डिफ़ॉल्ट था, लेकिन सुरक्षा कारणों से डिफ़ॉल्ट हटा दिया गया।
समाधान: हमेशा एल्गोरिदम स्पष्ट रूप से पास करें: hashlib.sha256, hashlib.sha512, या आपके प्रोटोकॉल की आवश्यकता हो।
# digestmod नहीं — Python 3.4+ में TypeError उठाता है sig = hmac.new(key, msg).hexdigest()
# हमेशा हैश एल्गोरिदम निर्दिष्ट करें sig = hmac.new(key, msg, hashlib.sha256).hexdigest()
समस्या: कई webhook प्रदाता (Stripe, Shopify) Base64-एन्कोडेड हस्ताक्षर भेजते हैं, हेक्स नहीं। हेक्स स्ट्रिंग की Base64 मान से तुलना हमेशा विफल होती है, जिससे सभी webhook अस्वीकृत हो जाते हैं।
समाधान: हस्ताक्षर प्रारूप के लिए प्रदाता के दस्तावेज़ देखें। यदि वे Base64 उपयोग करते हैं, तो .hexdigest() स्ट्रिंग नहीं बल्कि कच्चे .digest() बाइट्स एन्कोड करें।
# प्रदाता Base64 भेजता है, लेकिन हम हेक्स उत्पन्न करते हैं — कभी मेल नहीं खाता expected = hmac.new(key, body, hashlib.sha256).hexdigest() # "a3f1b9c0..." बनाम "o/G5wE59..." — हमेशा बेमेल
import base64
# प्रदाता का प्रारूप मिलाएं: कच्चे बाइट्स → Base64
raw = hmac.new(key, body, hashlib.sha256).digest()
expected = base64.b64encode(raw).decode("ascii")
# "o/G5wE59..." — हेडर से मेल खाता हैstdlib hmac बनाम cryptography — त्वरित तुलना
webhook सत्यापन, API हस्ताक्षरण, और सामान्य HMAC संचालन के लिए stdlib hmac मॉड्यूल उपयोग करें — इसकी शून्य निर्भरताएं हैं और यह हर मानक एल्गोरिदम को कवर करता है। बैच संचालन के लिए जहाँ एकबारगी गति मायने रखती है वहाँ hmac.digest() उपयोग करें। cryptography लाइब्रेरी केवल तब उपयोग करें जब आप पहले से इस पर अन्य संचालन (TLS, X.509, सममित एन्क्रिप्शन) के लिए निर्भर हों और अपवाद-आधारित .verify() API चाहते हों। बिना कोई Python लिखे त्वरित हस्ताक्षर जांच के लिए, HMAC जनरेटर टूल में अपनी कुंजी और संदेश चिपकाएं और तुरंत परिणाम पाएं।
अक्सर पूछे जाने वाले प्रश्न
Python में hmac.new() और hmac.digest() में क्या अंतर है?
hmac.new() एक HMAC object return करता है जो incremental .update() calls support करता है और .digest() (raw bytes) तथा .hexdigest() (hex string) दोनों देता है। hmac.digest() Python 3.7 में जोड़ा गया one-shot function है जो intermediate object बनाए बिना सीधे raw bytes return करता है। जब पूरा message एक साथ हो और सिर्फ result चाहिए तो hmac.digest() use करें। जब chunks में data feed करना हो या hex output चाहिए तो hmac.new() use करें।
import hmac, hashlib
key = b"webhook_secret_2026"
body = b'{"event":"payment.completed","amount":9950}'
# एकबारगी — कच्चे बाइट्स लौटाता है
raw = hmac.digest(key, body, hashlib.sha256)
# object-based — incremental .update() और hex output support करता है
h = hmac.new(key, body, hashlib.sha256)
hex_sig = h.hexdigest()Python में HMAC हस्ताक्षर कैसे सत्यापित करें?
साझा गोपनीय कुंजी का उपयोग करके मूल संदेश पर HMAC पुनः उत्पन्न करें, फिर hmac.compare_digest() से तुलना करें। हस्ताक्षर तुलना के लिए कभी == उपयोग न करें। == संचालक पहले असमान बाइट पर शॉर्ट-सर्किट करता है, जिससे अपेक्षित हस्ताक्षर की लंबाई और सामग्री के बारे में जानकारी लीक होती है।
import hmac, hashlib
def verify_signature(secret: bytes, message: bytes, received_sig: str) -> bool:
expected = hmac.new(secret, message, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, received_sig)क्या Python hmac SHA-256 और hashlib.sha256 से हैश करना एक समान है?
नहीं। hashlib.sha256 इनपुट का सामान्य SHA-256 हैश उत्पन्न करता है जिसे कोई भी पुनः निर्मित कर सकता है। HMAC-SHA256 RFC 2104 के अनुसार हैश गणना में गोपनीय कुंजी मिलाता है, इसलिए केवल वही व्यक्ति सही आउटपुट उत्पन्न या सत्यापित कर सकता है जिसके पास कुंजी है। सामान्य हैश केवल अखंडता सिद्ध करता है। HMAC अखंडता और प्रामाणिकता दोनों सिद्ध करता है।
import hmac, hashlib msg = b"transfer:9950:USD" key = b"api_secret_k8x2" plain_hash = hashlib.sha256(msg).hexdigest() # कोई भी इसे उत्पन्न कर सकता है hmac_hash = hmac.new(key, msg, hashlib.sha256).hexdigest() # कुंजी आवश्यक है
क्या Python 3 में HMAC-SHA1 उपयोग किया जा सकता है?
हाँ, digestmod तर्क के रूप में hashlib.sha1 पास करें। HMAC-SHA1 Python 3 में ठीक काम करता है और hmac मॉड्यूल में इसके लिए कोई अप्रचलन चेतावनी नहीं है। लेकिन नए डिज़ाइन के लिए SHA-1 को कमज़ोर माना जाता है — इसकी टक्कर प्रतिरोध क्षमता 80 बिट से कम है और NIST ने 2015 में अधिकांश डिजिटल हस्ताक्षर उपयोग के लिए इसे अप्रचलित घोषित किया। आज HMAC-SHA1 का मुख्य कारण OAuth 1.0a जैसे पुराने प्रोटोकॉल के साथ पिछड़ी संगतता है। जब दोनों पक्षों पर नियंत्रण हो तो सभी नए कार्यों के लिए HMAC-SHA256 या HMAC-SHA512 का उपयोग करें।
import hmac, hashlib key = b"oauth_consumer_secret" base_string = b"GET&https%3A%2F%2Fapi.example.com&oauth_nonce%3Dabc123" sig = hmac.new(key, base_string, hashlib.sha1).digest()
Python में सुरक्षित HMAC कुंजी कैसे उत्पन्न करें?
मानक लाइब्रेरी से secrets.token_bytes() उपयोग करें। HMAC-SHA256 के लिए 32-बाइट कुंजी मानक अनुशंसा है क्योंकि यह हैश ब्लॉक आकार से मेल खाती है। HMAC-SHA512 के लिए 64 बाइट उपयोग करें। अनुप्रयोग कोड में कुंजी उत्पन्न करने के लिए random.random() या os.urandom() का उपयोग न करें — Python 3.6 से secrets सुरक्षा-संवेदनशील यादृच्छिकता के लिए सही मॉड्यूल है।
import secrets hmac_sha256_key = secrets.token_bytes(32) # 256 बिट hmac_sha512_key = secrets.token_bytes(64) # 512 बिट # कॉन्फ़िगरेशन फ़ाइलों के लिए हेक्स के रूप में संग्रहीत करें print(hmac_sha256_key.hex()) # उदाहरण: "a3f1b9c04e..."
Python 3 में hmac.new() को digestmod क्यों आवश्यक है?
Python 3.4 से पहले digestmod का डिफ़ॉल्ट MD5 था जो क्रिप्टोग्राफ़िक रूप से टूटा हुआ है — MD5 में ज्ञात टक्कर हमले हैं और इसे किसी भी नए सुरक्षा-संवेदनशील कोड में उपयोग नहीं किया जाना चाहिए। Python अनुरक्षकों ने डिफ़ॉल्ट हटाकर डेवलपर्स को स्पष्ट एल्गोरिदम चुनने पर बाध्य किया, ताकि वे अनजाने में MD5-आधारित MAC न भेजें। digestmod के बिना hmac.new(key, msg) कॉल करने पर TypeError मिलती है। हमेशा एल्गोरिदम स्पष्ट रूप से पास करें: hashlib.sha256, hashlib.sha512, या कोई अन्य hashlib निर्माणकर्ता। संदेह में hashlib.sha256 सुरक्षित डिफ़ॉल्ट है — कोई ज्ञात कमज़ोरी नहीं और किसी भी व्यावहारिक कार्यभार के लिए पर्याप्त तेज़।
import hmac, hashlib key = b"secret" msg = b"data" # Python 3.4+ में TypeError उठाता है # hmac.new(key, msg) # TypeError: missing required argument: 'digestmod' # हमेशा एल्गोरिदम निर्दिष्ट करें h = hmac.new(key, msg, hashlib.sha256)
Python स्क्रिप्ट चलाए बिना त्वरित HMAC जांच के लिए, अपनी कुंजी और संदेश ऑनलाइन HMAC जनरेटर में चिपकाएं — SHA-256, SHA-384, और SHA-512 का तत्काल समर्थन।
संबंधित टूल
Dmitri is a DevOps engineer who relies on Python as his primary scripting and automation language. He builds internal tooling, CI/CD pipelines, and infrastructure automation scripts that run in production across distributed teams. He writes about the Python standard library, subprocess management, file processing, encoding utilities, and the practical shell-adjacent Python that DevOps engineers use every day.
Maria is a backend developer specialising in Python and API integration. She has broad experience with data pipelines, serialisation formats, and building reliable server-side services. She is an active member of the Python community and enjoys writing practical, example-driven guides that help developers solve real problems without unnecessary theory.