Skip to content
Kembali ke Blog
Keamanan

bcrypt vs Argon2 vs scrypt: hashing password 2026

Bandingkan bcrypt, Argon2id, dan scrypt dengan parameter OWASP 2026, kerangka keputusan, dan contoh kode. Pilih hash yang sesuai untuk aplikasi Anda.

18 menit membaca

bcrypt vs Argon2 vs scrypt: hashing password 2026

Jawaban singkat: untuk proyek baru apa pun di 2026, pakai Argon2id dengan m=19456, t=2, p=1. Itu baseline dari OWASP Password Storage Cheat Sheet, dan ini algoritma hashing password dengan ketahanan GPU dan saluran samping (side-channel) paling kuat yang bisa Anda kirim ke produksi sekarang.

Kalau Argon2 tidak tersedia di stack Anda (jarang, tapi kadang muncul di runtime embedded atau lama), pakai scrypt dengan N=2^17, r=8, p=1. Pakai bcrypt dengan cost=12 hanya kalau Anda terjebak di sistem lama yang sudah memakai bcrypt dan tidak bisa menambah dependensi baru. Pakai PBKDF2-HMAC-SHA-256 dengan 600.000 iterasi ketika kepatuhan FIPS-140 wajib.

AlgoritmaParameter OWASP 2026Kapan dipilih
Argon2idm=19456 KiB, t=2, p=1Default untuk proyek baru
scryptN=2^17, r=8, p=1Argon2 tidak tersedia
bcryptcost=12 (min 10)Hanya sistem lawas
PBKDF2HMAC-SHA-256, 600k iterasiFIPS-140 wajib

Sisa artikel ini menjelaskan alasan di balik angka-angka itu, cara menyetelnya di perangkat keras Anda, dan cara migrasi tanpa memaksa pengguna reset password. Butuh password uji yang kuat untuk benchmarking? Pakai Generator Kata Sandi Acak. Untuk gambaran yang lebih luas, baca Dasar-Dasar Keamanan Web.

Kenapa hashing password beda dari hashing umum

Fungsi hash terlihat mirip dari luar: data masuk, digest panjang tetap keluar, dan tidak bisa dibalik. Tapi tujuan desain “hash file ISO 4 GB” dan “hash password 12 karakter” justru berlawanan. Yang pertama harus secepat yang silikon mampu. Yang kedua harus selambat yang masih bisa ditoleransi anggaran latensi login Anda.

Mencampur keduanya adalah pintu masuk dari kebocoran data ke pengambilalihan akun.

Kenapa MD5 dan SHA-256 tidak cukup untuk password

Hash serbaguna seperti MD5, SHA-1, dan SHA-256 dirancang untuk throughput. Mereka memproses gigabyte per detik di CPU komoditas dan puluhan gigabyte per detik di GPU. Itu bagus untuk checksum file dan content addressing, tapi berbahaya untuk password.

Benchmark Hashcat di satu RTX 4090 menunjukkan sekitar 164 GH/s untuk MD5 dan 22 GH/s untuk SHA-256 pada 2024. Password 8 karakter huruf kecil alfanumerik (36^8 ≈ 2,8 × 10^12 kandidat) tumbang di satu GPU dalam waktu kurang dari semenit terhadap MD5 dan beberapa menit terhadap SHA-256. Database bocor berisi sha256(password) praktis sama saja dengan plaintext.

Salt juga tidak menolong. Salt memang mencegah rainbow table prakomputasi, tapi tidak memperlambat serangan per akun: penyerang tinggal menghash setiap kandidat yang digabung dengan salt yang sudah ikut bocor.

Untuk checksum non-keamanan, MD5 dan SHA-256 tetap berguna, dan itulah peran alat seperti MD5 & SHA-256 Hash Generator. Untuk perbandingan mendalam kapan tiap algoritma cocok, baca MD5 vs SHA-256. Tapi untuk password, Anda butuh hash yang sengaja lambat.

Tiga properti hash password modern

