ToolDeck

Python HMAC hmac.new() SHA-256

·DevOps Engineer & Python Automation Specialist·ตรวจสอบโดยMaria Santos·เผยแพร่เมื่อ

ใช้ เครื่องสร้าง HMAC ฟรีโดยตรงในเบราว์เซอร์ของคุณ — ไม่ต้องติดตั้ง

ลอง เครื่องสร้าง HMAC ออนไลน์ →

ทุก webhook callback ทุก API request ที่มีการเซ็น ทุกการแจ้งเตือน event จาก Stripe หรือ GitHub ล้วนใช้ HMAC signature เพื่อพิสูจน์ว่า payload ไม่ถูกดัดแปลง module hmac ของ Python จัดการ HMAC-SHA256 ใน Python ด้วย การเรียกฟังก์ชันเดียว: hmac.new(key, msg, hashlib.sha256). ไม่ต้อง pip install ไม่ต้อง C extension ไม่ต้องพึ่ง third-party สำหรับการตรวจสอบ signature แบบ one-off โดยไม่ต้องเขียนโค้ด เครื่องมือ HMAC Generator ออนไลน์ ให้ผลลัพธ์ได้ทันที คู่มือนี้ครอบคลุม hmac.new(), hmac.digest(), hmac.compare_digest(), การเข้ารหัส Base64, การตรวจสอบ webhook, การเซ็น API request และอัลกอริทึม hash ทุกตัวตั้งแต่ SHA-1 ถึง SHA-512 ตัวอย่างทั้งหมดใช้ Python 3.7+

  • hmac.new(key, msg, hashlib.sha256) คือ entry point มาตรฐาน — key และ msg ต้องเป็น bytes, digestmod บังคับตั้งแต่ Python 3.4
  • hmac.digest(key, msg, "sha256") คือทางเลือก one-shot ที่เร็วกว่า เพิ่มมาใน Python 3.7 — คืนค่า raw bytes ไม่ต้องสร้าง object กลาง
  • ตรวจสอบ signature ด้วย hmac.compare_digest() เสมอเพื่อป้องกัน timing attack — ห้ามใช้ == สำหรับการเปรียบเทียบ HMAC
  • เข้ารหัส raw .digest() output เป็น Base64 สำหรับ HTTP header และ webhook signature: base64.b64encode(h.digest())
  • module hmac รองรับ hashlib algorithm ทุกตัว: sha1, sha256, sha384, sha512, md5, blake2b

HMAC คืออะไร?

HMAC (Hash-based Message Authentication Code) คือโครงสร้างที่กำหนดใน RFC 2104 ที่ผสมคีย์ลับกับฟังก์ชัน hash เพื่อสร้าง authentication tag ขนาดคงที่ ต่างจาก plain hash (ที่ทุกคนสามารถคำนวณได้) HMAC ต้องการความรู้เกี่ยวกับคีย์ลับ ซึ่งหมายความว่าคุณสามารถใช้มันเพื่อตรวจสอบทั้งความสมบูรณ์และความถูกต้องของข้อความ หากแม้แต่หนึ่ง byte ของข้อความหรือคีย์เปลี่ยนแปลง output จะแตกต่างกันอย่างสิ้นเชิง โครงสร้างทำงานโดยการแฮชคีย์ที่ XOR กับค่าคงที่ padding สองตัว (ipad และ opad) โดยครอบข้อความระหว่างการดำเนินการ hash สองครั้ง module hmac ของ Python ใช้งาน RFC นี้โดยตรง

Before · Python
After · Python
# Plain SHA-256 hash — ไม่มีคีย์ลับ ทุกคนสามารถคำนวณได้
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() — Entry Point ของ Standard Library

module hmac เป็นส่วนหนึ่งของ Python standard library ต้อง import เพียงสองบรรทัดและพร้อมใช้งาน: import hmac, hashlib. ฟังก์ชันหลักสามตัวคือ hmac.new() (สร้าง HMAC object), hmac.digest() (one-shot Python 3.7+) และ hmac.compare_digest() (การเปรียบเทียบแบบ constant-time) ไม่ต้อง pip install

hmac.new(key, msg, digestmod) รับ argument สามตัว ทั้ง key และ msg ต้องเป็น bytes-like object ( bytes, bytearray หรือ memoryview). argument digestmod บังคับตั้งแต่ Python 3.4 และรับ hashlib constructor ใดก็ได้ (เช่น hashlib.sha256) หรือชื่อ string เช่น "sha256"

Python 3.7+ — ตัวอย่าง HMAC-SHA256 เบื้องต้น
import hmac
import hashlib

key = b"webhook_signing_key_2026"
message = b'{"event":"invoice.paid","invoice_id":"inv_8f3a","amount":19900}'

# สร้าง HMAC object และรับ hex signature
signature = hmac.new(key, message, hashlib.sha256).hexdigest()
print(signature)
# "b4e74f6c9a1d3e5f8b2a7c0d4e6f1a3b5c7d9e0f2a4b6c8d0e1f3a5b7c9d0e2f"

HMAC object มีเมธอด output สองตัว .digest() คืนค่า raw bytes (32 bytes สำหรับ SHA-256, 64 สำหรับ SHA-512) .hexdigest() คืนค่า hex string พิมพ์เล็ก hex string เป็น Python str ธรรมดา — ไม่ต้องผ่านขั้นตอน decode

