Pertanyaan dan Ruang Lingkup
Sebuah produk SaaS dengan 10.000.000 akun sedang membangun ulang autentikasi password. Sekitar 7.000.000 record database menggunakan bcrypt dengan cost 10, 2.000.000 menggunakan PBKDF2-HMAC-SHA256 dengan 210000 iterasi, dan 1.000.000 menggunakan SHA-256 tanpa salt per-record. Format yang ada tidak konsisten, dan beberapa baris tidak secara langsung mengidentifikasi algoritma dan parameternya. Pada jam sibuk, layanan autentikasi harus menangani 1500 verifikasi password per detik. Setiap instans mengizinkan paling banyak 24 operasi hash komputasi tinggi (expensive hash) secara konkuren.
Rancang migrasi lengkap ke Argon2id. Jelaskan model ancaman, pemilihan parameter dan pengukuran kapasitas, format penyimpanan yang dapat berevolusi, verifikasi multi-algoritma, upgrade saat login, perubahan password konkuren, akun yang sudah lama tidak aktif, pengelolaan pepper, respons terhadap paparan database atau kunci, pertahanan terhadap enumerasi akun dan kehabisan sumber daya, serta kriteria rollout dan penyelesaian. Jumlah akun, kombinasi algoritma, parameter warisan, dan batas konkurensi adalah batasan wawancara, bukan ambang batas keamanan universal.
Ini adalah pertanyaan rekayasa keamanan backend dan autentikasi. Verifier kredensial dan state machine migrasi adalah fokus utamanya. Desain lengkap untuk pendaftaran, pemulihan password, MFA, atau sesi berada di luar cakupan kecuali jika alur tersebut memengaruhi migrasi kredensial atau respons kebocoran.
Apa yang Dievaluasi oleh Pewawancara
Pertama, apakah kandidat dapat membedakan antara online guessing dan offline cracking? Rate limit membatasi endpoint login, tetapi tidak membatasi penyerang yang telah memperoleh database hash. Password adalah rahasia manusia dengan entropi rendah. Digest cepat seperti SHA-256 memungkinkan penyerang mengenumerasi kandidat dengan cepat; hash khusus password meningkatkan biaya setiap tebakan melalui salt per-record, komputasi yang dapat disesuaikan, dan biaya memori.
Kedua, apakah kandidat memahami bahwa parameter harus diukur terhadap kapasitas nyata? “Gunakan Argon2id” memilih algoritma tetapi belum menyelesaikan desain. Jawaban yang lengkap memilih memori m, iterasi t, paralelisme p, panjang salt, dan panjang output, lalu menghitung bagaimana verifikasi konkuren memengaruhi memori, CPU, latensi, dan paparan denial-of-service. Parameter yang lebih tinggi tidak otomatis lebih aman. Jika traffic serangan menghabiskan memori layanan, ketersediaan autentikasi akan gagal terlebih dahulu.
Ketiga, dapatkah kandidat memigrasikan data yang tidak dapat diubah kembali (irreversible)? Sistem tidak mengetahui password plaintext setiap pengguna, sehingga tidak dapat mendekripsi hasil bcrypt secara offline dan mengonversinya ke Argon2id. Jalur yang biasa dilakukan adalah memverifikasi record warisan dengan sukses dan menggunakan plaintext yang diberikan dalam permintaan tersebut untuk membuat record saat ini. Akun yang sudah lama tidak aktif memerlukan verifier warisan yang terkontrol, wrapping sementara, atau reset, tergantung pada risiko algoritma warisan dan riwayat paparannya.
Terakhir, jawaban yang kuat mampu menangani race condition dan batasan operasional. Upgrade saat login tidak boleh menimpa reset password yang terjadi secara konkuren. Pepper tidak boleh berada di samping database hash. Versi algoritma, parameter, dan status migrasi memerlukan observabilitas, tetapi log tidak boleh berisi password, hash lengkap, atau pepper. “Kode baru telah di-deploy” bukanlah kriteria penyelesaian.
Klarifikasi Sebelum Menjawab
- Apakah setiap format yang ada dapat diidentifikasi secara andal? Tentukan algoritma, parameter, pengkodean karakter, lokasi salt, dan versi pustaka historis. Jangan menebak format dan mencoba beberapa verifier untuk baris yang tidak dapat diidentifikasi.
- Bagaimana bcrypt warisan menangani input di atas 72 byte? Reproduksi semantik pengkodean dan pemotongan (truncation) implementasi historis sehingga migrasi tidak secara diam-diam mengubah kredensial efektif pengguna.
- Apakah database, backup, atau kumpulan hash warisan pernah terekspos? Melakukan wrapping pada database saat ini tidak dapat menarik kembali digest cepat tanpa salt yang sudah terekspos. Tindakan reset paksa dan sesi mungkin diperlukan.
- Berapa anggaran sumber daya nyata dari instans autentikasi? Dapatkan baseline memori, kuota CPU, batas konkurensi hash, kecepatan autoscaling, target latensi p95 dan p99, serta tingkat kegagalan yang dapat diterima.
- Apakah batasan kepatuhan FIPS atau lainnya berlaku? Batasan ini dapat membatasi algoritma dan implementasi, tetapi label kepatuhan tidak menggantikan pengukuran parameter atau desain migrasi.
- Apakah pepper sudah ada? Konfirmasikan penyimpanannya, dependensi panggilan, versi, kemampuan rotasi, batasan audit, dan perilaku saat layanan kunci tidak tersedia.
- Apa batasan transaksi untuk perubahan password dan penerbitan sesi? Urutan migrasi, reset konkuren, dan penerbitan sesi harus eksplisit, jika tidak, password lama dapat memperoleh sesi baru setelah reset.
- Bagaimana nilai bisnis dan risiko membagi akun yang sudah lama tidak aktif? Akun dengan hak istimewa, aktif baru-baru ini, dan tidak aktif selama bertahun-tahun dapat memiliki tenggat waktu dan persyaratan verifikasi ulang yang berbeda.
Kerangka Jawaban 30 Detik
“Saya akan mendefinisikan tujuan utama sebagai resistensi terhadap tebakan offline setelah kebocoran database hash dan melindungi kapasitas autentikasi online secara terpisah. Password baru menggunakan Argon2id dengan salt acak independen. Record membawa algoritma, versi, m/t/p, salt, dan output. Jika kita menggunakan pepper, pepper tersebut berada di sistem kunci di luar database. Saya akan menggunakan minimum OWASP saat ini sebagai titik awal kandidat, lalu melakukan uji beban pada instans yang setara dengan produksi untuk memori konkuren, CPU, dan latensi p99 daripada menyalin satu nilai mentah-mentah.
Saat login, versi record yang dideklarasikan memilih tepat satu verifier warisan. Setelah verifikasi berhasil, saya menghitung record Argon2id saat ini dan melakukan compare-and-swap terhadap hash lama. Jika perubahan konkuren membuat operasi itu gagal, saya memuat ulang dan memverifikasi record terbaru alih-alih menimpa reset password. Password baru dan yang direset segera menggunakan format saat ini. Akun SHA-256 tanpa salt mendapatkan tenggat waktu migrasi yang lebih pendek; ketika wrapping yang aman tidak tersedia atau telah terjadi paparan, akun tersebut harus direset.
Endpoint menggunakan error yang seragam, dummy hash saat ini, rate limit akun dan sumber yang independen, serta konkurensi hash yang dibatasi untuk menahan enumerasi dan kehabisan memori. Setelah rilis, saya melacak migrasi berdasarkan versi algoritma, latensi, memori, kegagalan, konflik CAS, dan penyelesaian reset. Saya menyatakan selesai hanya setelah format warisan berisiko tinggi mencapai nol, pengujian race condition dan beban puncak lolos, serta latihan rotasi kunci berhasil.”
Penjelasan Langkah demi Langkah
Langkah 1: Pisahkan attack surface online dan offline
Login normal adalah jalur online. Throughput endpoint, kontrol per-akun, kontrol sumber, sistem risiko, dan pemantauan membatasi penyerang. Menebak setelah kebocoran database adalah jalur offline: penyerang menjalankan verifier pada GPU, ASIC, atau instans cloud mereka sendiri tanpa batasan rate limit aplikasi. Penyimpanan password terutama meningkatkan biaya setiap upaya kandidat pada jalur kedua tersebut.
SHA-256 tanpa salt memiliki dua masalah. Algoritma ini cepat, dan password yang sama menghasilkan digest yang sama, sehingga penyerang dapat menggunakan kembali pekerjaan yang telah dihitung sebelumnya (precomputed work) dan mengidentifikasi kelompok yang menggunakan password yang sama. Salt acak independen untuk setiap record membuat password yang sama menghasilkan output yang berbeda dan memaksa komputasi dilakukan per-record. Salt dapat disimpan bersama hash dan tidak perlu dirahasiakan. Salt tidak mengubah SHA-256 yang cepat menjadi hash password yang sesuai; resistensi yang bermakna berasal dari algoritma khusus, dapat disesuaikan, dan lebih disukai memory-hard.
Pepper adalah kontrol terpisah. Pepper adalah rahasia sisi server yang dibagikan ke seluruh record atau dikelola berdasarkan versi, dan harus dipisahkan dari database password, biasanya dalam layanan manajemen kunci (KMS), HSM, atau protected execution environment. Pepper dapat mengurangi dampak kebocoran yang hanya mengenai database, tetapi tidak menggantikan salt per-record maupun hashing lambat. Jika database dan pepper keduanya terekspos, pemrosesan batch database tidak dapat merekey record yang terpengaruh secara aman karena layanan tidak memiliki password plaintext pengguna.
Langkah 2: Pilih parameter dan hitung kapasitas autentikasi
Untuk record baru, gunakan implementasi Argon2id yang terawat. Salah satu kandidat minimum OWASP saat ini adalah m=19456 KiB, t=2, dan p=1. RFC 9106 memberikan rekomendasi umum dengan memori lebih tinggi, termasuk 64 MiB, tiga pass, dan empat lane untuk opsi dengan batasan memori. Dokumen-dokumen tersebut menargetkan batasan operasional yang berbeda, sehingga tidak ada satu tuple yang menjadi konstanta universal untuk layanan web.
Proses seleksi yang lebih dapat dipertanggungjawabkan adalah:
- Mulai dari kandidat yang telah ditinjau pada CPU, batas memori, dan runtime yang sama dengan yang digunakan di produksi.
- Ukur median, p95, p99 verifikasi tunggal, memori residen aktual, dan waktu CPU.
- Lakukan uji beban dengan campuran traffic puncak normal, lonjakan login, password salah, dan akun yang tidak ada.
- Batasi konkurensi dan amati waktu antrean, OOM container, throttling CPU, dan batas waktu upstream (timeout).
- Pilih biaya penyerang tertinggi yang berkelanjutan dalam anggaran ketersediaan, dan catat perangkat keras, versi pustaka, serta tanggal pengukuran.
Pada 19 MiB, memori kerja hash teoretis untuk 24 operasi simultan sudah mencapai 456 MiB, sebelum baseline proses, overhead pustaka, objek request, dan margin keamanan. Jika satu verifikasi membutuhkan 250 milidetik pada instans target, perkiraan maksimum kasarnya adalah sekitar 96 penyelesaian per detik. Melayani 1500 per detik membutuhkan setidaknya sekitar 16 instans setara yang tersedia terus-menerus, dengan ruang tambahan (headroom) untuk tail latency, kegagalan, dan jeda autoscaling. Perhitungan ini mengungkap perkiraan besaran kapasitas; uji beban menentukan nilai akhirnya.
Gunakan salt acak 128-bit independen baru per record dan, misalnya, output 256-bit. Biarkan pustaka yang matang menghasilkan dan mengurai pengkodean standar daripada merakit field kriptografi secara manual. Input password memerlukan pengkodean byte yang stabil dan terdokumentasi sebelum di-hash. Jika Unicode diterima, tentukan normalisasi dan terapkan secara konsisten selama pendaftaran, login, dan migrasi.
Langkah 3: Buat record kredensial self-describing dan dapat berevolusi
Record harus membawa informasi non-rahasia yang diperlukan untuk verifikasi. Pengkodean Argon2 dapat terlihat seperti ini:
$argon2id$v=19$m=19456,t=2,p=1$SALT_BASE64$TAG_BASE64Format warisan juga memerlukan pemetaan deterministik seperti {bcrypt}, {pbkdf2-sha256}, dan {sha256-legacy}. Label adalah protokol parsing, bukan jaminan keamanan. Tolak label yang tidak dikenal, field yang hilang, nilai Base64 yang tidak valid, atau parameter di luar kebijakan, lalu kirim akun ke antrean pemulihan terkontrol. Jangan mencoba algoritma secara berurutan hingga salah satunya cocok secara kebetulan.
Parsing parameter memerlukan batas atas. Jika penyerang dapat merusak record, mereka dapat menetapkan nilai memori atau iterasi yang ekstrem dan menghabiskan sumber daya layanan melalui permintaan login. Verifier hanya menerima algoritma yang diterapkan dan rentang parameter yang diizinkan. Record di luar rentang menghasilkan peristiwa keamanan tanpa data sensitif dan memerlukan pemulihan akun.
Tabel kredensial membutuhkan setidaknya pengkodean saat ini, waktu pembaruan kredensial, dan status disposisi keamanan. Laporan migrasi dapat diagregasi dari awalan pengkodean atau scheme_id dengan kardinalitas rendah. Jangan pernah menempatkan hash lengkap, salt, kandidat password, rahasia pepper, atau perantara verifikasi di log, label metrik, atau sistem analitik.
Langkah 4: Upgrade secara aman setelah login berhasil
Fungsi migrasi mengurai record dan memanggil satu verifier yang cocok. Hanya setelah kredensial warisan berhasil, layanan memiliki plaintext yang benar dari permintaan ini dan dapat menghitung record Argon2id saat ini. Pertahankan pekerjaan komputasi berat di luar transaksi database yang singkat dan kondisikan penulisan pada record lama:
record = loadCredential(userId)
ok = verifyByDeclaredScheme(record.hash, submittedPassword)
if !ok: rejectWithGenericError()
if needsRehash(record.hash):
upgraded = hashWithCurrentPolicy(submittedPassword)
changed = compareAndSwap(userId, expected=record.hash, replacement=upgraded)
if !changed:
latest = loadCredential(userId)
if !verifyByDeclaredScheme(latest.hash, submittedPassword):
rejectAndAskForFreshLogin()
issueSessionAfterCredentialStateIsConfirmed()Compare-and-swap mencegah upgrade login menimpa reset password yang terjadi secara konkuren. Pembaruan bersyarat yang gagal dapat berarti login lain telah menyelesaikan migrasi yang sama atau pengguna baru saja memilih password yang berbeda. Muat ulang dan verifikasi input saat ini terhadap record terbaru; jangan menerbitkan sesi hanya karena record lama pernah cocok sekali. Pendaftaran, perubahan password sukarela, dan pemulihan password menulis format saat ini secara langsung dan tidak pernah membuat record warisan lainnya.
Kebijakan risiko menentukan apakah login dapat dilanjutkan ketika penulisan upgrade gagal. Error database yang dapat dicoba lagi (retryable) dapat meninggalkan record warisan yang dapat diterima untuk sementara dan memancarkan peristiwa kegagalan migrasi. Format berisiko tinggi dapat mewajibkan upgrade yang berhasil sebelum penerbitan sesi. Dalam kedua kasus tersebut, batasi percobaan ulang agar satu login tidak mengeksekusi beberapa hash komputasi berat tanpa henti.
Langkah 5: Perlakukan format warisan yang dapat diterima dan berisiko tinggi secara berbeda
Bcrypt dan PBKDF2 yang cukup kuat dapat mempertahankan verifikasi read-only selama periode migrasi terkontrol dan melakukan upgrade setelah login berhasil. Minimalkan paparan verifier warisan: mereka hanya melayani record yang ada dan tidak dapat membuat kredensial baru. Lacak sisa akun, aktivitas, dan kecepatan migrasi untuk setiap format. Sebelum menghapus verifier pada tenggat waktunya, selesaikan setiap akun yang masih bergantung padanya.
SHA-256 tanpa salt memiliki risiko lebih tinggi. Jika tidak ada paparan yang terjadi dan reset universal langsung tidak memungkinkan, layanan dapat memperlakukan digest yang ada sebagai input ke algoritma luar lambat yang baru di-salt sebagai pengerasan database sementara. Verifikasi pertama-tama mereproduksi operasi historis SHA-256 dan kemudian memverifikasi lapisan luar. Setelah login berhasil, layanan tetap menggantinya dengan record Argon2id standar yang dihitung dari password yang dikirimkan.
Wrapper tersebut tidak setara dengan Argon2id(password). Wrapper tidak dapat menarik kembali digest dalam yang telah bocor, dan tidak memperbaiki masalah pengkodean historis, pemotongan, atau password lemah. Jika hash warisan atau backup terekspos, akun memiliki hak istimewa, atau semantik format tidak pasti, wajibkan reset, cabut sesi yang relevan, dan pulihkan melalui alur verifikasi independen. Akun biasa yang tidak aktif selama bertahun-tahun juga dapat dibekukan login password-nya pada tenggat waktu dan menggunakan pemulihan saat kembali alih-alih mempertahankan verifier terlemah selamanya.
Langkah 6: Rancang versi pepper dan respons kebocoran
Jika pepper digunakan, langkah prapemrosesan ber-kunci (keyed) yang telah ditinjau dapat mendahului hash password, atau HMAC dapat melindungi output-nya. Konstruksi yang matang dan tinjauan keamanan harus memutuskan komposisi pastinya. Database hanya menyimpan pengidentifikasi versi pepper non-rahasia; kunci sebenarnya tetap berada di luar database dan backup-nya. Layanan autentikasi menggunakan akses least-privilege, dengan masa pakai cache eksplisit dan perilaku saat terjadi kegagalan layanan kunci.
Rotasi rutin dapat menyimpan kunci saat ini dan sebelumnya untuk sementara waktu. Setelah verifikasi berhasil dengan versi lama, hitung ulang record lengkap dari plaintext yang dikirimkan dan pepper saat ini. Kunci lama tidak boleh bertahan tanpa batas waktu. Rencana rotasi menghitung akun pada versi sebelumnya dan menetapkan jalur reset atau pembekuan bagi mereka yang tidak bermigrasi.
Susun respons kebocoran data berlapis sesuai dengan bukti:
- Hanya database: amankan bukti, tutup titik masuk, tingkatkan pemantauan, dan putuskan reset setelah mengevaluasi algoritma dan parameter. Pepper rahasia memberi pertahanan tambahan tetapi tidak membuat password lemah menjadi aman.
- Hanya pepper: rotasi kunci, selidiki log akses, dan tentukan apakah penyerang mungkin juga telah memperoleh database hash.
- Database dan pepper yang cocok: tangani ini sebagai paparan hash password, paksa akun yang terpengaruh untuk mereset, cabut atau perpendek sesi yang relevan, dan peringatkan pengguna untuk mengubah password yang digunakan kembali.
Rotasi yang berhasil tidak menghapus paparan historis. Record insiden harus mencakup versi yang terpengaruh, cakupan akun, backup, sesi, notifikasi, persentase penyelesaian, dan pengecualian residual.
Langkah 7: Tahan enumerasi dan kehabisan sumber daya secara bersamaan
Akun yang tidak ada, password salah, akun dinonaktifkan, dan kegagalan migrasi mengembalikan semantik error eksternal yang sama, termasuk status dan bentuk respons yang konsisten. Untuk akun yang tidak ada, jalankan satu dummy hash terkontrol di bawah kebijakan saat ini untuk mengurangi kesenjangan yang jelas antara respons instan dan verifikasi komputasi berat. Campuran algoritma warisan masih dapat memiliki perbedaan waktu (timing). Migrasi, pengerasan runtime, dan pengukuran statistik harus mengurangi perbedaan yang dapat dieksploitasi; jangan berjanji bahwa setiap respons jaringan memiliki waktu yang sepenuhnya konstan (constant-time).
Hashing komputasi berat itu sendiri menciptakan celah denial-of-service. Sebelum antrean hash, lakukan pembatasan sumber (source throttling) kasar dan pemeriksaan validitas permintaan yang tidak mengungkapkan apakah suatu akun ada. Untuk pekerjaan yang diterima, terapkan kuota akun dan sumber yang independen, antrean berbatas global, dan 24 izin konkurensi per instans. Satu bucket tunggal yang menggunakan kunci pasangan IP-dan-username memungkinkan penyerang mengubah satu dimensi berulang kali dan menghindari batas agregat.
Ketika antrean penuh, gagal dengan cepat (fail fast) menggunakan respons sementara yang seragam alih-alih menumpuk pekerjaan tanpa batas. Sinyal penskalaan harus mencakup waktu antrean, hash aktif, headroom memori, dan throttling CPU, bukan hanya jumlah permintaan. Log berisi pengidentifikasi akun internal yang tidak dapat diubah kembali (irreversible), versi skema kardinalitas rendah, kelas hasil, dimensi pembatasan, dan bucket latensi. Log tidak boleh berisi password yang dikirimkan, record kredensial lengkap, atau materi kunci.
Langkah 8: Rollout secara bertahap dan terima dengan bukti
Mulailah dengan inventarisasi read-only. Konfirmasikan bahwa setiap record warisan dapat diurai, dan verifikasi implementasi historis dengan vektor uji yang diketahui di lingkungan terisolasi. Kemudian deploy kode yang dapat membaca setiap format warisan yang didukung tetapi hanya menulis format saat ini. Buat pendaftaran baru dan perubahan password menulis Argon2id terlebih dahulu. Aktifkan upgrade saat login untuk kelompok kecil, amati konflik CAS, kegagalan verifikasi, dan kurva sumber daya, lalu perluas secara bertahap.
Sebelum rilis penuh, verifikasi setidaknya:
- Perilaku password-benar, password-salah, panjang-batas, Unicode, dan record rusak untuk setiap format historis.
- Race condition antara upgrade login dan reset password konkuren, membuktikan bahwa login lama tidak dapat menimpa password baru atau menerbitkan sesi yang tidak valid.
- Latihan rotasi dan kegagalan untuk versi pepper saat ini, sebelumnya, dan yang tidak dikenal.
- Latensi, memori, CPU, antrean, dan penskalaan pada target 1500 verifikasi per detik dengan campuran traffic serangan.
- Distribusi pesan, status, ukuran, dan latensi untuk akun yang tidak ada dan setiap kelas kegagalan.
- Pemindaian untuk field sensitif di database, backup, log, metrik, dan pelacakan error.
Dasbor migrasi mengelompokkan berdasarkan algoritma dan tingkat risiko: jumlah total, jumlah aktif baru-baru ini, upgrade harian yang berhasil, alasan kegagalan, penyelesaian reset wajib, dan tenggat waktu. Penyelesaian teknis berarti setiap penulisan baru menggunakan kebijakan saat ini; SHA-256 tanpa salt dan versi yang terekspos berada di angka nol; verifier warisan yang tidak diperlukan telah dihapus; setiap format warisan yang masih dapat diterima memiliki pengecualian yang terdokumentasi; uji beban puncak dan race condition lolos; latihan rotasi pepper dan pemulihan memiliki bukti; dan SLO autentikasi tetap sesuai kesepakatan.
Contoh Jawaban Berkualitas Tinggi
“Pertama-tama saya akan memisahkan dua attack surface. Kontrol endpoint membatasi serangan online; mereka tidak membatasi serangan offline setelah kebocoran database hash. Oleh karena itu, password memerlukan hash memory-hard khusus dengan salt acak independen dan biaya yang dapat disesuaikan. Record baru menggunakan implementasi Argon2id yang matang dan mendeskripsikan sendiri versi algoritma, m/t/p, salt, dan output. Jika diaktifkan, pepper diberi versi dalam sistem kunci di luar database dan backup-nya.
Saya tidak akan menyalin parameter langsung dari blog. Saya akan menggunakan 19 MiB, t=2, p=1 OWASP saat ini sebagai salah satu kandidat minimum dan mengukur p50, p95, p99 tunggal dan konkuren, CPU, serta memori nyata pada instans yang setara dengan produksi, lalu melakukan uji beban pada beban puncak normal dan traffic serangan. Sembilan belas MiB dikalikan 24 operasi konkuren sudah mencapai 456 MiB memori kerja, sehingga layanan membutuhkan antrean berbatas, izin konkurensi, dan headroom instans yang memadai. Pustaka yang matang menghasilkan salt acak per record, dan record menyimpan parameter untuk upgrade di masa mendatang.
Saat login, format yang dideklarasikan memilih tepat satu verifier. Setelah password warisan berhasil, saya menghitung record Argon2id saat ini di luar transaksi database dan memperbarui hanya jika hash lama masih cocok. Jika CAS gagal, saya memuat ulang kredensial terbaru dan memverifikasi input ini lagi. Login konkuren kemudian dapat menyatu (converge), sementara login lama tidak dapat menimpa reset password yang terjadi bersamaan. Saya menerbitkan sesi hanya setelah mengonfirmasi status kredensial saat ini. Pendaftaran, perubahan sukarela, dan pemulihan hanya menulis format baru sejak hari pertama.
Bcrypt dan PBKDF2 yang masih dapat diterima mendapatkan periode migrasi yang ditentukan dengan dukungan verifikasi saja. SHA-256 tanpa salt masuk ke antrean berisiko lebih tinggi. Jika belum pernah bocor, wrapper luar lambat yang baru di-salt dapat memberikan penahanan jangka pendek, tetapi tidak menggantikan penghitungan ulang hash password sebenarnya. Akun yang terekspos, memiliki hak istimewa, dan lama tidak aktif direset atau dibekukan pada tenggat waktu. Verifier warisan tidak bertahan selamanya.
Endpoint menggunakan error seragam dan dummy hash saat ini untuk mengurangi perbedaan enumerasi akun, ditambah batas sumber dan akun yang independen, antrean global, dan batas konkurensi memori untuk menahan denial of service amplifikasi hash. Bukti penyelesaian mencakup distribusi versi, nol record warisan berisiko tinggi, kegagalan migrasi dan konflik CAS, uji beban puncak dan race condition, pemindaian log sensitif, rotasi pepper, dan latihan kebocoran. Saya akan menyatakan selesai hanya setelah pemeriksaan tersebut lolos dan verifier warisan yang direncanakan telah dipensiunkan.”
Kesalahan Umum dan Perbaikan
- Menyimpan password sebagai SHA-256 dengan salt → salt mencegah penggunaan ulang pekerjaan lintas akun tetapi tidak mencegah tebakan cepat pada satu record → gunakan hash password khusus, dapat disesuaikan, dan memory-hard.
- Mengklaim hash tidak dapat di-crack → tebakan kandidat masih menemukan password yang lemah → nyatakan tujuannya sebagai peningkatan biaya offline, bersamaan dengan pemblokiran password yang telah disusupi dan MFA.
- Memperlakukan parameter OWASP sebagai optimal secara permanen → perangkat keras, pustaka, sumber daya instans, dan traffic berubah → catat lingkungan benchmark, ukur ulang, dan upgrade berdasarkan versi.
- Mengonversi setiap record bcrypt ke Argon2id secara offline → hash baru standar tidak dapat diturunkan tanpa plaintext → hash ulang setelah verifikasi berhasil dan wrap, reset, atau bekukan sisanya berdasarkan risiko.
- Memperbarui migrasi tanpa kondisi nilai lama → login dapat menimpa reset password yang telah selesai → gunakan compare-and-swap, lalu muat ulang dan verifikasi ulang setelah kegagalan.
- Menahan lock baris pengguna selama hashing → pekerjaan komputasi berat memperpanjang durasi lock dan okupansi pool koneksi → hitung di luar transaksi dan lakukan penulisan bersyarat yang singkat.
- Menyimpan pepper di tabel konfigurasi database yang sama → satu kebocoran database mendapatkan kedua lapisan → simpan kunci dalam sistem yang dilindungi secara independen dan audit berdasarkan versi.
- Merotasi pepper dengan mengubah satu environment variable → record lama tidak dapat diverifikasi secara langsung dengan kunci baru → simpan dua versi secara singkat, lalu hitung ulang setelah login berhasil atau wajibkan reset.
- Mengembalikan respons segera untuk akun yang tidak ada → waktu respons mengungkapkan keberadaan akun → gunakan error seragam, dummy hash, dan uji distribusi latensi empiris.
- Menjalankan Argon2id tanpa batas konkurensi → penyerang dapat mengamplifikasi konsumsi memori dan CPU → terapkan batas dua dimensi, lalu antrean berbatas dan izin konkurensi.
- Mengabaikan batas input bcrypt → perilaku 72-byte historis dapat mengubah kredensial efektif selama migrasi → reproduksi verifier warisan dan wajibkan perubahan password eksplisit untuk akun yang terpengaruh.
- Hanya memeriksa bahwa pendaftaran baru menggunakan Argon2id → record warisan yang aktif atau berisiko tinggi tetap terekspos → lacak inventaris berdasarkan algoritma, risiko, dan aktivitas, dengan kriteria nol dan pengecualian.
Pertanyaan Lanjutan
Pertanyaan lanjutan 1: Mengapa salt dapat disimpan dalam plaintext sedangkan pepper harus tetap rahasia?
Salt membuat input setiap record menjadi unik, mencegah password yang sama berbagi output dan pekerjaan yang dihitung sebelumnya. Penyerang yang mengetahui salt tetap harus menebak setiap record secara terpisah. Pepper memberi nilai tambah karena penyerang yang hanya memiliki akses ke database tidak memiliki rahasia sisi server, sehingga pepper harus tetap dipisahkan dari database hash. Kontrol tersebut memiliki fungsi berbeda; pepper tidak menggantikan salt independen per-record.
Pertanyaan lanjutan 2: Dapatkah database secara langsung meningkatkan jumlah iterasi Argon2id?
Tidak ada hash password standar dengan parameter lebih tinggi yang dapat diturunkan dari output lama tanpa plaintext pengguna. Wrapper luar dapat mengeraskan output lama untuk sementara waktu, tetapi hal itu mengubah semantik record dan tidak dapat menghapus risiko output yang sebelumnya telah terekspos. Upgrade standar tetap menghitung ulang setelah verifikasi password berhasil atau mewajibkan reset.
Pertanyaan lanjutan 3: Mengapa tidak mengizinkan login segera setelah CAS gagal?
Kegagalan dapat berarti permintaan lain telah menyelesaikan migrasi yang sama, atau dapat berarti pengguna secara bersamaan menyetel password yang berbeda melalui pemulihan. Password lama tidak valid dalam kasus kedua. Memuat ulang record terbaru dan memverifikasi input yang dikirimkan membedakan kedua kasus tersebut; verifikasi yang gagal tidak boleh menerima sesi.
Pertanyaan lanjutan 4: Apakah parameter Argon2id yang lebih tinggi selalu lebih baik?
Biaya memori atau waktu yang lebih tinggi meningkatkan biaya serangan offline dan penggunaan sumber daya login yang sah. Parameter yang berlebihan menciptakan tail latency, penumpukan antrean, OOM instans, dan penguat denial-of-service untuk permintaan berbiaya murah. Kebijakan yang tepat adalah biaya tertinggi yang berkelanjutan yang diukur di bawah batasan perangkat keras nyata, konkurensi, penskalaan, dan SLO, serta harus dinilai ulang saat perangkat keras dan ancaman berubah.
Pertanyaan lanjutan 5: Apa yang harus terjadi pada akun yang telah tidak aktif selama lima tahun dan masih menggunakan bcrypt?
Klasifikasikan berdasarkan hak istimewa, riwayat paparan, dan parameter warisan. Akun biasa berisiko rendah dapat dibekukan login password-nya setelah tenggat waktu migrasi dan menyetel password baru melalui pemulihan terkontrol saat pengguna kembali. Akun dengan hak istimewa atau yang terpengaruh harus direset lebih awal dan sesinya dicabut. Mempertahankan verifier warisan selamanya membuat migrasi tidak akan pernah selesai.