Hash password yang layak dirilis pada 2026 punya tiga properti:

  1. Lambat secara desain, dengan work factor yang bisa disetel. Login idealnya memakan 100–500 ms, cukup cepat sehingga pengguna tidak terasa, tapi cukup lambat agar penyerang offline membakar berhari-hari per sejuta tebakan. Work factor harus berupa parameter agar bisa Anda naikkan seiring perangkat keras makin kuat.
  2. Salt per-record. Salt acak yang unik per password mematahkan rainbow table dan memaksa penyerang menyerang setiap akun secara individual. Algoritma modern membuat dan menanam salt di string keluaran untuk Anda.
  3. Memory-hard. GPU dan ASIC cepat dalam komputasi tapi mahal dalam memori bandwidth tinggi. Algoritma yang butuh puluhan MiB per hash memaksa penyerang menyiapkan RAM sebanding dengan paralelismenya, dan itu mematikan efektivitas biaya peternakan GPU.

bcrypt memenuhi (1) dan (2) tapi bukan (3). scrypt adalah algoritma pertama yang memenuhi ketiganya. Argon2 memperhalus desainnya dan memenangkan Password Hashing Competition. Bagian berikut membahas masing-masing.

Tiga algoritma: arsitektur dan tradeoff

bcrypt: berbasis Blowfish, time-hard

bcrypt dirancang pada 1999 oleh Niels Provos dan David Mazières untuk OpenBSD. Algoritma ini dibangun di atas cipher Blowfish, dengan fase key-setup mahal (“EksBlowfish”) yang diulang sebanyak 2^cost kali. Satu-satunya parameter yang bisa disetel adalah cost factor (kadang disebut “log rounds”): setiap kenaikan satu satuan menggandakan beban kerja. Hash cost=10 menjalankan 1.024 key schedule; cost=14 menjalankan 16.384.

Hash bcrypt tampak seperti ini:

$2b$12$R9h/cIPz0gi.URNNX3kh2OPST9/PgBkqquzi.Ss7KIUgO2t0jWMUW
 │  │  │                      │
 │  │  │                      └─ 31-char base64 hash
 │  │  └─ 22-char base64 salt
 │  └─ cost factor (12)
 └─ algorithm identifier ($2b$ = bcrypt v2)

Format ini self-describing: verify() membaca cost dan salt dari string yang tersimpan, tanpa perlu kolom terpisah.

Kekurangannya nyata. Footprint memori bcrypt sekitar 4 KiB, cukup kecil sehingga GPU kelas atas bisa menjalankan ribuan core bcrypt paralel. Selain itu, bcrypt diam-diam memotong masukan di 72 byte. Passphrase 100 karakter punya keamanan yang sama dengan 72 byte pertamanya. Cost maksimum 31, tapi apa pun di atas sekitar 16 mulai menyakiti latensi login di perangkat keras komoditas.

scrypt: pelopor memory-hard

scrypt dipublikasikan pada 2009 oleh Colin Percival untuk layanan backup Tarsnap dan distandarkan sebagai RFC 7914 pada 2016. Algoritma ini memperkenalkan gagasan memory-hardness: algoritma mengisi buffer besar dengan data pseudo-random, lalu membaca dari posisi acak, memaksa setiap implementasi benar-benar mengalokasikan memori itu.

scrypt menerima tiga parameter:

  • N: biaya CPU/memori (harus pangkat dari 2)
  • r: ukuran blok dalam byte (pengali pada memori dan ronde mixing)
  • p: paralelisme (komputasi independen, terutama untuk menskalakan waktu CPU tanpa menskalakan memori)

Pemakaian memori kira-kira 128 × N × r byte. Dengan rekomendasi OWASP N=2^17, r=8, itu sama dengan 128 × 131072 × 8 = 134.217.728 byte, atau tepat 128 MiB per hash.

scrypt juga key derivation function, bukan sekadar password hash. Algoritma ini dipakai di dompet kripto, enkripsi disk penuh, dan proof-of-work Litecoin yang asli. Peran ganda itu praktis ketika Anda butuh penyimpanan password sekaligus derivasi kunci dari satu pustaka.

Argon2 (id/i/d): pemenang Password Hashing Competition

Password Hashing Competition berlangsung dari 2013 sampai 2015, mengevaluasi 24 algoritma kandidat berdasarkan memory-hardness, ketahanan saluran samping, dan kesederhanaan implementasi. Argon2 menang, dan distandarkan sebagai RFC 9106 pada 2021.