Python 3.7+ — .digest() เทียบกับ .hexdigest()
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

# ทั้งสองแทนข้อมูลเดียวกัน — hex คือ string encoding ของ bytes
assert raw_bytes.hex() == hex_string

หาก key หรือ message เป็น Python string ให้เรียก .encode() เพื่อแปลงเป็น bytes ก่อนส่งเข้า hmac.new()เรื่องนี้ทำให้เกือบทุกคนสะดุดในครั้งแรก — Python 3 string เป็น Unicode ไม่ใช่ bytes และ module hmac จะปฏิเสธ string

Python 3.7+ — การแปลง string เป็น bytes
import hmac
import hashlib

# String key และ message — .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..."  — hex string output ที่สม่ำเสมอ
หมายเหตุ:parameter digestmod ไม่มีค่าเริ่มต้นตั้งแต่ Python 3.4 การเรียก hmac.new(key, msg) โดยไม่ระบุจะเกิด TypeError ก่อนหน้า 3.4 มีค่าเริ่มต้นเป็น MD5 ซึ่งเป็นเหตุผลที่ Python maintainer ลบค่าเริ่มต้นออก — เพื่อบังคับให้เลือกอย่างชัดเจนและปลอดภัย

HMAC-SHA256 Base64, SHA-1, SHA-512 และ MD5

ฟังก์ชัน hmac.new() ทำงานร่วมกับ hash algorithm ใดก็ได้ที่มีอยู่ใน hashlibผู้ให้บริการ webhook และ API gateway ส่วนใหญ่ใช้ HMAC-SHA256 แต่คุณจะพบ SHA-1 ใน OAuth 1.0a SHA-512 ใน protocol ที่กำหนดไว้ และ MD5 ในระบบเก่าที่ยังไม่ได้อัปเดต

HMAC-SHA256 พร้อม Base64 Output

ผู้ให้บริการ webhook หลายรายส่ง signature เป็น Base64-encoded string ใน HTTP header เพื่อให้ได้รูปแบบเดียวกัน ส่ง raw .digest() bytes ไปยัง base64.b64encode()

Python 3.7+ — การเข้ารหัส HMAC-SHA256 เป็น Base64
import hmac
import hashlib
import base64

key = b"whsec_MbkP7x9yFqHGn3tRdWz5"
payload = b'{"id":"evt_1Nq","type":"charge.succeeded","data":{"amount":4200}}'

# Raw digest → Base64 (ทั่วไปสำหรับ Authorization header และ webhook signature)
raw_digest = hmac.new(key, payload, hashlib.sha256).digest()
b64_signature = base64.b64encode(raw_digest).decode("ascii")

print(b64_signature)
# "dGhpcyBpcyBhIHNhbXBsZSBzaWduYXR1cmU="

# ค่านี้คือค่าที่จะนำไปเปรียบเทียบกับ X-Signature header
header_value = f"sha256={b64_signature}"
print(header_value)
# "sha256=dGhpcyBpcyBhIHNhbXBsZSBzaWduYXR1cmU="

HMAC-SHA1 — ความเข้ากันได้กับ Protocol เก่า

SHA-1 ถือว่าอ่อนแอสำหรับการออกแบบใหม่ แต่ HMAC-SHA1 ยังคงจำเป็นสำหรับ OAuth 1.0a และ webhook รุ่นเก่าบางตัว โค้ดเหมือนกันทุกอย่าง — เพียงแค่เปลี่ยน algorithm

Python 3.7+ — HMAC-SHA1
import hmac
import hashlib

consumer_secret = b"oauth_consumer_secret_2026"
token_secret = b"oauth_token_secret_2026"

# OAuth 1.0a ใช้ consumer_secret&token_secret เป็น signing key
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..."  — URL-encode นี้สำหรับ Authorization header

HMAC-SHA512 — Output ที่ยาวขึ้น

Python 3.7+ — 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 bytes (512 bits)
print(len(h.hexdigest()))  # 128 hex characters
print(h.hexdigest()[:40] + "...")
# "8e3a1f9b2c4d6e7f0a1b3c5d7e9f0a2b4c6d8e0f..."

HMAC-MD5 — สำหรับระบบเก่าเท่านั้น

Python 3.7+ — HMAC-MD5
import hmac
import hashlib

# MD5 เสียหายในทางการเข้ารหัส — ใช้เฉพาะเพื่อความเข้ากันได้กับ protocol เก่า
key = b"legacy_api_key"
msg = b"action=charge&amount=1500&merchant=store_42"

sig = hmac.new(key, msg, hashlib.md5).hexdigest()
print(sig)  # hex string 32 ตัวอักษร
# "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6"
คำเตือน:HMAC-MD5 ยอมรับได้เฉพาะสำหรับความเข้ากันได้แบบย้อนหลังกับระบบที่ไม่สามารถย้ายได้ สำหรับโปรเจกต์ใหม่ ให้ใช้ HMAC-SHA256 อย่างน้อย MD5 มีช่องโหว่ collision ที่รู้จัก ซึ่งแม้จะใช้งานได้ยากกว่าในโหมด HMAC แต่ก็ทำให้เป็นตัวเลือกที่ไม่ดีโดยค่าเริ่มต้น

