Dalam satu kalimat
HMAC adalah jabat tangan kriptografis yang menggunakan kunci rahasia bersama untuk membuktikan bahwa sebuah pesan itu asli dan belum diutak-atik.
Masalah yang dipecahkannya
Dulu, di zaman koboi internet yang masih liar, ngirim pesan itu ibaratnya kayak ngirim kartu pos. Siapa pun yang mencegatnya bisa membacanya, dan mungkin bahkan mencoret-coretnya sebelum meneruskannya. Kalau kamu dapat kartu pos yang bilang "Temui aku tengah malam, bawa uangnya," gimana kamu bisa yakin itu benar-benar dari kontak agen rahasiamu, dan bukan dari musuh bebuyutannya, si Evil Eve? Dan gimana kamu bisa yakin kalau pesan aslinya bukan "Ketemu jam 12 siang buat makan bareng"?
Inilah masalah ganda autentisitas (apakah ini benar-benar dari kamu?) dan integritas (apakah sudah diubah?).
Fungsi hash kriptografis sederhana (seperti SHA-256) kelihatannya seperti langkah awal yang bagus. Kamu bisa melakukan hash pada pesanmu, kirim pesan dan hash-nya, dan penerima bisa menghitung ulang hash pesannya untuk melihat apakah cocok. Keren! Itu memecahkan masalah integritas. Jika satu byte saja dari pesan diubah, hash-nya tidak akan cocok.
Tapi itu tidak memecahkan masalah autentisitas. Si Evil Eve bisa saja mengubah pesannya, menghitung hash baru untuk pesannya yang baru, lalu mengirimkan keduanya. Penerima akan melihat bahwa hash-nya cocok dengan pesannya, tapi mereka tidak punya cara untuk tahu bahwa seluruh paket itu adalah pemalsuan.
Di sinilah HMAC (Hash-based Message Authentication Code) datang sebagai pahlawan. Dengan menambahkan kunci rahasia bersama ke dalam proses hashing, HMAC menciptakan sebuah tanda tangan yang hanya bisa dibuat oleh seseorang yang memiliki kunci rahasia itu. Ibaratnya, ini adalah perbedaan antara segel lilin biasa (siapa pun bisa membuatnya) dan segel lilin yang dibuat dengan cincin stempel unik (hanya raja yang punya). HMAC memberi kita integritas dan autentisitas sekaligus.
Cara kerjanya di balik layar
HMAC bukanlah jenis fungsi hash yang baru; ini adalah sebuah resep yang menggunakan fungsi hash yang sudah ada (seperti SHA-256) dengan cara yang cerdas dan spesifik. Spesifikasi resminya ada di RFC 2104, tapi mari kita bedah dengan bahasa yang lebih santai.
Bahan-bahannya
Untuk meracik HMAC, kamu butuh tiga hal:
- Pesan (The Message): Data yang ingin kamu lindungi. Bisa berupa payload JSON untuk webhook, serangkaian parameter URL, atau potongan data biner apa pun.
- Kunci Rahasia (The Secret Key): Serangkaian byte yang hanya diketahui oleh pengirim dan penerima. Ini adalah bahan ajaibnya. Jika bocor, seluruh sistem akan rusak.
- Fungsi Hash (The Hash Function): Algoritma standar seperti SHA-1, SHA-256, atau SHA-512. Pilihan fungsi hash menentukan panjang tanda tangan HMAC akhir (misalnya, HMAC-SHA256 menghasilkan tanda tangan 256-bit).
Resepnya (Algoritma HMAC)
Kamu mungkin berpikir bisa langsung melakukan hash(key + message). Kelihatannya simpel, tapi konstruksi ini rentan terhadap beberapa trik kripto cerdik yang disebut "serangan ekstensi panjang" (length extension attacks). Konstruksi HMAC yang resmi sedikit lebih rumit, sengaja dibuat untuk mencegah serangan-serangan ini. Ia menggunakan proses hashing ganda.
Berikut adalah langkah-langkahnya secara sederhana:
Siapkan Kunci: Fungsi hash beroperasi pada blok data berukuran tetap (misalnya, 64 byte untuk SHA-256). Kunci perlu disiapkan agar sesuai dengan ukuran blok ini.
- Jika kunci lebih panjang dari ukuran blok, kamu melakukan hash pada kunci itu sendiri dan menggunakan hasilnya sebagai kunci baru.
- Jika kunci lebih pendek dari ukuran blok, kamu mengisinya dengan byte nol hingga mencapai ukuran blok.
Buat Kunci Dalam dan Luar: Dari kunci yang telah disiapkan ini, kita menurunkan dua kunci terpisah.
ipad(inner pad): sebuah byte konstan (0x36) yang diulang-ulang untuk mengisi ukuran blok.opad(outer pad): byte konstan lain (0x5C) yang diulang-ulang untuk mengisi ukuran blok.
Kita membuat
inner_padded_keydengan mengambil kunci yang telah kita siapkan dan melakukan operasi XOR denganipad. Kita membuatouter_padded_keydengan melakukan XOR pada kunci yang telah disiapkan denganopad.Lakukan Hash Ganda: Sekarang bagian utamanya.
- Hash Dalam: Gabungkan
inner_padded_keydengan pesan asli, dan jalankan melalui fungsi hash. - Hash Luar: Gabungkan
outer_padded_keydengan hasil dari hash dalam, dan jalankan lagi melalui fungsi hash.
- Hash Dalam: Gabungkan
Hasil akhir dari hash luar inilah yang menjadi tanda tangan HMAC-mu!
Dalam pseudocode, kelihatannya seperti ini:
function hmac(key, message, hash_function, block_size) {
// 1. Siapkan kunci
if (key.length > block_size) {
key = hash_function(key);
}
if (key.length < block_size) {
key = pad_with_zeros(key, block_size);
}
// 2. Buat kunci dalam dan luar yang sudah di-pad
o_key_pad = key XOR (0x5C diulang sampai block_size);
i_key_pad = key XOR (0x36 diulang sampai block_size);
// 3. Lakukan hash ganda
inner_hash_result = hash_function(i_key_pad + message);
final_hmac = hash_function(o_key_pad + inner_hash_result);
return final_hmac;
}
Kenapa Hash Ganda?
Struktur dalam-lalu-luar ini adalah resep rahasianya. Hash bagian dalam menggabungkan rahasia dan pesan. Hash bagian luar pada dasarnya melakukan hash pada hasil operasi pertama lagi dengan rahasia. Ini "menyegel" hash bagian dalam. Hal ini membuatnya mustahil secara komputasi bagi penyerang untuk memanipulasi hasil hash perantara tanpa mengetahui kuncinya, sehingga menggagalkan serangan ekstensi panjang dan potensi pembobolan kriptografis lainnya. Ini adalah konstruksi yang terbukti tangguh dan telah teruji oleh waktu.
Cerita dari dunia nyata
Penjaga Webhook GitHub
Sebuah tim startup memiliki server continuous integration (CI) yang diatur untuk secara otomatis men-deploy aplikasi mereka ke production setiap kali ada yang push ke branch main. Pemicunya adalah webhook dari GitHub: sebuah request POST yang dikirim dari server GitHub ke URL publik di server CI mereka. Suatu malam, seorang anak magang yang iseng menemukan URL publik itu dan, dengan perintah cURL sederhana, mulai mengirim payload webhook palsu, memicu puluhan deployment yang tidak berguna dan memakan banyak sumber daya.
Developer senior di tim itu memperbaikinya dalam 15 menit. Di pengaturan webhook GitHub, dia membuat sebuah "secret" acak yang panjang. Dia menyalin secret ini dan mengkonfigurasikannya sebagai environment variable di server CI mereka. GitHub sekarang menggunakan secret ini untuk membuat tanda tangan HMAC-SHA256 untuk setiap payload webhook, mengirimkannya dalam header X-Hub-Signature-256. Kode di server CI diperbarui untuk melakukan perhitungan HMAC yang sama pada body request mentah yang diterimanya, menggunakan secret yang sama. Jika tanda tangan yang dihitung cocok dengan yang ada di header, permintaan diproses. Jika tidak, permintaan ditolak dengan 403 Forbidden. Keisengan itu pun langsung berhenti.
Pelajaran: Selalu amankan webhook Anda dengan verifikasi tanda tangan HMAC. Jangan percaya permintaan masuk apa pun sampai telah diautentikasi.
Mengamankan Toples Cookie API
Seorang developer sedang membangun layanan yang menggunakan cookie sederhana yang ditandatangani untuk autentikasi. Ketika pengguna login, server akan mengeluarkan cookie yang berisi user_id dan timestamp expiry. Untuk mencegah pengguna mengedit cookie mereka untuk menjadi pengguna lain (misalnya, mengubah user_id=123 menjadi user_id=1), developer tersebut menyertakan tanda tangan HMAC.
Payload cookie-nya kira-kira seperti ini: user_id=123&expiry=1678886400. Server akan menandatangani string persis ini dengan kunci rahasia yang disimpan di server. Cookie akhir yang dikirim ke browser adalah data="user_id=123&expiry=1678886400"&signature="sha1=2a8b...".
Ketika pengguna membuat permintaan berikutnya, browser mereka mengirimkan kembali cookie tersebut. Server akan mengambil bagian data, menghitung ulang tanda tangan HMAC menggunakan kunci rahasianya, dan membandingkannya dengan bagian signature dari cookie. Jika cocok, server tahu bahwa ID pengguna dan tanggal kedaluwarsa itu sah dan belum diutak-atik.
Pelajaran: HMAC adalah cara yang fantastis untuk membuat token atau cookie "stateless" yang anti-rusak, menjadi dasar bagi banyak sistem autentikasi, termasuk JSON Web Tokens (JWTs).
Transfer Bank yang Gagal Dibajak
Sebuah platform e-commerce terintegrasi dengan API prosesor pembayaran untuk memulai pembayaran ke vendor-vendornya. Panggilan API-nya adalah pesan JSON sederhana: {"vendor_id": "ven_abc", "amount": 500.00, "currency": "USD"}. Platform tersebut khawatir tentang serangan man-in-the-middle (MITM). Bahkan melalui HTTPS, yang mengenkripsi lalu lintas, penyerang yang canggih bisa (dalam beberapa skenario teoretis, seperti dengan otoritas sertifikat yang disusupi) mencegat dan mengubah permintaan. Mereka bisa mengubah amount menjadi 50000.00 atau vendor_id menjadi milik mereka sendiri.
API prosesor pembayaran tersebut mengharuskan setiap permintaan ditandatangani dengan HMAC-SHA512. Platform akan melakukan serialisasi payload JSON menjadi string kanonis, menghitung tanda tangan dengan kunci API pribadi mereka, dan mengirimkannya dalam header Authorization. Server prosesor pembayaran akan melakukan langkah-langkah yang persis sama. Jika tanda tangan yang mereka hitung cocok dengan yang dikirim di header, mereka tahu dua hal pasti: permintaan itu datang dari platform yang sah (autentisitas) dan vendor_id serta amount tidak diubah di tengah jalan (integritas).
Pelajaran: Untuk operasi berisiko tinggi, HMAC menyediakan lapisan keamanan penting untuk menjamin bahwa pengirim dan konten pesan sesuai dengan yang Anda harapkan.
Kesalahan dan jebakan umum
- Membocorkan kunci rahasia. Kunci adalah segalanya. Jika kamu mengeksposnya di JavaScript sisi klien, memasukkannya ke repositori Git publik, atau mencatatnya dalam teks biasa, keamananmu hilang. Perlakukan seperti kata sandi.
- Menggunakan perbandingan non-constant-time. Saat kamu memeriksa apakah tanda tangan yang diberikan pengguna cocok dengan yang kamu hitung, perbandingan string standar seperti
if (a === b)bisa menjadi celah keamanan. Fungsi ini sering kali mengembalikanfalsebegitu menemukan karakter yang tidak cocok. Ini menciptakan perbedaan waktu kecil yang dapat diukur oleh penyerang untuk menebak tanda tangan karakter demi karakter. Ini adalah "serangan timing" (timing attack). Selalu gunakan fungsi perbandingan "constant-time" khusus dari pustaka kripto yang membutuhkan waktu yang sama terlepas dari di mana ketidakcocokan terjadi. - Menandatangani data yang salah. Pengirim dan penerima harus menghitung HMAC pada urutan byte yang sama persis. Bug yang umum terjadi adalah satu pihak menandatangani objek JSON yang sudah dipercantik (prettified) sementara pihak lain menandatangani versi ringkas satu baris. Atau satu pihak menyertakan karakter baris baru di akhir (trailing newline) dan pihak lain tidak. Kamu harus menyepakati format pesan kanonis dan menaatinya.
- Melupakan serangan replay (replay attacks). HMAC sendiri tidak menghentikan penyerang untuk menangkap pesan yang valid dan ditandatangani lalu mengirimkannya berulang-ulang. Jika pesan itu adalah "bayar Bob $10," kamu tidak ingin penyerang bisa memicu pembayaran itu 1000 kali. Untuk mencegah ini, sertakan nilai yang berubah setiap permintaan—seperti timestamp atau "nonce" (number used once / angka yang hanya digunakan sekali)—di dalam data yang ditandatangani. Server kemudian dapat memeriksa timestamp untuk menolak permintaan lama atau menyimpan daftar nonce yang telah digunakan untuk menolak duplikat.
Kenapa ini perlu kamu perhatikan
Kamu harus memikirkan HMAC setiap kali berurusan dengan komunikasi yang perlu dipercaya. Ini bukan tentang menjaga kerahasiaan data (itu tugas enkripsi), tapi tentang memastikan data tersebut sah.
- Membangun atau menggunakan API? Terutama dengan webhook (dari layanan seperti Stripe, GitHub, Twilio), HMAC adalah standar industri untuk memverifikasi bahwa permintaan itu asli.
- Bekerja dengan autentikasi? Banyak sistem berbasis token, yang paling terkenal adalah JWT, menggunakan HMAC (misalnya, algoritma 'HS256') untuk menandatangani payload token, mencegah pengguna mengubah izin mereka sendiri.
- Perlu memverifikasi integritas data? Jika kamu meneruskan data melalui lingkungan yang tidak tepercaya (seperti browser pengguna dalam sebuah cookie) dan perlu memastikan data itu kembali tanpa diubah, HMAC adalah alatmu.
Ini adalah alat fundamental dalam kotak peralatan keamanan seorang web developer. Memahami cara kerjanya akan membuatmu menjadi insinyur yang lebih baik dan lebih sadar akan keamanan.
Gali lebih dalam
- RFC 2104: HMAC: Keyed-Hashing for Message Authentication: Spesifikasi teknis aslinya. Isinya padat, tapi ini adalah sumber kebenaran tertinggi.
- Wikipedia: HMAC: Gambaran umum tingkat tinggi yang bagus tentang sejarah, prinsip desain, dan detail implementasi.
- OWASP: Replay Attack: Halaman dari Open Web Application Security Project tentang serangan replay, sebuah konsep penting untuk dipahami saat menggunakan HMAC.
- Stripe Docs: Checking webhook signatures: Panduan praktis dari dunia nyata oleh perusahaan yang sangat bergantung pada HMAC untuk mengamankan transaksi miliaran dolar.
- Crypto 101: HMAC: Penjelasan yang sedikit lebih mudah diakses tentang prinsip-prinsip kriptografi di balik desain HMAC.