Argon2 punya tiga varian. Perbedaannya ada pada cara memori dialamatkan selama mixing:

  • Argon2d memakai alamat memori data-dependent. Pilihan ini memaksimalkan ketahanan terhadap serangan GPU dan ASIC tapi membocorkan informasi lewat saluran samping cache-timing. Cocok untuk proof-of-work kripto, bukan otentikasi.
  • Argon2i memakai alamat data-independent. Aman terhadap saluran samping, tapi sedikit lebih lemah terhadap serangan tradeoff GPU.
  • Argon2id hibrida: paruh pertama dari pass pertama memakai pengindeksan Argon2i (aman saluran samping), sisanya memakai pengindeksan Argon2d (tahan GPU). RFC 9106 secara eksplisit merekomendasikan Argon2id untuk hashing password, begitu juga OWASP.

Argon2 menerima tiga parameter:

  • m: memori dalam KiB
  • t: biaya waktu (jumlah pass terhadap buffer memori)
  • p: paralelisme (jumlah lane yang diproses bersamaan)

Hash Argon2id memakai format string PHC dan tampak seperti ini:

$argon2id$v=19$m=19456,t=2,p=1$c29tZXNhbHQ$RdescudvJCsgt3ub+b+dWRWJTmaaJObG

Seperti bcrypt, semua parameter ditanam di string, sehingga verify() tidak butuh tabel parameter terpisah.

Parameter rekomendasi OWASP 2026

OWASP Password Storage Cheat Sheet adalah rujukan kanonik. Angka di bawah sesuai dengan panduan terkini di sana. Angka-angkanya konservatif, diukur untuk web server tipikal dengan anggaran latensi login 100–500 ms, dan Anda tetap perlu benchmark di perangkat keras Anda sendiri sebelum rilis.

Parameter Argon2id: pilihan pertama

Rekomendasi baseline OWASP: m=19456 (19 MiB), t=2, p=1.

Kalau server Anda punya headroom RAM lebih besar, Anda bisa menggeser beban kerja antara memori dan waktu. RFC 9106 menerbitkan profil ekuivalen; OWASP merekomendasikan salah satu dari berikut:

memoryCost (m)timeCost (t)parallelism (p)RAM per hash
471041146 MiB
194562119 MiB (baseline)
122883112 MiB
9216419 MiB
7168517 MiB

Aturan praktis penyetelan. Pilih m lebih dulu berdasarkan anggaran RAM untuk login bersamaan puncak. Kalau Anda memperkirakan 100 login simultan dan punya 4 GiB cadangan, itu 40 MiB per hash. Lalu naikkan t sampai satu verify makan 100–500 ms di CPU produksi Anda. Biarkan p=1 kecuali Anda punya alasan multi-core spesifik untuk mengubahnya (kebanyakan framework web sudah memberi setiap request thread sendiri).

Parameter scrypt: kalau Argon2 tidak ada

Rekomendasi OWASP: N=2^17 (131072), r=8, p=1, yang pakai 128 MiB per hash.

Kalau 128 MiB per login bersamaan terlalu berat untuk server Anda, OWASP membolehkan profil yang lebih lemah:

NrpRAM per hash
2^1781128 MiB (preferred)
2^168164 MiB
2^158132 MiB

N harus pangkat dua. Menaikkan r menambah memori dan beban CPU secara proporsional; menaikkan p menambah beban CPU tanpa menambah memori per instance. Untuk hashing password, biarkan r dan p di nilai default dan setel hanya N.

bcrypt: cost factor 10+ hanya untuk sistem lama

OWASP tidak lagi merekomendasikan bcrypt untuk proyek baru, tapi bcrypt masih ada di mana-mana, dari Devise, Spring Security, ASP.NET Identity, sampai tak terhitung sistem auth bikinan sendiri yang memakainya sebagai default.