การอ้างอิง Parameter ของ hmac.new()

signature ของ constructor คือ hmac.new(key, msg=None, digestmod)ฟังก์ชันทั้งสามใน module ใช้รูปแบบ key และ algorithm argument เดียวกัน

hmac.new() constructor

Parameter
Type
ค่าเริ่มต้น
คำอธิบาย
key
bytes | bytearray
(จำเป็น)
คีย์ลับ — ต้องเป็น bytes ไม่ใช่ string
msg
bytes | None
None
ข้อความเริ่มต้นสำหรับแฮช สามารถเพิ่มข้อมูลได้ภายหลังผ่าน .update()
digestmod
str | callable
(จำเป็น)
อัลกอริทึม hash — เช่น hashlib.sha256 หรือ string "sha256"

hmac.digest() one-shot (Python 3.7+)

Parameter
Type
คำอธิบาย
key
bytes
คีย์ลับ
msg
bytes
ข้อความที่ต้องการยืนยัน
digest
str | callable
อัลกอริทึม hash — เหมือนกับ digestmod ใน hmac.new()

parameter digestmod รับทั้ง callable (เช่น hashlib.sha256) หรือชื่อ string (เช่น "sha256") แนะนำให้ใช้รูปแบบ callable เพราะได้รับการตรวจสอบตอน import — การพิมพ์ผิดในรูปแบบ string จะล้มเหลวตอน runtime เท่านั้น

hmac.digest() — HMAC แบบ One-Shot ที่เร็วกว่า (Python 3.7+)

Python 3.7 เพิ่ม hmac.digest(key, msg, digest) เป็นฟังก์ชันระดับ module ทำการคำนวณ HMAC ในการเรียกครั้งเดียวโดยไม่ต้องสร้าง HMAC object กลาง ค่าที่คืนกลับเป็น raw bytes (เทียบเท่ากับการเรียก .digest() บน object) ฟังก์ชันนี้ใช้ C implementation ที่ปรับปรุงแล้วบน CPython และหลีกเลี่ยง overhead จากการสร้าง object ทำให้เร็วขึ้นอย่างเห็นได้ชัดในการวนซ้ำหนาแน่น

Python 3.7+ — hmac.digest() แบบ one-shot
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}',
]

# One-shot digest — ไม่มี HMAC object กลาง
signatures = [hmac.digest(key, msg, hashlib.sha256) for msg in messages]

# แปลงเป็น hex สำหรับแสดงผล
for msg, sig in zip(messages, signatures):
    print(f"{msg[:30]}... -> {sig.hex()[:24]}...")

ข้อจำกัดคือ: hmac.digest() คืนค่าเฉพาะ raw bytes ถ้าต้องการ hex string โดยตรง คุณยังต้องใช้ hmac.new() เพื่อเรียก .hexdigest() หรือต่อ .hex() กับผลลัพธ์ bytes

หมายเหตุ:hmac.digest() ไม่รองรับการเรียก .update() แบบทีละส่วน ถ้าต้องอ่านไฟล์ขนาดใหญ่เป็นชิ้นๆ และต้องการ HMAC เนื้อหา ให้ใช้ hmac.new() และเรียก .update(chunk) ในลูป

การตรวจสอบ HMAC Signature จาก Webhook และ API Response

การใช้งาน HMAC ที่พบบ่อยที่สุดใน Python คือการตรวจสอบ webhook signature ผู้ให้บริการรายใหญ่ทุกราย (Stripe, GitHub, Shopify, Twilio) เซ็น payload ด้วย HMAC-SHA256 และส่ง signature ใน header รูปแบบเสมอเหมือนกัน: คำนวณ HMAC ใหม่จาก raw request body จากนั้นเปรียบเทียบด้วย hmac.compare_digest()

การตรวจสอบ Webhook Signature

Python 3.7+ — การตรวจสอบ webhook HMAC (Flask)
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 — ต้องตรงกับสิ่งที่ถูกเซ็นพอดี
    raw_body = request.get_data()

    # รับ signature จาก header
    received_sig = request.headers.get("X-Signature-256", "")

    # คำนวณ HMAC ใหม่จาก raw body
    expected_sig = hmac.new(WEBHOOK_SECRET, raw_body, hashlib.sha256).hexdigest()

    # การเปรียบเทียบแบบ constant-time — ป้องกัน timing attack
    if not hmac.compare_digest(f"sha256={expected_sig}", received_sig):
        abort(403, "Invalid signature")

    # ตรวจสอบ signature แล้ว — ดำเนินการ event
    event = request.get_json()
    print(f"Verified event: {event['type']} for {event['data']['amount']}")
    return "", 200

ฟังก์ชัน hmac.compare_digest() เปรียบเทียบ string หรือลำดับ byte สองชุดในเวลาคงที่ การเปรียบเทียบด้วย == ธรรมดาจะหยุดทำงานเมื่อพบ byte แรกที่ไม่ตรงกัน ผู้โจมตีสามารถวัดเวลาตอบสนองจากหลาย request และค่อยๆ สร้าง signature ที่คาดหวังขึ้นใหม่ทีละ byte การเปรียบเทียบแบบ constant-time ขจัดช่องทางด้านข้างนี้

การตรวจสอบ GitHub Webhook

