Password Hashing & Storage — Security

Kenapa Tidak Boleh Simpan Password Plain Text? Jika database bocor dan password disimpan dalam plain text, semua akun pengguna langsung terekspos. Banyak…

Password hashing itu soal menyimpan password tanpa pernah menyimpan password aslinya. Bayangin kamu mau memverifikasi kunci rumah seseorang tanpa menyimpan kuncinya: kamu simpan foto pola giginya saja. Dari foto itu kamu bisa mencocokkan kunci yang datang, tapi kamu tidak bisa membentuk ulang kuncinya dari foto. Hash adalah foto pola gigi itu: sidik jari satu arah dari password.

🧪 Tebakan cepat: dua orang kebetulan pakai password yang sama, password123. Kalau password mereka di-hash pakai SHA-256, hash-nya sama atau beda? Tebak dulu, jawabannya ada di bagian "Kenapa hash cepat itu salah".

Jangan simpan plain text

Kalau database bocor dan password tersimpan apa adanya (plain text), semua akun langsung terekspos. Lebih parah lagi, banyak orang pakai password yang sama di banyak layanan, jadi satu kebocoran menyeret akun-akun lain. Maka password tidak pernah disimpan apa adanya. Yang disimpan adalah hash-nya.

Hash: sidik jari satu arah

Hash mengubah teks apa pun jadi deretan karakter dengan panjang tetap, dan prosesnya satu arah: gampang dari password ke hash, (nyaris) mustahil balik dari hash ke password. Waktu login, server meng-hash password yang kamu ketik, lalu membandingkan dengan hash yang tersimpan. Cocok berarti benar.

Kenapa hash cepat itu salah

Hash seperti MD5, SHA-1, dan SHA-256 dibuat untuk cepat. Untuk file itu bagus, untuk password itu bencana. Di Lab, hash rahasia123 dengan SHA-256:

SHA-256("rahasia123")
= bee5688aea66a47460b19c76f8f199c6b9585eb726f8322b1429793863609ca2

Hash yang sama persis muncul setiap kali, karena SHA-256 deterministik: input sama, output sama. Ada tiga masalah dari situ:

Kesimpulannya: jangan pakai MD5, SHA-1, atau SHA-256 untuk password.

Salt: bikin tiap hash unik

Salt adalah string acak yang digabungkan ke password sebelum di-hash. Tiap user dapat salt berbeda, jadi:

Salt tidak rahasia; dia disimpan bersama hash. Tujuannya bukan menyembunyikan, tapi membuat tiap hash unik.

bcrypt dan argon2id: sengaja lambat

bcrypt dan argon2id dirancang khusus untuk password, dengan dua sifat yang hilang di SHA-256:

Hash-nya kelihatan begini (perhatikan formatnya, bukan nilainya):

bcrypt   : $2b$12$R9h/cIPz0gi.URNNX3kh2OPST9/PgBkqquzi.Ss7KIUgO2t0jWMUW
argon2id : $argon2id$v=19$m=19456,t=2,p=1$c29tZXNhbHQ$RdescudvJCsgt3ub...

Rekomendasi OWASP saat ini: pakai argon2id (minimal memori 19 MiB, iterasi 2, paralelisme 1), atau bcrypt dengan cost minimal 10. Atur cost sampai satu kali hashing memakan waktu sekitar seperempat detik di servermu.

Di PHP: password_hash dan password_verify

Di latihan, PHP sudah menyediakan ini dengan aman:

$password = "rahasia123";
$hash = password_hash($password, PASSWORD_DEFAULT); // bcrypt, salt otomatis
echo "Hash berhasil dibuat\n";

// Verifikasi: cocokkan password mentah dengan hash tersimpan
echo "Password cocok: " . (password_verify("rahasia123", $hash) ? "true" : "false") . "\n";
echo "Password salah: " . (password_verify("password_salah", $hash) ? "true" : "false") . "\n";

⚠️ Jebakan yang sering ketemu

TL;DR: Password disimpan sebagai hash satu arah, bukan plain text. MD5/SHA-256 salah untuk password: terlalu cepat (sekitar sepuluh miliar tebakan per detik di GPU), deterministik (password sama = hash sama, jadi rainbow table jalan). Salt bikin tiap hash unik. bcrypt dan argon2id sengaja lambat lewat cost factor dan punya salt otomatis. Di PHP, password_hash($pw, PASSWORD_DEFAULT) (bcrypt) untuk membuat, password_verify($input, $hash) untuk mencocokkan. OWASP sekarang: argon2id (19 MiB, t=2, p=1) atau bcrypt cost minimal 10.

Yang akan kamu pelajari