Kalau Anda terjebak dengan bcrypt, aturannya:

  • bcrypt cost factor minimum: 10. Di bawah 10 cukup cepat sehingga satu GPU menyelesaikan database bocoran dalam hitungan hari.
  • Direkomendasikan: 12 sampai 14, tergantung perangkat keras. Di server x86 modern, cost=12 butuh sekitar 250 ms per hash; cost=13 butuh 500 ms.
  • Targetkan 100–300 ms per verify di perangkat keras produksi Anda. Benchmark, jangan menebak.
  • Ingat batas masukan 72 byte. Kalau pengguna boleh memilih passphrase, pre-hash dengan SHA-256 (lihat FAQ).

Ketahanan GPU bcrypt dibatasi oleh footprint memori 4 KiB. Tidak ada cost factor bcrypt yang akan menyamai memory-hardness Argon2id, jadi pilih Argon2id kalau bisa.

Referensi praktis: di server EPYC 2024, bcrypt(cost=12) berjalan sekitar 250 ms; di laptop kelas atas, lebih dekat ke 350 ms. Kalau angka Anda meleset satu orde besaran dari rentang 100–500 ms, periksa ulang apakah pustaka Anda benar-benar memakai bcrypt native atau jatuh ke polyfill JavaScript yang lambat (sebagian bundler menanggalkan dependensi native dalam build serverless).

PBKDF2: jalur kepatuhan FIPS-140

PBKDF2 (RFC 8018) adalah algoritma pilihan terakhir dalam panduan keamanan. Lebih tua dari bcrypt, bukan memory-hard, dan jatuh ke serangan GPU lebih cepat daripada ketiganya di atas. Tapi ini satu-satunya primitif hashing password yang tervalidasi FIPS-140, dan itu penting untuk pemerintah federal, HIPAA layanan kesehatan, dan deployment finansial tertentu.

Kalau Anda butuh PBKDF2, pakai:

  • HMAC-SHA-256 sebagai PRF (jangan pakai SHA-1; jangan pakai SHA-256 polos tanpa HMAC)
  • Minimal 600.000 iterasi (baseline OWASP 2026)
  • Salt acak 16-byte per password

Kalau FIPS tidak berlaku bagi Anda, pilih Argon2id. Desain PBKDF2 yang berukuran output tetap dan berukuran memori tetap berarti setiap dolar silikon GPU yang dibeli penyerang langsung jadi tebakan password per detik tambahan.

SP 800-63B dari NIST menyebut PBKDF2-HMAC “approved” untuk hashing password tapi tidak sampai merekomendasikannya di atas alternatif memory-hard. Baca itu sebagai: NIST mengizinkan PBKDF2 karena memensiunkannya akan membatalkan setiap deployment pemerintah lama, bukan karena ini pilihan terbaik untuk proyek greenfield.

Kerangka keputusan: algoritma mana yang harus Anda pilih?

Tabel perbandingan

DimensibcryptscryptArgon2idPBKDF2
Memory-hardTidakYaYaTidak
Ketahanan GPUSedangTinggiSangat tinggiRendah
Ketahanan saluran sampingSedangSedangTinggi (id)Sedang
Kompleksitas parameter1 (cost)3 (N, r, p)3 (m, t, p)1 (iterasi)
Kematangan pustakaSangat baikBaikBaikSangat baik
Batas panjang masukan72 byteTidak adaTidak adaTidak ada
Standardisaside factoRFC 7914RFC 9106RFC 8018
Status OWASP 2026Hanya lawasAlternatifPilihan pertamaHanya FIPS

Pakai Argon2id sebagai default

Untuk proyek baru, yaitu aplikasi web tipikal di stack modern Node/Python/Go/Rust/JVM tanpa kendala FIPS, pakai Argon2id dengan m=19456, t=2, p=1. Anda dapat ketahanan GPU dan saluran samping paling kuat yang ada, format dengan parameter tertanam yang tetap aman saat pustaka diperbarui, dan tanpa kejutan batas panjang masukan. Ekosistem pustakanya matang: argon2 di npm, argon2-cffi di PyPI, golang.org/x/crypto/argon2, crate argon2 di crates.io, semuanya terawat dan ter-benchmark.

Kapan pilih scrypt atau bcrypt

Pilih scrypt kalau Argon2 tidak tersedia di runtime Anda (jarang sekali pada 2026, bahkan Cloudflare Workers dan Deno sekarang mendukungnya), atau kalau Anda sudah punya sistem berbasis scrypt di produksi dan biaya migrasi melebihi selisih keamanannya. scrypt tetap algoritma yang solid; cuma kurang halus di sisi saluran samping dibanding Argon2id.