รูปแบบ webhook ของ GitHub แสดงให้เห็นรูปแบบครบถ้วน GitHub ส่ง header X-Hub-Signature-256 ที่มี sha256= ตามด้วย HMAC-SHA256 แบบ hex-encoded ของ raw request body ที่เซ็นด้วย webhook secret ที่คุณกำหนดในการตั้งค่า repository ข้อแตกต่างหลักจากการตรวจสอบ webhook ทั่วไปคือ คุณต้องตัด prefix sha256= ออกก่อนเปรียบเทียบ และต้องอ่าน raw bytes ของ request body — การ parse JSON ก่อน จะเปลี่ยน byte representation และทำลายการตรวจสอบ

Python 3.7+ — การตรวจสอบ GitHub X-Hub-Signature-256
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()  # raw bytes — อย่า parse 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), โดยความแตกต่างเพียงอย่างเดียวคือชื่อ header และ signature เป็น hex หรือ Base64-encoded ตรวจสอบเอกสารของผู้ให้บริการเสมอเพื่อยืนยันรูปแบบการเข้ารหัส — การสับสนระหว่าง hex กับ Base64 เป็นสาเหตุที่พบบ่อยที่สุดของข้อผิดพลาด signature mismatch

การยืนยันตัวตน API Request ด้วย HMAC

บาง API กำหนดให้ client เซ็นแต่ละ request ด้วย HMAC string ที่เซ็นมักประกอบด้วย HTTP method, path, timestamp และ request body นี่คือรูปแบบที่ใช้สำหรับ internal service-to-service authentication

Python 3.7+ — การเซ็น API request ด้วย HMAC-SHA256
import hmac
import hashlib
import time
import json

def sign_request(secret: bytes, method: str, path: str, body: str) -> dict:
    """สร้าง HMAC-SHA256 signature สำหรับ API request"""
    timestamp = str(int(time.time()))

    # สร้าง signing string — 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..."}

การเซ็น HTTP Request ด้วย requests Library

Python 3.7+ — HMAC-signed requests ด้วย requests library
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=(",", ":"))  # compact 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

# ส่ง signed POST request
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=(",", ":") เมื่อ serialize body สำหรับการเซ็น ค่าเริ่มต้นของ json.dumps() จะเพิ่มช่องว่างหลัง separator ซึ่งเปลี่ยน byte representation และทำลายการตรวจสอบ signature หาก server serialize ต่างออกไป JSON แบบ compact ให้รูปแบบที่กำหนดแน่นอน

การสร้าง HMAC จาก Command Line

บางครั้งคุณต้องการคำนวณ HMAC โดยไม่ต้องเขียน script flag -c ของ Python และ openssl ทั้งสองจัดการได้จาก terminal

bash — HMAC-SHA256 ผ่าน Python one-liner
python3 -c "
import hmac, hashlib
print(hmac.new(b'my_secret', b'message_to_sign', hashlib.sha256).hexdigest())
"
# outputs: hex string 64 ตัวอักษร
bash — HMAC-SHA256 ผ่าน openssl (สำหรับเปรียบเทียบ)
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
bash — HMAC จาก environment variable key
# เก็บ key ใน env var เพื่อหลีกเลี่ยงการแสดงใน shell history
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())
"
หมายเหตุ:flag echo -n สำคัญมาก — หากไม่ใส่ echo จะเพิ่ม newline character ต่อท้ายข้อความซึ่งเปลี่ยน HMAC output นี่คือสาเหตุที่พบบ่อยที่สุดของ signature mismatch เมื่อ debug จาก terminal

ทางเลือกสำหรับประสิทธิภาพสูง — cryptography Library

สำหรับ application ส่วนใหญ่ module hmac มาตรฐานเพียงพอแล้ว ถ้าคุณใช้ library cryptography สำหรับ TLS หรือการจัดการ certificate อยู่แล้ว มันก็มี HMAC ที่ขับเคลื่อนด้วย OpenSSL ด้วย ความแตกต่างในทางปฏิบัติหลักจาก stdlib คือ API แบบ exception-based ของ .verify() — มัน raise เมื่อไม่ตรงกันแทนที่จะคืนค่า boolean ที่คุณอาจลืมตรวจสอบ

bash — ติดตั้ง cryptography
pip install cryptography
Python 3.7+ — HMAC ผ่าน cryptography library
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()  # raw bytes

print(signature.hex())
# "9c4e2a..."

# โหมดตรวจสอบ — raise InvalidSignature เมื่อไม่ตรงกัน
h_verify = crypto_hmac.HMAC(key, hashes.SHA256())
h_verify.update(message)
h_verify.verify(signature)  # raise cryptography.exceptions.InvalidSignature ถ้าผิด

เมธอด .verify() ของ library cryptography มีประโยชน์มาก: มัน raise exception เมื่อไม่ตรงกันแทนที่จะคืนค่า boolean ทำให้ยากขึ้นที่จะ ละเลยความล้มเหลวในการตรวจสอบโดยไม่ตั้งใจ hmac.compare_digest() ของ standard library คืนค่า True/ Falseซึ่งสามารถถูกละเลยโดยไม่รู้ตัวหากนักพัฒนาลืมตรวจสอบ return value

แสดงผล Terminal พร้อม Syntax Highlighting

ถ้ากำลัง debug HMAC signature ใน terminal และต้องการ output สีสัน rich จัดการได้ดีมาก

