Generator HMAC

Hitung HMAC dari teks, byte hex, atau file dengan kunci rahasia menggunakan SHA-256, SHA-384, SHA-512, SHA-1, atau MD5, lalu cocokkan dengan tanda tangan webhook atau API. Tidak ada data yang keluar dari browser Anda.

Berjalan sepenuhnya di browser Anda. Tidak ada yang diunggah.

Cara menggunakan

  1. Pilih Algoritma. HMAC-SHA256 dipilih secara default dan dipakai oleh sebagian besar webhook dan API.
  2. Masukkan Kunci rahasia dan atur Format kunci ke Teks (dibaca sebagai UTF-8), Hex, atau Base64. Gunakan Hex atau Base64 jika kunci berupa byte mentah, bukan string yang menyerupai kata sandi.
  3. Ketik atau tempel Pesan, ubah masukan ke Hex untuk byte mentah, atau klik Buka file. HMAC diperbarui seiring Anda mengetik.
  4. Pada Keluaran sebagai, pilih hex (huruf kecil), HEX (huruf besar), atau Base64, lalu salin hasilnya, atau tempel tanda tangan yang Anda terima ke kolom Bandingkan dengan untuk melihat Cocok atau Tidak cocok.

Cara kerja HMAC

HMAC (hash-based message authentication code, RFC 2104) menggabungkan hash kriptografis dengan kunci rahasia. Hanya pihak yang mengetahui kunci yang dapat menghasilkan nilai yang benar untuk sebuah pesan, sehingga HMAC yang cocok membuktikan dua hal sekaligus: pesan tidak diubah, dan pesan berasal dari pemegang kunci.

Konstruksinya adalah H((K ⊕ opad) ‖ H((K ⊕ ipad) ‖ message)). Kunci di-hash terlebih dahulu jika lebih panjang dari ukuran blok hash (64 byte untuk MD5, SHA-1, dan SHA-256, 128 byte untuk SHA-384 dan SHA-512), ditambah byte nol hingga mencapai ukuran tersebut, lalu di-XOR dengan ipad (byte 0x36) untuk hash dalam (inner hash) atas pesan dan dengan opad (byte 0x5c) untuk hash luar (outer hash) atas hasil hash dalam. Konstruksi naif SHA-256(key ‖ message) tidak memiliki hash luar, sehingga siapa pun yang melihat satu tag dapat menambahkan data ke pesan dan menghitung tag baru yang valid tanpa kunci (serangan length-extension).

Panjang keluarannya sama dengan panjang hash yang mendasarinya: 32 byte, atau 64 karakter hex, untuk HMAC-SHA256. RFC 2104 menyarankan kunci yang setidaknya sepanjang itu, dan generator Base64 acak dapat membuat kunci yang sesuai.

Penggunaan tanda tangan HMAC

  • Webhook GitHub. Header X-Hub-Signature-256 berisi sha256= diikuti HMAC-SHA256 dalam hex dari body permintaan mentah, yang dihitung dengan kunci rahasia webhook. Anda dapat menempelkan seluruh nilai header ke kolom Bandingkan dengan; awalan sha256= akan diabaikan.
  • Webhook Stripe. Header Stripe-Signature memuat stempel waktu t dan tanda tangan v1: HMAC-SHA256 dalam hex dari stempel waktu, sebuah titik, dan body mentah, yang dihitung dengan kunci rahasia endpoint (whsec_...) dalam bentuk teks.
  • Webhook Shopify. X-Shopify-Hmac-Sha256 berisi HMAC-SHA256 dari body mentah dalam Base64, dengan client secret aplikasi sebagai kunci, jadi pilih keluaran Base64 atau tempel nilai header tersebut ke kolom Bandingkan dengan.
  • AWS Signature Version 4. Kunci penandatanganan diturunkan dengan merangkai HMAC-SHA256: pertama tanggal, dengan kunci berupa AWS4 yang disambung dengan secret access key, lalu region, layanan, dan aws4_request, masing-masing dengan hasil langkah sebelumnya sebagai kunci. Atur Format kunci ke Hex untuk memasukkan keluaran satu langkah ke langkah berikutnya.
  • JSON Web Token. HS256, HS384, dan HS512 adalah HMAC-SHA256, -384, dan -512 atas header terenkode, sebuah titik, dan payload terenkode. Bagian ketiga token adalah HMAC tersebut dalam Base64 aman untuk URL, yang diterima apa adanya oleh kolom Bandingkan dengan. Decoder JWT memverifikasi token secara utuh.