Pilih bcrypt kalau Anda merawat sistem lama, ada kebutuhan keras untuk meminimalkan dependensi (tanpa kode native, tanpa paket tambahan), dan batas masukan 72 byte bisa diterima basis pengguna Anda. bcrypt sudah dideploy pada skala internet selama dua dekade; mode kegagalannya dipahami dengan baik.

Pilih PBKDF2 kalau regulator menyuruhnya. Itu satu-satunya alasan. Kalau auditor Anda menerima Argon2id (kini makin banyak diterima untuk beban kerja non-FIPS), pakai Argon2id.

Kesalahan umum yang harus dihindari

Sebagian besar kebocoran penyimpanan password dalam dekade terakhir bisa ditelusuri ke kumpulan kecil kesalahan rekayasa yang berulang. Tidak satu pun eksotik; semuanya bisa ditangkap dengan meninjau kode auth Anda sambil membuka daftar di bawah.

  • Hashing password dengan SHA-256 atau MD5 mentah. Ini kegagalan penyimpanan password paling besar. Lihat MD5 vs SHA-256 untuk alasan keduanya keliru untuk password.
  • Memakai satu salt global untuk semua pengguna. Salt harus unik per record. Argon2 dan bcrypt membuatkannya untuk Anda; jangan ditimpa.
  • Menyetel waktu hash di bawah 50 ms. Anda menukar keamanan demi peningkatan kecepatan yang tak terasa oleh pengguna mana pun. Target 100–500 ms.
  • Menyetel waktu hash di atas 1 detik. Anda menciptakan vektor denial-of-service terhadap endpoint login Anda sendiri. Batasi sekitar 500 ms.
  • Hashing password di sisi klien lalu mengirim digest-nya ke server. Hash itu sekarang adalah password. Siapa pun yang mencuri database bisa otentikasi tanpa perlu membalik. Hash di server, selalu.
  • Menyimpan parameter algoritma di kolom terpisah. Format string PHC sudah menanamnya di hash. Manfaatkan.
  • Mencatat password atau hash saat penanganan error. Keduanya milik pengguna, bukan agregator log Anda. Bersihkan di lapisan parsing request sebelum mencapai logger mana pun.
  • Memperlakukan exception verify() sebagai kegagalan otentikasi. Pustaka yang melempar exception pada hash tersimpan yang rusak harus memunculkan errornya, bukan diam-diam jatuh ke “password salah”. Bedakan antara “password salah” (return 401) dan “hash tersimpan rusak” (return 500 dan kirim alert ke on-call).

Implementasi di dunia nyata

Argon2id di Node.js

Paket argon2 (binding native ke implementasi referensi) adalah pilihan kanonik di Node:

import argon2 from 'argon2';

// Hashing saat signup atau ganti password
const hash = await argon2.hash(password, {
  type: argon2.argon2id,
  memoryCost: 19456,  // 19 MiB
  timeCost: 2,
  parallelism: 1,
});
// → '$argon2id$v=19$m=19456,t=2,p=1$<salt>$<hash>'

// Verifikasi saat login
const ok = await argon2.verify(hash, candidate);
if (!ok) throw new Error('Invalid credentials');

// Deteksi parameter usang dan re-hash setelah login berhasil
if (argon2.needsRehash(hash, { type: argon2.argon2id, memoryCost: 19456, timeCost: 2, parallelism: 1 })) {
  const upgraded = await argon2.hash(candidate, {
    type: argon2.argon2id, memoryCost: 19456, timeCost: 2, parallelism: 1,
  });
  await db.users.update({ id: user.id }, { password_hash: upgraded });
}

Langkah needsRehash adalah kunci migrasi jangka panjang: setiap login sukses jadi kesempatan untuk mengupgrade hash tersimpan ke parameter terkini, tanpa mengganggu pengguna.

Pola yang sama di Python dengan argon2-cffi:

from argon2 import PasswordHasher
from argon2.exceptions import VerifyMismatchError

ph = PasswordHasher(memory_cost=19456, time_cost=2, parallelism=1)