bash — ติดตั้ง rich
pip install rich
Python 3.7+ — HMAC output สีสันด้วย 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)
หมายเหตุ:Rich สำหรับการแสดงผลใน terminal เท่านั้น อย่าใช้เมื่อเขียน HMAC signature ลงไฟล์ HTTP header หรือระบบรวบรวม log — ANSI escape code จะทำให้ output เสียหาย

การทำงานกับไฟล์ขนาดใหญ่ — Incremental HMAC

สำหรับไฟล์ขนาดใหญ่กว่า 50 MB หรือมากกว่า การโหลดทุกอย่างเข้าหน่วยความจำเพียงเพื่อคำนวณ HMAC เป็นการสิ้นเปลือง เมธอด .update() บน HMAC object ให้คุณส่งข้อมูลเป็นชิ้นๆ ทำให้การใช้หน่วยความจำคงที่ไม่ว่าขนาดไฟล์จะเป็นเท่าไร

Python 3.7+ — HMAC ไฟล์ขนาดใหญ่แบบ chunked
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()

# เซ็น database export ขนาด 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}")
Python 3.7+ — ตรวจสอบ HMAC signature ของไฟล์ที่ดาวน์โหลด
import hmac
import hashlib

def verify_file_hmac(key: bytes, filepath: str, expected_hex: str) -> bool:
    """ตรวจสอบ HMAC-SHA256 signature ของไฟล์"""
    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)

# ตรวจสอบ artifact ที่ดาวน์โหลด
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'}")
หมายเหตุ:เปลี่ยนไปใช้ chunked HMAC เมื่อไฟล์มีขนาดเกิน 50-100 MB หรือเมื่อประมวลผล upload บน web server ที่หน่วยความจำต่อ request มีความสำคัญ วิธี .update() ใช้หน่วยความจำ chunk_size คงที่โดยไม่คำนึงถึงขนาดไฟล์ ค่าเริ่มต้น 64 KB — ใหญ่พอที่จะลด syscall overhead เล็กพอที่จะอยู่ใน L2 cache ของ hardware ส่วนใหญ่

การสร้าง HMAC Key ที่ปลอดภัยในทางการเข้ารหัสใน Python

คีย์ที่อ่อนแอหรือคาดเดาได้ทำลายโครงสร้าง HMAC ทั้งหมด module secrets (Python 3.6+) ให้ random bytes ที่แข็งแกร่งในทางการเข้ารหัส สำหรับ HMAC-SHA256 ใช้คีย์ขนาด 32 bytes สำหรับ HMAC-SHA512 ใช้ 64 bytes ขนาดเหล่านี้ตรงกับขนาด block ภายในของ hash algorithm ซึ่งเป็นความยาวคีย์ที่เหมาะสมที่สุด ตาม RFC 2104

Python 3.7+ — สร้าง HMAC key ด้วย secrets
import secrets

# สร้างคีย์ที่ตรงกับขนาด block ของ hash algorithm
sha256_key = secrets.token_bytes(32)   # 256 bits — สำหรับ HMAC-SHA256
sha512_key = secrets.token_bytes(64)   # 512 bits — สำหรับ HMAC-SHA512

# รูปแบบ hex — ปลอดภัยสำหรับไฟล์ config และ environment variable
print(f"HMAC-SHA256 key: {sha256_key.hex()}")
# เช่น "a3f1b9c04e7d2f8a1b3c5d7e9f0a2b4c6d8e0f1a2b3c4d5e6f7a8b9c0d1e2f"

print(f"HMAC-SHA512 key: {sha512_key.hex()}")
# hex string 128 ตัวอักษร

# URL-safe Base64 — กะทัดรัด ปลอดภัยสำหรับ HTTP header
import base64
b64_key = base64.urlsafe_b64encode(sha256_key).decode("ascii")
print(f"Base64 key: {b64_key}")
# เช่น "o_G5wE59L4obPF1-nwortG2ODwobPExdXnqLnA0dLi8="
คำเตือน:ห้ามใช้ random.random() หรือ random.randbytes() จาก module random สำหรับ HMAC key ค่าเริ่มต้น module random ใช้ Mersenne Twister PRNG ซึ่งสามารถคาดเดาได้ หลังจากสังเกต 624 output ให้ใช้ secrets.token_bytes() เสมอสำหรับความสุ่มที่ต้องการความปลอดภัย

ความยาวคีย์และข้อกำหนดของ RFC 2104

RFC 2104 ระบุว่า HMAC key สามารถมีความยาวใดก็ได้ แต่แนะนำให้ใช้คีย์อย่างน้อย L bytes โดยที่ L คือความยาว output ของ hash function พื้นฐาน สำหรับ HMAC-SHA256 คือ 32 bytes (256 bits) คีย์ที่สั้นกว่า L bits จะลด security margin ตามสัดส่วน คีย์ที่ยาวกว่าขนาด block ของ hash (64 bytes สำหรับ SHA-256, 128 bytes สำหรับ SHA-512) จะถูก hash ลงมาเป็นขนาด block ก่อน ดังนั้นจึงไม่มีประโยชน์ใดในการใช้คีย์ที่ยาวกว่าขนาด block ใช้ 32 bytes สำหรับ HMAC-SHA256 และ 64 bytes สำหรับ HMAC-SHA512

