Password Hashing untuk Developer — Mengapa bcrypt, Argon2, dan scrypt Lebih Aman daripada MD5
Aku masih ingat masa-masa pertama kali membuat sistem login. Saat itu, aku menyimpan password user langsung sebagai teks biasa di database MySQL. Rasanya praktis: login cukup bandingkan password_input == password_database, selesai. Baru setelah baca artikel tentang kebocoran data, aku sadar bahwa praktik itu ibarat menyimpan kunci rumah di bawah keset depan pintu. Terlihat mudah, tapi begitu ada yang mengangkat keset, semua pintu terbuka.
Dari situ aku mulai belajar soal password hashing. Ternyata, menyimpan password bukan soal menyembunyikan teks, melainkan mengubahnya menjadi representasi yang tidak bisa dibalik — bahkan oleh pemilik sistem sekalipun. Artikel ini adalah catatan perjalananku memahami bcrypt, Argon2, scrypt, dan mengapa algoritma lama seperti MD5 sudah tidak pantas digunakan lagi.
Hashing Bukan Encryption, dan Itu Penting
Banyak pemula yang mengira hashing dan encryption itu sama. Padahal keduanya beda seperti kotak surat dan kotak aman. Encryption adalah kotak aman yang bisa dibuka kembali dengan kunci. Hashing adalah kotak surat yang hanya bisa dimasukkan surat, tapi tidak bisa diambil lagi. Hasilnya sekali masuk, tidak ada jalan keluar.
Ketika kita meng-hash password, kita tidak ingin bisa mengembalikannya menjadi teks asli. Yang kita butuhkan hanyalah kemampuan untuk memverifikasi: apakah password yang diketik user saat login menghasilkan hash yang sama dengan yang tersimpan? Jika iya, akses diterima. Jika tidak, tolak.
Konsep ini disebut one-way function. Fungsi yang mudah dijalankan ke satu arah, tapi sangat sulit dibalik. Bayangkan seperti membuat smoothie: mudah memblender buah-buahan, tapi hampir mustahil memisahkannya kembali menjadi apel, pisang, dan mangga dalam bentuk utuh.
Kenapa MD5 dan SHA1 Tidak Lagi Cukup?
Dulu, MD5 adalah raja. Semua tutorial PHP jaman awal-awal pakai md5($password). Tapi lama-kelamaan, MD5 menunjukkan kelemahan fatal: dia terlalu cepat. Kecepatan memang biasanya keunggulan di komputasi, tapi dalam konteks hashing password, kecepatan justru jadi bumerang.
Semakin cepat sebuah algoritma menghasilkan hash, semakin cepat pula attacker bisa mencoba miliaran kombinasi password dalam satu detik. Teknik ini disebut brute-force atau dictionary attack. Dengan GPU modern, satu komputer bisa mencoba triliunan hash MD5 per detik. Password seperti "P@ssw0rd123" bisa dipecahkan dalam hitungan menit.
Selain itu, MD5 juga rentan terhadap collision: dua input berbeda bisa menghasilkan hash yang sama. Meski collision tidak langsung membuka password, ini menunjukkan bahwa struktur MD5 sudah tidak solid. Sama seperti fondasi rumah yang retak — mungkin masih berdiri, tapi tidak layak dihuni.
SHA1 punya masalah serupa. Keduanya dirancang untuk kecepatan, bukan untuk keamanan password. Mereka bagus untuk checksum file, tapi salah tempat jika dipakai untuk menyimpan credential.
Salt: Biar Setiap Hash Jadi Unik
Sebelum masuk ke algoritma modern, ada satu konsep penting: salt. Bayangkan kamu membuat mi instan. Jika semua orang pakai bumbu yang sama, hasilnya akan sama. Tapi jika setiap orang menambahkan sedikit bahan rahasia yang berbeda — satu sendok kecap, sejumput cabai, setengah sendok minyak wijen — maka mi yang sama jadi punya rasa berbeda. Itulah salt.
Dalam hashing, salt adalah string acak yang ditambahkan ke password sebelum di-hash. Salt disimpan bersama hash di database. Jadi walau dua user memiliki password "123456", hash mereka akan berbeda karena salt masing-masing berbeda. Ini menghancurkan efisiensi rainbow table, yaitu tabel precomputed hash untuk password umum.
Tanpa salt, attacker bisa mencocokkan hash hasil bocoran dengan rainbow table dan langsung menemukan password. Dengan salt, mereka harus menyerang setiap hash satu per satu, memperlambat proses secara drastis. Tapi salt saja tidak cukup jika algoritma dasarnya masih cepat seperti MD5.
bcrypt: Standar Lama yang Masih Dipercaya
bcrypt adalah algoritma hashing password yang dirancang khusus untuk perlambatan. Dia menggabungkan salt secara internal, sehingga developer tidak perlu mengelola salt secara manual. Yang paling menarik: bcrypt punya parameter cost factor yang menentukan seberapa banyak iterasi dilakukan. Cost factor bisa dinaikkan seiring bertambahnya kecepatan hardware.
Di PHP, bcrypt digunakan secara otomatis lewat fungsi password_hash() dan password_verify(). Ini adalah salah satu API terbaik yang pernah aku temui: sederhana, aman, dan tidak bisa salah digunakan dengan mudah.
12]);
// $hash berisi salt + cost + hash dalam satu string
// Saat login
if (password_verify($password, $hash)) {
// Login berhasil
}
// Upgrade cost factor jika perlu
if (password_needs_rehash($hash, PASSWORD_BCRYPT, ['cost' => 13])) {
$hash = password_hash($password, PASSWORD_BCRYPT, ['cost' => 13]);
}
?>
Nilai cost yang umum saat ini berkisar antara 10 hingga 13. Semakin tinggi, semakin lambat proses hashing. Biasanya kita pilih cost factor yang membuat proses hashing memakan waktu sekitar 250-500 milidetik. Itu cukup lambat untuk menghambat brute-force, tapi masih nyaman untuk satu user yang login.
Argon2: Juara Password Hashing Competition
Argon2 adalah pemenang Password Hashing Competition tahun 2015. Dia dirancang untuk lebih tangguh terhadap serangan dengan hardware khusus seperti GPU dan ASIC. Argon2 punya tiga varian: Argon2d, Argon2i, dan Argon2id. Untuk password, yang paling direkomendasikan adalah Argon2id, karena menawarkan perlindungan terbaik dari berbagai jenis serangan.
Yang membuat Argon2 istimewa adalah penggunaan memory-hard. Bukan hanya CPU yang dibebani, tapi juga memori. Ini membuat serangan dengan GPU jauh lebih mahal karena GPU biasanya punya memori terbatas per thread. Analoginya: jika bcrypt membuat attacker berjalan kaki, Argon2 membuat mereka berjalan kaki sambil membawa batu besar di punggung.
Di PHP 7.2+, Argon2 tersedia sebagai opsi default untuk password_hash(). Konfigurasinya sedikit lebih kompleks dari bcrypt karena ada tiga parameter: memory cost, time cost, dan threads.
65536, // 64 MB
'time_cost' => 4, // iterasi
'threads' => 3 // parallelism
]);
// Verifikasi tetap sama
if (password_verify($password, $hash)) {
// Login berhasil
}
?>
Parameter di atas bisa disesuaikan dengan kapasitas server. Penting untuk tidak memilih nilai terlalu rendah, karena akan mengurangi perlindungan terhadap serangan hardware. Sebaliknya, nilai terlalu tinggi bisa membuat server kewalahan jika ada banyak login bersamaan.
scrypt: Alternatif Memory-Hard yang Andal
scrypt adalah algoritma memory-hard yang dirancang oleh Colin Percival. Tujuan utamanya sama dengan Argon2: membuat brute-force dengan hardware khusus menjadi tidak efisien. scrypt banyak digunakan di dunia cryptocurrency, termasuk Litecoin, sebelum akhirnya disusul oleh Argon2.
Meski scrypt tidak menjadi pemenang kompetisi, dia masih dianggap aman dan digunakan di beberapa sistem. Bedanya dengan bcrypt: bcrypt lebih terbatas pada CPU cost, sementara scrypt juga menambahkan memory cost. Jika bcrypt seperti mengunci pintu dengan banyak kunci, scrypt mengunci pintu dengan banyak kunci dan membuat ruangan di belakangnya sempit sehingga susah bergerak.
Di PHP, scrypt tidak tersedia secara native lewat password_hash(). Jika ingin menggunakannya, biasanya perlu ekstensi tambahan atau library pihak ketiga. Untuk sebagian besar aplikasi web modern, bcrypt atau Argon2 sudah lebih dari cukup.
Pepper: Lapisan Rahasia Tambahan
Selain salt, ada konsep yang lebih jarang dibahas: pepper. Jika salt adalah bahan unik yang disimpan bersama hash, maka pepper adalah rahasia global yang disimpan terpisah dari database. Biasanya pepper disimpan di file konfigurasi server atau environment variable, bukan di database.
Fungsi pepper adalah memberikan lapisan perlindungan tambahan jika database bocor. Attacker yang hanya mendapatkan dump database tidak akan bisa memverifikasi password tanpa mengetahui pepper. Ini seperti memiliki brankas di rumah dengan dua kunci: satu kunci disimpan di brankas itu sendiri, satu lagi selalu ada di sakumu.
Namun, pepper harus digunakan dengan hati-hati. Jika pepper hilang atau berubah, semua password menjadi tidak bisa diverifikasi. Dia bukan pengganti salt, melainkan pelengkap. Alurnya biasanya: gabungkan password + salt, hash, lalu gabungkan hasil dengan pepper, hash sekali lagi.
Best Practices yang Aku Terapkan
Setelah memahami berbagai algoritma, aku menyimpulkan beberapa praktik dasar yang selalu aku coba terapkan:
- Jangan pernah menyimpan password dalam bentuk plaintext atau reversible encryption.
- Gunakan
password_hash()danpassword_verify()di PHP; jangan membuat algoritma hashing sendiri. - Pilih Argon2id jika tersedia, fallback ke bcrypt dengan cost factor yang tinggi.
- Gunakan salt yang unik dan otomatis untuk setiap password.
- Terapkan kebijakan password yang kuat di sisi client dan server, tapi ingat bahwa kebijakan saja tidak menggantikan hashing yang baik.
- Pertimbangkan rate limiting dan account lockout untuk menghambat brute-force.
- Siapkan incident response plan jika database bocor, termasuk memaksa user mengganti password.
Yang paling penting dari semua: jangan pernah merasa keamanan adalah satu tugas yang selesai. Keamanan adalah proses. Algoritma yang hari ini dianggap aman, besok bisa saja tidak lagi. Makanya fungsi seperti password_needs_rehash() sangat berguna: dia memungkinkan kita meningkatkan keamanan secara bertahap tanpa mengganggu user.
Kesimpulan
Password hashing adalah salah satu fondasi keamanan aplikasi yang sering dianggap remeh. Padahal, satu kesalahan di sini bisa berakibat fatal saat data bocor. MD5 dan SHA1 mungkin masih terlihat di banyak tutorial lama, tapi mereka bukan pilihan yang tepat untuk menyimpan password. Gunakan bcrypt, Argon2id, atau scrypt — algoritma yang dirancang untuk perlambatan dan ketahanan terhadap serangan modern.
Bagiku, memahami password hashing seperti belajar mengunci rumah dengan benar. Kunci yang bagus tidak harus rumit, tapi harus benar. Dan yang terpenting, kita harus tahu mengapa kunci itu dipilih.
Kalau kamu punya pengalaman atau pendapat lain soal password hashing, silakan tinggalkan di kolom komentar. Aku senang belajar dari sudut pandam yang berbeda. Jika artikel ini bermanfaat, jangan ragu untuk membagikannya.