Máy tính HMAC, PBKDF2 & HKDF

Tính mã xác thực thông điệp có khóa với HMAC-MD5, HMAC-SHA-1, HMAC-SHA-256, HMAC-SHA-384 hoặc HMAC-SHA-512 (RFC 2104) trên văn bản, byte hex hoặc toàn bộ tệp — khóa nhập dưới dạng văn bản, hex hoặc Base64. Hoặc dẫn xuất khóa với PBKDF2 (RFC 8018) và HKDF (RFC 5869). Mọi kết quả có thể hiển thị dạng hex, hex chữ hoa, Base64 hoặc Base64url. Với digest thuần xem Trình tạo băm; với checksum xem Máy tính CRC; với HMAC dùng bên trong JWT xem Bộ giải mã JWT.
Chạy hoàn toàn cục bộ — khóa và thông điệp không bao giờ rời tab của bạn. Tệp tối đa 200 MB.
Cấu trúc: Đầu ra:
Thuật toán HMAC: RFC 2104 — biến thể MD5 cần md5.js (do trang này tải).
Đọc hex chấp nhận khoảng trắng, dấu hai chấm và tiền tố 0x; Base64 phải ở dạng chuẩn có hoặc không có phần đệm.
Khóa rỗng hợp lệ theo RFC 2104 nhưng gần như luôn là một lỗi — HMAC không có khóa chỉ là một hàm băm chậm.
Dòng đầu tiên ghi lại chính xác các tham số đã dùng (thuật toán, cách đọc, kích thước đầu vào), nên một kết quả được sao chép-dán luôn có thể tái tạo.
Bạn cần cấu trúc nào?
HMAC biến một bí mật chia sẻ cộng một thông điệp thành một bộ xác thực: người nhận biết khóa có thể tính lại nó và phát hiện chỉnh sửa. Đó là “HS256” bên trong mọi JWT đã ký (xem Bộ giải mã JWT) và một nửa các sơ đồ ký yêu cầu API trên thế giới. PBKDF2 dùng để kéo dài một mật khẩu của con người thành một khóa: nó lặp HMAC hàng nghìn lần để mỗi lần đoán mật khẩu của kẻ tấn công tốn cùng một độ trễ. HKDF dùng cho khóa giao thức: nó nhận các byte bí mật đã ngẫu nhiên (ví dụ một bí mật chia sẻ DH) và mở rộng chúng an toàn thành nhiều khóa gắn với mục đích — TLS 1.3 dẫn xuất toàn bộ khóa lưu lượng theo cách này. Quy tắc ngón tay cái: xác thực → HMAC; mật khẩu → PBKDF2 (hoặc scrypt/Argon2, xem Trình tạo băm mật khẩu khi được công bố); bí mật đều → HKDF.
Tự kiểm tra
Chạy các engine của trang với các vector đã công bố: 10 mốc HMAC (kiểu RFC 2202/4231, năm thuật toán × hai đầu vào), 6 mốc PBKDF2 (SHA-1 và SHA-256 ở ba số vòng lặp) và bốn trường hợp kiểm thử RFC 5869 HKDF A.1–A.4. Không có gì được gửi đi đâu cả.
HMAC, PBKDF2 và HKDF — băm có khóa được giải thích từ đầu
Trong một câu: một hàm băm trần như SHA-256 ai cũng tính được, nên nó không chứng minh được ai đã gửi thông điệp — HMAC trộn một khóa bí mật để chỉ người giữ khóa mới tạo (hoặc xác minh) được digest; PBKDF2 và HKDF sau đó tái sử dụng cơ chế HMAC đó để biến bí mật thành khóa, chậm cho mật khẩu và nhanh cho vật liệu đã ngẫu nhiên.
HMAC là gì (RFC 2104)

Cấu trúc. HMAC là hai lần chạy hàm băm, không phải một. Khóa của bạn được đệm tới kích thước khối của hàm băm (64 byte cho MD5/SHA-1/SHA-256, 128 cho SHA-384/512); thông điệp được băm một lần với khóa XOR một pad trong cố định, và digest đó lại được băm với khóa XOR một pad ngoài cố định. Cấu trúc bánh kẹp kép này được chứng minh là an toàn miễn là hàm băm nền là một hàm giả ngẫu nhiên tốt — đó là lý do HMAC-MD5 vẫn chống được các tấn công va chạm thực tế đã phá MD5 thuần (dù sao nó cũng đã bị ngừng dùng, xem bên dưới).

Khóa. Mọi độ dài khóa đều dùng được: ngắn hơn kích thước khối thì dùng nguyên, dài hơn thì được băm trước. Trang này cũng cho phép bạn nhập khóa dưới dạng văn bản, hex hoặc Base64 để khóa sản xuất 64 ký tự hex có thể được dán mà không ai nhầm nó với mật khẩu văn bản 64 ký tự — cách đọc được ghi vào dòng đầu ra chính vì lý do đó.