การเก็บรักษาและการหมุนเวียนคีย์อย่างปลอดภัย

ห้าม hardcode HMAC key ในซอร์สโค้ด แนวทางมาตรฐานสำหรับ production deployment คือ โหลดคีย์จาก environment variable ตอน startup: os.environ["HMAC_SECRET"].encode()สำหรับสภาพแวดล้อมที่ต้องการความปลอดภัยสูง เก็บคีย์ใน secrets management system เช่น AWS Secrets Manager, HashiCorp Vault หรือ GCP Secret Manager และดึงมาตอน runtime ระบบเหล่านี้มี audit log การควบคุมการเข้าถึง และการหมุนเวียนอัตโนมัติ โดยไม่ต้อง deploy โค้ดใหม่

วางแผนสำหรับการหมุนเวียนคีย์ตั้งแต่ต้น เมื่อหมุนเวียนคีย์จะมีช่วงที่ request ระหว่างทาง ถูกเซ็นด้วยคีย์เก่าและจะล้มเหลวในการตรวจสอบกับคีย์ใหม่ วิธีแก้มาตรฐานคือช่วงทับซ้อนสั้นๆ: ยอมรับ signature จากทั้งคีย์เก่าและใหม่ในช่วงเวลาสั้น (นาทีถึงชั่วโมง) จากนั้นเลิกใช้คีย์เก่า หากคีย์ถูกเปิดเผย — รั่วผ่าน log, รั่วผ่าน git commit หรือถูกเปิดเผยในเหตุการณ์ — หมุนเวียนทันที และถือว่า signature ทั้งหมดที่ผลิตด้วยคีย์ที่ถูกเปิดเผยเป็นที่ไม่น่าเชื่อถือ ตรวจสอบผลลัพธ์การตรวจสอบที่ cache ไว้ใหม่และแจ้ง downstream consumer ของการเปลี่ยนแปลงคีย์

การใช้ bytearray และ memoryview กับ hmac.new()

ฟังก์ชัน hmac.new() รับ bytes-like object ใดก็ได้สำหรับทั้ง parameter key และ msg ซึ่งหมายความว่าคุณสามารถส่ง bytes, bytearray หรือ memoryview โดยตรงโดยไม่ต้องคัดลอกหรือแปลง เรื่องนี้สำคัญมากในสองสถานการณ์: การใช้งาน network protocol ที่ socket.recv_into() เขียนข้อมูลลงใน bytearray buffer ที่จัดสรรไว้ล่วงหน้า และระบบ high-throughput ที่การหลีกเลี่ยง intermediate copy ลด GC pressure slice ของ memoryview เป็น zero-copy: มันเปิดหน้าต่างสู่ buffer ต้นฉบับโดยไม่จัดสรรหน่วยความจำใหม่ ที่หลายหมื่น message ต่อวินาที การขจัดการจัดสรรเหล่านั้นให้ความแตกต่างที่วัดได้ใน latency และ throughput

Python 3.7+ — bytearray และ memoryview กับ HMAC
import hmac
import hashlib

# bytearray — bytes ที่เปลี่ยนแปลงได้ มีประโยชน์สำหรับ binary protocol buffer
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 — zero-copy slice ของ buffer ขนาดใหญ่
large_buffer = bytearray(4096)
large_buffer[:20] = b"sensor_reading_12345"

# HMAC เฉพาะ 20 bytes แรกโดยไม่ต้องคัดลอก
view = memoryview(large_buffer)[:20]
sig = hmac.new(key, view, hashlib.sha256).hexdigest()
print(f"Sensor signature: {sig[:32]}...")

ข้อผิดพลาดที่พบบ่อย

สองข้อผิดพลาดแรกที่เห็นในเกือบทุก code review ที่เกี่ยวกับ webhook handler พวกมันเกิดขึ้นง่ายภายใต้ความกดดันด้านเวลาและยากที่จะสังเกตโดยไม่รู้ว่าต้องมองหาอะไร

เปรียบเทียบ HMAC signature ด้วย == แทน hmac.compare_digest()

ปัญหา: ตัวดำเนินการ == หยุดทำงานเมื่อพบ byte แรกที่ไม่ตรงกัน ทำให้รั่วข้อมูล timing ที่ให้ผู้โจมตีสร้าง signature ที่คาดหวังขึ้นใหม่ทีละขั้น

วิธีแก้ไข: ใช้ hmac.compare_digest() สำหรับการเปรียบเทียบ signature เสมอ — มันทำงานในเวลาคงที่โดยไม่คำนึงว่าความไม่ตรงกันเกิดขึ้นที่ไหน

Before · Python
After · Python
received_sig = request.headers["X-Signature"]
expected_sig = hmac.new(key, body, hashlib.sha256).hexdigest()

if received_sig == expected_sig:  # มีความเสี่ยงต่อ timing attack
    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):  # constant-time
    process_webhook(body)
ส่ง string แทน bytes ไปยัง hmac.new()

ปัญหา: hmac.new() ต้องการ bytes-like object การส่ง Python str จะเกิด TypeError: "key: expected bytes or bytearray, but got 'str'"

วิธีแก้ไข: เรียก .encode() กับ string key และ message ก่อนส่งเข้า hmac.new()