# Hash
stored = ph.hash(password)

# Verify
try:
    ph.verify(stored, candidate)
except VerifyMismatchError:
    raise ValueError('Invalid credentials')

# Re-hash saat parameter di-upgrade
if ph.check_needs_rehash(stored):
    stored = ph.hash(candidate)

Di Go dengan golang.org/x/crypto/argon2:

import (
    "crypto/rand"
    "golang.org/x/crypto/argon2"
)

func hashPassword(password string) ([]byte, []byte) {
    salt := make([]byte, 16)
    rand.Read(salt)
    hash := argon2.IDKey([]byte(password), salt, 2, 19456, 1, 32)
    return hash, salt
}

Pustaka standar Go tidak menyertakan encoder format PHC; kalau Anda memakai primitif argon2.IDKey langsung, Anda bertanggung jawab meng-encode parameter dan salt bersama hash-nya. Sebagian besar proyek Go memakai wrapper seperti github.com/alexedwards/argon2id untuk itu.

Rust dengan crate argon2 juga sama idiomatiknya:

use argon2::{Argon2, PasswordHasher, PasswordVerifier, password_hash::{SaltString, rand_core::OsRng}};

let salt = SaltString::generate(&mut OsRng);
let argon2 = Argon2::default();  // Argon2id, m=19456, t=2, p=1 by default
let hash = argon2.hash_password(password.as_bytes(), &salt)?.to_string();

// On verify
let parsed = argon2::password_hash::PasswordHash::new(&hash)?;
argon2.verify_password(candidate.as_bytes(), &parsed)?;

Di ketiga runtime itu, string yang dihasilkan saling kompatibel: hash yang dibuat di Node bisa diverifikasi mulus di Python atau Rust. Kompatibilitas lintas runtime itu membuat Argon2 jadi taruhan yang lebih aman untuk arsitektur poliglot dibanding wrapper yang spesifik per algoritma.

Pola migrasi bcrypt ke Argon2id

Anda hampir tidak pernah dapat kesempatan menghapus tabel users dan mulai dari nol. Pola migrasi yang benar sama dengan yang dipakai di bagian migrasi MD5-ke-bcrypt pada FAQ generator hash kami: upgrade lunak yang dipicu login.

Tambahkan kolom yang melacak algoritma:

ALTER TABLE users ADD COLUMN password_algo VARCHAR(16) NOT NULL DEFAULT 'bcrypt';

Saat login, dispatch ke verifier yang tepat:

async function verifyAndMaybeRehash(user, candidate) {
  let ok;
  if (user.password_algo === 'argon2id') {
    ok = await argon2.verify(user.password_hash, candidate);
  } else if (user.password_algo === 'bcrypt') {
    ok = await bcrypt.compare(candidate, user.password_hash);
    if (ok) {
      // Verify lawas berhasil → re-hash dengan Argon2id
      const newHash = await argon2.hash(candidate, {
        type: argon2.argon2id, memoryCost: 19456, timeCost: 2, parallelism: 1,
      });
      await db.users.update({ id: user.id }, {
        password_hash: newHash,
        password_algo: 'argon2id',
      });
    }
  }
  return ok;
}

Tetapkan jendela penyetopan 6–12 bulan. Kirim email “password Anda disimpan dengan metode usang, silakan login untuk mengupgrade” di bulan ke-9. Setelah 12 bulan, akun yang masih di bcrypt harus reset password paksa pada login berikutnya. Pengguna aktif bermigrasi diam-diam; akun tidak aktif kena friksi sekali.

Pola yang sama bekerja untuk migrasi dari scrypt atau PBKDF2. Satu-satunya state yang Anda butuhkan adalah kolom password_algo.

Pepper, batas panjang, dan jebakan encoding

Beberapa sudut tajam yang sering menggigit deployment nyata:

Pepper. Pepper adalah secret level aplikasi yang ditambahkan ke setiap password sebelum hashing, disimpan terpisah dari database (di KMS, env var, atau Hashicorp Vault). Kalau database Anda bocor tapi secret aplikasi Anda tidak, hash yang bocor tidak bisa diserang tanpa pepper. Terapkan sebagai HMAC, bukan konkatenasi:

import { createHmac } from 'crypto';
const peppered = createHmac('sha256', process.env.PEPPER).update(password).digest();
const hash = await argon2.hash(peppered, { type: argon2.argon2id, /* ... */ });

Rotasikan pepper jarang-jarang (perlu re-hashing) tapi tetap dukung rotasi dengan memberi versi: PEPPER_V2, dengan fallback ke PEPPER_V1 saat verify.

Batas 72-byte bcrypt. Kalau Anda harus memakai bcrypt sekaligus mendukung password panjang sembarang, pre-hash dengan SHA-256 dan encode base64 (menghindari NUL byte tertanam yang ditangani bcrypt secara tidak konsisten):

import { createHash } from 'crypto';
const prepped = createHash('sha256').update(password, 'utf8').digest('base64');
const hash = await bcrypt.hash(prepped, 12);

Transformasi prepped yang sama harus dijalankan saat verify. Dokumentasikan di kode auth Anda dengan komentar besar; versi-Anda di masa depan akan berterima kasih kepada versi-Anda saat ini.

Normalisasi UTF-8. String "café" bisa di-encode sebagai c-a-f-é (4 codepoint, NFC) atau c-a-f-e + combining acute (5 codepoint, NFD). Tampilannya identik tapi hash-nya berbeda. Selalu normalisasi ke NFC sebelum hashing:

const normalized = password.normalize('NFC');

Hal ini menggigit keyboard ponsel dan copy-paste dari PDF lebih sering daripada yang Anda kira.

Jangan pernah pre-hash di klien. Hash yang dihitung klien lalu dikirim ke server adalah password baru. Siapa pun yang membaca database Anda bisa otentikasi. Hash di server, titik. JWT tidak mengubah ini, lihat Cara Decode Token JWT untuk apa yang sebenarnya (dan tidak) dilakukan JWT untuk otentikasi.

Benchmark di perangkat keras produksi, bukan laptop Anda. Laptop Intel generasi ke-13 menjalankan Argon2id m=19456, t=2, p=1 dalam sekitar 35 ms. Parameter yang sama di instance EC2 t3.small lebih dekat ke 180 ms; di Raspberry Pi 4, di atas 600 ms. Pilih perangkat keras yang benar-benar menjalankan produksi, ukur 1.000 verify, dan setel dari mediannya. Variasi latensi login akibat cold start container serverless juga layak diukur; cold start Lambda bisa menambah 200–800 ms yang tidak ada hubungannya dengan hashing.

FAQ

Apa beda hashing password dengan enkripsi?

Hashing satu arah: Anda menghitung sidik jari panjang tetap yang tidak bisa dibalik untuk memulihkan masukannya. Enkripsi dua arah: dengan kunci yang tepat, Anda bisa dekripsi kembali ke aslinya. Password harus di-hash, bukan dienkripsi. Server seharusnya tidak bisa memulihkan password pengguna mana pun, supaya kebocoran database tidak otomatis jadi kebocoran kredensial.

Kenapa saya tidak boleh memakai SHA-256 saja untuk password?

SHA-256 dirancang untuk kecepatan. GPU modern menghitung 22 miliar hash SHA-256 per detik, artinya password 8 karakter huruf kecil dari database bocor jatuh dalam hitungan menit. Hash password butuh tiga properti yang tidak dimiliki SHA-256: eksekusi yang sengaja lambat, salt per-record, dan memory-hardness. Prinsip tradeoff yang sama sudah dijelaskan di panduan “Don’t Use MD5 for Security” pada generator hash kami, dan Anda bisa baca lebih lanjut soal cara penyerang mengubah hash lemah jadi plaintext di Entropi Password.

Apakah bcrypt masih aman pada 2026?

bcrypt sendiri belum dipecah. Key schedule berbasis Blowfish-nya tetap utuh secara kriptografis. Yang berubah adalah model ancamannya: GPU dan ASIC membuat ketiadaan memory-hardness pada bcrypt jadi kelemahan yang berarti dibanding Argon2id. Sikap OWASP 2026 adalah bcrypt bisa diterima untuk sistem lama dengan cost ≥ 10, tapi proyek baru sebaiknya memilih Argon2id.

Argon2i vs Argon2d vs Argon2id, yang mana sebaiknya saya pakai?