Bạn gặp nó ở đâu. Trường HS256 trong header JWT thực chất là HMAC-SHA-256 trên các phần token đã mã hóa base64url (Bộ giải mã JWT trên site này tính đúng điều đó khi bạn dán khóa bí mật HS256). Chữ ký webhook (Stripe, GitHub), AWS SigV4, bảo vệ bản ghi TLS (các phiên bản cũ hơn) và họ hàng umac-64@openssh.com của OpenSSH đều thuộc cùng một họ.

Vì sao không chỉ hash(message || key)? Tấn công mở rộng độ dài: mọi hàm băm họ MD5/SHA-1/SHA-2 cho phép kẻ tấn công biết H(secret || msg) tính H(secret || msg || padding || anything) mà không cần bí mật. Việc tách trong/ngoài của HMAC loại bỏ lớp tấn công đó. Đây là lỗi tự làm phổ biến nhất trong mã chữ ký API — và cũng là lý do HMAC tồn tại.

PBKDF2 là gì (RFC 8018)

Chậm theo thiết kế. Một mật khẩu có lẽ chỉ khoảng 40 bit entropy thật; GPU của kẻ tấn công thử hàng tỷ SHA-256 thô mỗi giây. PBKDF2 chạy HMAC(password, salt) lặp đi lặp lại — iter lần — nên mỗi lần đoán tốn đúng iter HMAC cho bạn và cho kẻ tấn công. Mặc định ở đây là 600.000 vòng với HMAC-SHA-256, mức chuẩn trong OWASP Password Storage Cheat Sheet; thanh trượt đi tới mười triệu vì hướng dẫn bảo mật liên tục tăng khi phần cứng nhanh hơn.

Muối. Một muối ngẫu nhiên riêng cho mỗi mật khẩu khiến những người dùng giống nhau không còn băm giống nhau, và các bảng tiền tính (rainbow table) mất giá trị. Muối không phải bí mật — nó được lưu cạnh băm — chỉ cần duy nhất. 16 byte ngẫu nhiên là tiêu chuẩn.

Điểm yếu đã biết. PBKDF2 tốn CPU nhưng không tốn bộ nhớ: GPU và ASIC song song hóa nó rất hiệu quả. Đó là lý do lời khuyên hiện đại là scrypt hoặc Argon2id khi thiết kế lưu trữ băm mật khẩu (trang Trình tạo băm mật khẩu trong họ này bao phủ chúng), và PBKDF2 vẫn là lựa chọn đúng cho các thiết lập tương thích và FIPS-140.

HKDF là gì (RFC 5869)

Extract rồi expand. HKDF làm hai việc. Extract: nén vật liệu khóa đầu vào có thể không đều (ví dụ một bí mật chia sẻ Diffie–Hellman) cùng với một muối thành một khóa giả ngẫu nhiên ngắn PRK = HMAC(salt, IKM). Expand: kéo dài PRK đó tới bất kỳ độ dài nào đến 255 khối băm, mỗi khối đầu ra được nối với khối trước và gắn nhãn bởi trường info. Kết quả là một bí mật có thể an toàn cho bạn một khóa mã hóa, một khóa MAC và một IV, tất cả được tách biệt.

Không dùng cho mật khẩu. HKDF giả định đầu vào của nó đã có đủ entropy — nó thực hiện một HMAC cho mỗi 32 byte đầu ra, nên một mật khẩu của con người đi qua nó gần như tức thì, đúng thứ kẻ tấn công cần. Đưa mật khẩu qua HKDF thay vì PBKDF2 là một lỗi thiết kế kinh điển; trường info dành cho nhãn mục đích ("client traffic key", "server iv"), không phải để thêm entropy.

Bạn gặp nó ở đâu. TLS 1.3 dẫn xuất mọi khóa nó dùng từ bí mật bắt tay qua HKDF; WireGuard, Signal, EAP-TLS 1.3 và JSON Web Encryption (làm KDF thỏa thuận khóa trực tiếp) đều nằm trên cùng một cây họ hàng.

Giá trị neo — tái tạo chúng trên trang này

Hai bảng đầu là các vector kiểm thử mà nút Mẫu và tự kiểm tra của trang này được xây dựng trên đó (khóa "key", thông điệp “The quick brown fox jumps over the lazy dog”; rồi trường hợp kiểu RFC với khóa 16 byte 0x0b và thông điệp “Hi There”). Tất cả được tạo bởi một triển khai gốc độc lập và được xác minh lại trên trang này.