Before · Python
After · Python
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)
ลืมระบุ digestmod (Python 3.4+)

ปัญหา: การเรียก hmac.new(key, msg) โดยไม่ระบุ argument ที่สามจะเกิด TypeError ก่อน Python 3.4 มีค่าเริ่มต้นเป็น MD5 แต่ถูกลบออกด้วยเหตุผลด้านความปลอดภัย

วิธีแก้ไข: ระบุ algorithm อย่างชัดเจนเสมอ: hashlib.sha256, hashlib.sha512 หรือ algorithm ที่ protocol กำหนด

Before · Python
After · Python
# ไม่มี digestmod — เกิด TypeError ใน Python 3.4+
sig = hmac.new(key, msg).hexdigest()
# ระบุ hash algorithm เสมอ
sig = hmac.new(key, msg, hashlib.sha256).hexdigest()
ใช้ .hexdigest() เมื่อผู้ให้บริการคาดหวัง Base64

ปัญหา: ผู้ให้บริการ webhook หลายราย (Stripe, Shopify) ส่ง signature แบบ Base64-encoded ไม่ใช่ hex การเปรียบเทียบ hex string กับค่า Base64 จะล้มเหลวเสมอ ทำให้ webhook ทั้งหมดถูกปฏิเสธ

วิธีแก้ไข: ตรวจสอบเอกสารของผู้ให้บริการเพื่อยืนยันรูปแบบ signature ถ้าใช้ Base64 ให้เข้ารหัส raw .digest() bytes ไม่ใช่ .hexdigest() string

Before · Python
After · Python
# ผู้ให้บริการส่ง Base64 แต่เราคำนวณ hex — ไม่ตรงกันเลย
expected = hmac.new(key, body, hashlib.sha256).hexdigest()
# "a3f1b9c0..."  vs  "o/G5wE59..."  — ไม่ตรงกันเสมอ
import base64
# ตรงกับรูปแบบของผู้ให้บริการ: raw bytes → Base64
raw = hmac.new(key, body, hashlib.sha256).digest()
expected = base64.b64encode(raw).decode("ascii")
# "o/G5wE59..."  — ตรงกับ header

stdlib hmac เทียบกับ cryptography — การเปรียบเทียบสั้นๆ

Method
Algorithm
Output
Streaming
Custom Types
ต้องติดตั้ง
hmac.new() + hexdigest()
Any hashlib
Hex string
✓ ผ่าน .update()
N/A
ไม่ต้อง (stdlib)
hmac.new() + digest()
Any hashlib
Raw bytes
✓ ผ่าน .update()
N/A
ไม่ต้อง (stdlib)
hmac.digest()
Any hashlib
Raw bytes
✗ (one-shot)
N/A
ไม่ต้อง (stdlib, 3.7+)
hashlib.sha256 (plain hash)
SHA-256 only
Hex or bytes
✓ ผ่าน .update()
N/A
ไม่ต้อง (stdlib)
cryptography (HMAC)
Any
Raw bytes
✓ ผ่าน .update()
N/A
pip install
pyca/cryptography + CMAC
AES-CMAC
Raw bytes
✓ ผ่าน .update()
N/A
pip install

ใช้ module hmac ของ stdlib สำหรับการตรวจสอบ webhook การเซ็น API และการทำงาน HMAC ทั่วไป — ไม่ต้อง dependency และรองรับทุก standard algorithm ใช้ hmac.digest() สำหรับการดำเนินการแบบ batch ที่ความเร็ว one-shot มีความสำคัญ เลือก library cryptography เฉพาะเมื่อคุณพึ่งพามันสำหรับการดำเนินการอื่นอยู่แล้ว (TLS, X.509, symmetric encryption) และต้องการ API แบบ exception-based ของ .verify() สำหรับการตรวจสอบ signature อย่างรวดเร็วโดยไม่ต้องเขียน Python ใดๆ ใช้ เครื่องมือ HMAC Generator เพื่อวาง key และข้อความและรับผลลัพธ์ทันที

คำถามที่พบบ่อย

hmac.new() และ hmac.digest() ใน Python ต่างกันอย่างไร?

hmac.new() คืนค่า HMAC object ที่รองรับการเรียก .update() แบบทีละส่วน และให้ทั้ง .digest() (raw bytes) และ .hexdigest() (hex string) ส่วน hmac.digest() เป็นฟังก์ชัน one-shot ที่เพิ่มมาใน Python 3.7 ซึ่งคืนค่า raw bytes โดยตรงโดยไม่ต้องสร้าง object กลาง ใช้ hmac.digest() เมื่อมีข้อความครบถ้วนและต้องการผลลัพธ์เท่านั้น ใช้ hmac.new() เมื่อต้องการส่งข้อมูลเป็นชิ้นๆ หรือต้องการ hex output

Python
import hmac, hashlib

key = b"webhook_secret_2026"
body = b'{"event":"payment.completed","amount":9950}'

# One-shot — คืนค่า raw bytes
raw = hmac.digest(key, body, hashlib.sha256)

# Object-based — รองรับการอัปเดตแบบทีละส่วนและ hex output
h = hmac.new(key, body, hashlib.sha256)
hex_sig = h.hexdigest()

จะตรวจสอบ HMAC signature ใน Python ได้อย่างไร?