Pakai Argon2id. RFC 9106 menetapkannya sebagai varian yang direkomendasikan untuk hashing password. Argon2i bersifat data-independent (aman saluran samping tapi lebih lemah terhadap serangan tradeoff GPU). Argon2d bersifat data-dependent (kuat terhadap GPU tapi rentan saluran samping cache-timing). Argon2id adalah hibrida yang dapat keduanya sekaligus.

Bagaimana cara saya memilih parameter Argon2id untuk aplikasi saya?

Mulai dari baseline OWASP: m=19456, t=2, p=1. Lalu benchmark di CPU produksi Anda dan sesuaikan:

  1. Tentukan anggaran RAM per login (misal 50 MiB pada konkurensi puncak).
  2. Set m ke nilai itu atau di bawahnya.
  3. Jalankan argon2.hash() dalam loop dan ukur wall time.
  4. Naikkan t sampai mediannya berada di antara 100 dan 500 ms.

Biarkan p=1 kecuali Anda sudah profiling dan tahu paralelisme multi-lane membantu runtime Anda. Untuk server auth bertraffic tinggi, condongkan ke t lebih tinggi dan m lebih rendah agar headroom RAM lebih lapang.

Apa itu batas 72 byte bcrypt dan bagaimana menangani passphrase panjang?

bcrypt mengumpan masukan ke key schedule Blowfish, yang memotong di 72 byte. Passphrase 150 karakter punya keamanan yang sama dengan 72 byte pertamanya, sisanya diabaikan. Solusinya: pre-hash dengan SHA-256 (32 byte) atau SHA-512 (64 byte), encode base64 digest itu untuk menghindari NUL byte, lalu umpan ke bcrypt. Argon2id dan scrypt tidak punya batasan seperti ini; keduanya menerima masukan sepanjang apa pun secara langsung.

Bisakah saya migrasi bcrypt ke Argon2 tanpa memaksa pengguna reset password?

Bisa. Polanya: simpan kedua algoritma di balik kolom password_algo, dispatch verifikasi ke pustaka yang tepat, dan setiap kali verify bcrypt sukses, langsung re-hash dengan Argon2id lalu update baris itu. Pengguna aktif bermigrasi diam-diam dalam ritme login normalnya. Tetapkan jendela penyetopan 6–12 bulan untuk akun tidak aktif, lalu paksa reset password untuk record yang masih di bcrypt. Pola yang sama bekerja untuk migrasi algoritma-ke-algoritma apa pun.

Apakah PBKDF2 masih pilihan yang baik pada 2026?

Hanya kalau kepatuhan FIPS-140 memaksa Anda, biasa di pemerintah federal, layanan kesehatan teregulasi (HIPAA), dan sistem finansial tertentu. Pakai HMAC-SHA-256 sebagai PRF dengan setidaknya 600.000 iterasi. PBKDF2 bukan memory-hard, jadi jatuh ke serangan GPU lebih cepat daripada Argon2id pada anggaran latensi yang setara. Kalau FIPS tidak berlaku, pilih Argon2id dan lewati senam kepatuhan ini.


Jawaban hashing password 2026 pendek saja: default ke Argon2id dengan parameter baseline OWASP, jatuh ke scrypt kalau Argon2 tidak tersedia, pertahankan bcrypt hanya di tempat yang menuntutnya secara historis, dan sisakan PBKDF2 untuk sistem terikat-FIPS. Pasangkan hash dengan salt per-record (setiap pustaka modern menanganinya otomatis), pepper level aplikasi yang disimpan di luar database, dan loop re-hash yang dipicu login agar Anda bisa menaikkan work factor seiring perangkat keras makin kuat.

Buat kumpulan password representatif dengan Generator Kata Sandi Acak, benchmark jalur verify Anda di CPU produksi, dan tulis parameternya ke file konstanta supaya engineer berikutnya tahu persis apa yang harus dinaikkan pada 2028. Konteks keamanan lengkap, mulai dari TLS, manajemen sesi, rate limiting, sampai MFA, ada di Dasar-Dasar Keamanan Web. Pilih hash yang sesuai untuk aplikasi Anda.

Artikel Terkait

Lihat semua artikel