HMAC của “fox”, khóa = keyDigest (hex)
HMAC-MD580070713463e7749b90c2dc24911e275
HMAC-SHA-1de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9
HMAC-SHA-256f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8
HMAC-SHA-384d7f4727e2c0b39ae0f1e40cc96f60242d5b7801841cea6fc592c5d3e1ae50700582a96cf35e1e554995fe4e03381c237
HMAC-SHA-512b42af09057bac1e2d41708e48a902e09b5ff7f12ab428a4fe86653c73dd248fb82f948a549f7b791a5b41915ee4d1ec3935357e4e2317250d0372afa2ebeeb3a
Mốc tham chiếu KDFTham sốĐầu ra (hex, các byte đầu)
PBKDF2-HMAC-SHA-1mật khẩu / salt, c=4096, 32 byte4b007901b765489abead49d926f721d065a429c12e463f6c4cd79401085b03db
PBKDF2-HMAC-SHA-256mật khẩu / salt, c=4096, 32 bytec5e478d59288c841aa530db6845c4c8d962893a001ce4e11a4963873aa98134a
HKDF-SHA-256 (RFC 5869 A.1)IKM=0x0b×22, salt=00..0c, info=f0..f9, L=423cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865
HKDF-SHA-256 (RFC 5869 A.2)IKM=00..4f, salt=60..af, info=b0..ff, L=82b11e398dc80327a1c8e7f78c596a49344f012eda2d4efad8a050cc4c19afa97c…
HKDF-SHA-256 (RFC 5869 A.3)IKM=0x0b×22, salt và info rỗng, L=428da4e775a563c18f715f802a063c5a31b8a11f5c5ee1879ec3454e5f3c738d2d9d201395faa4b61a96c8
Những lỗi thường gặp
  • Nhầm HMAC với mã hóa. HMAC chứng minh tính toàn vẹn và nguồn gốc (với một bí mật chia sẻ); nó không giấu gì cả. Ai không có khóa vẫn thấy toàn bộ thông điệp.
  • Nhầm HMAC với chữ ký. Chữ ký số dùng khóa công khai: một bên ký, ai cũng xác minh được. HMAC là đối xứng: mọi bên xác minh cũng có thể giả mạo. Để chống chối bỏ bạn cần RSA/ECDSA (xem công cụ RSA trong họ này khi được công bố), không phải HMAC.
  • Đọc khóa sai cách. Một chuỗi hex 64 ký tự dán vào ô khóa văn bản sẽ thành 64 byte, không phải 32 — và HMAC thay đổi hoàn toàn. Trang này in cách đọc ra dòng đầu ra; khi hai công cụ không khớp, đó là điều đầu tiên cần so sánh.
  • Số vòng PBKDF2 quá thấp. 1.000 vòng lặp từng hợp lý vào năm 2000; ngày nay các máy GPU ăn nó rất nhanh. Nếu hệ thống của bạn vẫn lưu băm 1.000 vòng, hãy lên kế hoạch di chuyển băm lại khi đăng nhập.
  • HKDF trên mật khẩu. Một HMAC cho mỗi khối đầu ra nghĩa là một mật khẩu đi qua tức thì — dùng PBKDF2 (hoặc Argon2id) cho mật khẩu và HKDF cho các bí mật entropy cao.
  • Tái sử dụng một khóa đã dẫn xuất cho mọi thứ. Cách sửa không tốn gì: dẫn xuất các khóa riêng với các nhãn info khác nhau. Hai khóa từ cùng một IKM với nhãn khác nhau được thiết kế để độc lập.
Câu hỏi thường gặp

HMAC-MD5 có bị phá không? Với vai trò hàm băm kháng va chạm, MD5 đã chết, nhưng bảo mật của HMAC-MD5 phụ thuộc MD5 như một hàm giả ngẫu nhiên, và chưa có phá vỡ thực tế nào được biết. Dù sao cũng đã ngừng dùng — không có lý do gì để chọn nó thay vì HMAC-SHA-256 ngoại trừ tương thích với giao thức cũ.

Khóa HMAC nên dài bao nhiêu? Ít nhất bằng kích thước đầu ra của hàm băm (32 byte với SHA-256) và được sinh bởi một CSPRNG. Khóa ngắn hơn digest vẫn được phép, nhưng mỗi bit thiếu hụt sẽ làm giảm bảo mật trực tiếp.

PBKDF2 với nhiều vòng lặp hơn có “an toàn hơn” mãi mãi không? Nó làm tăng chi phí của kẻ tấn công theo tuyến tính, nhưng cũng làm tăng chi phí đăng nhập của bạn theo tuyến tính. Bài toán là chọn số lần lớn nhất mà người dùng của bạn chịu được — đó là điều các con số của OWASP được hiệu chỉnh theo.

Vì sao HKDF bị giới hạn ở 255 × kích thước băm? Vòng mở rộng là T(i) = HMAC(PRK, T(i-1) || info || i) với bộ đếm một byte i — 255 là giá trị đếm lớn nhất, một giới hạn cấu trúc cứng của RFC 5869, không phải lựa chọn chính sách.

Khác biệt giữa PBKDF2 trên trang này và Trình tạo băm mật khẩu là gì? Cùng thuật toán, việc khác nhau. Trang này dẫn xuất các byte khóa thô để bạn dùng ở nơi khác; trang băm mật khẩu tạo chuỗi thông tin xác thực được lưu (có muối và tham số nhúng) và xác minh các ứng viên đã dán với chúng.