คำนวณ HMAC ใหม่จากข้อความต้นฉบับโดยใช้คีย์ลับร่วม จากนั้นเปรียบเทียบโดยใช้ hmac.compare_digest() อย่าใช้ == สำหรับการเปรียบเทียบ signature เพราะตัวดำเนินการ == มีความเสี่ยงต่อ timing attack — มันหยุดทำงานเมื่อพบ byte แรกที่ไม่ตรงกัน ทำให้รั่วข้อมูลเกี่ยวกับความยาวและเนื้อหาของ signature ที่คาดหวัง

Python
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 คำนวณ plain SHA-256 hash ของ input ซึ่งทุกคนสามารถคำนวณซ้ำได้ HMAC-SHA256 ผสมคีย์ลับเข้าสู่กระบวนการแฮชตาม RFC 2104 ดังนั้นเฉพาะผู้ที่มีคีย์เท่านั้นที่สามารถสร้างหรือตรวจสอบ output ที่ถูกต้องได้ plain hash พิสูจน์ความสมบูรณ์ของข้อมูล ส่วน HMAC พิสูจน์ทั้งความสมบูรณ์และความถูกต้อง

Python
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()  # ต้องใช้คีย์

ใช้ HMAC-SHA1 ใน Python 3 ได้หรือไม่?

ได้ ส่ง hashlib.sha1 เป็น argument digestmod HMAC-SHA1 ยังทำงานได้ดีใน Python 3 และ module hmac ไม่มีคำเตือน deprecation อย่างไรก็ตาม SHA-1 ถือว่าอ่อนแอสำหรับการออกแบบใหม่ — ความต้านทานการชนกันต่ำกว่า 80 บิต และ NIST ได้ยกเลิกการใช้งานสำหรับการเซ็นลายมือดิจิทัลส่วนใหญ่ในปี 2015 เหตุผลหลักที่ใช้ HMAC-SHA1 ในปัจจุบันคือความเข้ากันได้แบบย้อนหลังกับ protocol เดิมที่กำหนดไว้ เช่น OAuth 1.0a หรือระบบ webhook รุ่นเก่า เมื่อควบคุมทั้งสองฝั่งของการเชื่อมต่อ ให้ใช้ HMAC-SHA256 หรือ HMAC-SHA512 สำหรับงานใหม่ทั้งหมด

Python
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()

จะสร้าง HMAC key ที่ปลอดภัยใน Python ได้อย่างไร?

ใช้ secrets.token_bytes() จาก standard library สำหรับ HMAC-SHA256 คีย์ขนาด 32 bytes เป็นคำแนะนำมาตรฐาน เนื่องจากตรงกับขนาด block ของ hash สำหรับ HMAC-SHA512 ใช้ 64 bytes อย่าใช้ random.random() หรือ os.urandom() สำหรับการสร้างคีย์ใน application code — secrets เป็น module ที่ถูกต้องสำหรับความสุ่มที่ต้องการความปลอดภัยตั้งแต่ Python 3.6

Python
import secrets

hmac_sha256_key = secrets.token_bytes(32)  # 256 bits
hmac_sha512_key = secrets.token_bytes(64)  # 512 bits

# เก็บเป็น hex สำหรับไฟล์ config
print(hmac_sha256_key.hex())
# เช่น "a3f1b9c04e..."

ทำไม hmac.new() ถึงต้องระบุ digestmod ใน Python 3?

ก่อน Python 3.4 digestmod มีค่าเริ่มต้นเป็น MD5 ซึ่งเสียหายในทางการเข้ารหัส — MD5 มีการโจมตีแบบ collision ที่รู้จักกันดีและไม่ควรใช้กับ code ที่ต้องการความปลอดภัย Python maintainer ลบค่าเริ่มต้นนี้ออกเพื่อบังคับให้เลือก algorithm อย่างชัดเจน ป้องกันไม่ให้นักพัฒนาส่ง MAC แบบ MD5 โดยไม่รู้ตัว หากเรียก hmac.new(key, msg) โดยไม่ระบุ digestmod จะได้รับ TypeError เสมอ ระบุ algorithm อย่างชัดเจน: hashlib.sha256, hashlib.sha512 หรือ hashlib constructor อื่นๆ เมื่อไม่แน่ใจ hashlib.sha256 คือตัวเลือกที่ปลอดภัย — ไม่มีจุดอ่อนที่รู้จักและเร็วพอสำหรับทุก workload ในทางปฏิบัติ

Python
import hmac, hashlib

key = b"secret"
msg = b"data"

# บรรทัดนี้จะเกิด TypeError ใน Python 3.4+
# hmac.new(key, msg)  # TypeError: missing required argument: 'digestmod'

# ระบุ algorithm เสมอ
h = hmac.new(key, msg, hashlib.sha256)

สำหรับการตรวจสอบ HMAC อย่างรวดเร็วโดยไม่ต้องเรียกใช้ Python script วาง key และข้อความของคุณใน เครื่องมือ HMAC Generator ออนไลน์ — รองรับ SHA-256, SHA-384 และ SHA-512 พร้อมผลลัพธ์ทันที

เครื่องมือที่เกี่ยวข้อง

DV
Dmitri VolkovDevOps Engineer & Python Automation Specialist

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.

MS
Maria Santosผู้ตรวจสอบทางเทคนิค

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.