Selalu hitung HMAC atas body mentah persis seperti yang diterima. Mengurai JSON lalu menyerialisasikannya kembali akan mengubah spasi atau urutan kunci, dan bahkan satu baris baru tambahan sudah menghasilkan HMAC yang sama sekali berbeda.

HMAC dalam kode

# Python
import hmac, hashlib
sig = hmac.new(b'key', b'message', hashlib.sha256).hexdigest()
hmac.compare_digest(sig, received)        # perbandingan waktu konstan

// Node.js
const crypto = require('crypto');
const sig = crypto.createHmac('sha256', 'key').update('message').digest('hex');
// timingSafeEqual memunculkan error jika panjangnya berbeda, jadi periksa dulu
crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(received));

// PHP: pesan ditulis sebelum kunci
$sig = hash_hmac('sha256', 'message', 'key');
hash_equals($sig, $received);

# OpenSSL: kunci teks, lalu kunci yang sama dalam bentuk hex
printf '%s' 'message' | openssl dgst -sha256 -hmac 'key'
printf '%s' 'message' | openssl dgst -sha256 -mac HMAC -macopt hexkey:6b6579

# Vektor uji: kunci "key", pesan "The quick brown fox jumps over the lazy dog"
# HMAC-SHA256 = f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8

Saat memverifikasi tanda tangan di kode Anda sendiri, gunakan perbandingan waktu konstan seperti pada contoh di atas. Operator == biasa berhenti pada karakter pertama yang berbeda, dan perbedaan waktu tersebut dapat dimanfaatkan penyerang untuk menemukan tanda tangan yang valid byte demi byte. Untuk skema bertanda waktu seperti milik Stripe, tolak juga permintaan yang stempel waktunya sudah lewat lebih dari beberapa menit untuk mencegah serangan replay.

Pertanyaan yang sering diajukan

Apakah HMAC-MD5 atau HMAC-SHA1 masih aman?

Serangan tabrakan (collision) mematahkan MD5 dan SHA-1 sebagai hash biasa, tetapi tidak memberikan cara praktis untuk memalsukan HMAC, yang bergantung pada sifat lain dari hash dan pada kunci rahasia (RFC 6151 membahas HMAC-MD5). Integrasi yang mewajibkannya, seperti kode TOTP berbasis HMAC-SHA1, boleh tetap dipertahankan. Untuk rancangan baru, gunakan HMAC-SHA256.

Mengapa HMAC saya tidak cocok dengan tanda tangan webhook?

Penyebab umumnya adalah meng-hash JSON yang sudah diurai dan diserialisasi ulang alih-alih body mentah, baris baru di akhir pesan, kunci rahasia atau Format kunci yang salah (kunci rahasia Base64 atau hex yang dimasukkan sebagai Teks, atau sebaliknya), dan algoritma yang salah. Perbedaan hex dan Base64 tidak menjadi masalah di sini: kolom Bandingkan dengan menerima hex huruf besar maupun kecil, Base64 standar, dan Base64 aman untuk URL.

Apa perbedaan HMAC dengan hash biasa?
Siapa pun dapat menghitung hash biasa seperti SHA-256, sehingga hash hanya menunjukkan bahwa data tidak berubah secara tidak sengaja. HMAC hanya dapat dihitung dengan kunci rahasia, sehingga HMAC yang valid juga menunjukkan bahwa nilai itu dibuat oleh seseorang yang memegang kunci tersebut.
Apakah HMAC sama dengan tanda tangan digital?

Tidak. Kedua pihak dalam HMAC berbagi satu kunci rahasia yang sama, sehingga siapa pun yang dapat memverifikasi tag juga dapat membuatnya. Tanda tangan seperti RSA atau ECDSA (RS256 atau ES256 pada JWT) dibuat dengan kunci privat dan diperiksa dengan kunci publik, sehingga pihak yang memverifikasinya tidak dapat memalsukannya.

Apakah kunci rahasia saya dikirim ke server?

Tidak. HMAC-SHA1 dan varian SHA-2 dihitung dengan Web Crypto API di browser Anda, sedangkan HMAC-MD5 dihitung oleh JavaScript di halaman ini. Kunci dan pesan tidak pernah keluar dari perangkat Anda. Meski begitu, tangani kunci rahasia produksi dengan hati-hati dan ganti (rotasi) kunci yang mungkin telah terekspos.