Bcrypt
Buat hash bcrypt atau periksa kata sandi terhadap hash yang ada tanpa keluar dari peramban: pilih cost dan varian $2a$, $2b$ atau $2y$, lalu bongkar isi hash.
Tidak ada yang Anda ketik di sini meninggalkan peramban ini. Pekerjaannya berjalan di sebuah Web Worker pada tab ini: buka panel jaringan Anda sendiri dan lihat, tidak ada satu pun permintaan keluar selama ia menghitung.
Buat sebuah hash
Sebuah kata sandi, sebuah cost dan sebuah varian. Salt-nya diambil baru dari peramban ini pada setiap jalannya, jadi kata sandi yang sama memberi hash yang berbeda setiap kali: itu bcrypt yang bekerja, bukan cacat.
Periksa kata sandi terhadap sebuah hash
Hash yang ditempel langsung dibongkar isinya, tanpa kata sandi dan tanpa menunggu. Tambahkan kata sandinya untuk mendapat jawaban kecocokan. Sebuah hash tidak bisa dibalik, tidak di sini dan tidak di mana pun.
Apa yang sebenarnya ada di dalam hash bcrypt
Hash bcrypt adalah satu string enam puluh karakter, dan setiap bagiannya terbuka. Tidak ada yang rahasia di dalamnya kecuali kata sandi yang menghasilkannya, dan kata sandi itu justru tidak ada di sana sama sekali. Membongkar isinya tidak butuh kunci, tidak butuh kata sandi dan tidak butuh perhitungan apa pun — halaman ini melakukannya begitu Anda menempelkan satu.
- Varian, bidang yang membuka string itu: $2b$, $2a$ atau $2y$. Ia menyebut aturan siapa yang menghasilkan hash tersebut.
- Cost, ditulis dengan tepat dua angka: 04 sampai 31. Ia adalah eksponen, jadi cost 12 berarti 2^12 — 4.096 — ronde perentangan kunci, dan cost 13 adalah dua kali kerja cost 12, bukan tambahan satu per tiga belas.
- Salt, dua puluh dua karakter: enam belas bita acak, disimpan terbuka di samping jawaban yang digaraminya.
- Digest, tiga puluh satu karakter terakhir: dua puluh tiga bita keluaran. Inilah satu-satunya bagian yang bergantung pada kata sandi, dan ia bukan hash-nya — hash adalah keseluruhan string itu.
Alfabet asal karakter-karakter itu adalah milik bcrypt sendiri, dan bukan Base64 standar: alfabet itu berjalan ./A-Za-z0-9, jadi titik dan garis miring yang membukanya, sementara Base64 menaruh plus dan garis miring di ujung. Menguraikannya dengan pengurai Base64 biasa memberi bita yang salah alih-alih galat, dan itu cara klasik untuk kehilangan satu sore.
Batas tujuh puluh dua bita dihitung dalam bita, dan itu ada akibatnya
bcrypt membaca paling banyak tujuh puluh dua bita dari kata sandi dan mengabaikan semua yang datang sesudahnya. Bukan tujuh puluh dua karakter — tujuh puluh dua bita UTF-8, jadi berapa karakter itu jadinya bergantung pada berapa harga huruf bahasanya: dua puluh enam huruf Latin tanpa tanda diakritik masing-masing berharga satu bita, dan huruf lain mana pun berharga lebih dari itu. Bahasa Indonesia ditulis dengan dua puluh enam huruf itu saja, jadi pembaca Indonesia bertemu batas itu pada tujuh puluh dua karakter, persis seperti pembaca Inggris.
- ASCII berharga satu bita per karakter, jadi penutur Inggris bertemu batas itu pada tujuh puluh dua karakter dan hampir tidak pernah mencapainya.
- Ibrani, Arab, Rusia dan Yunani berharga dua bita per huruf, jadi batas itu tiba pada tiga puluh enam karakter.
- Jepang, Korea dan Tionghoa berharga tiga, jadi batas itu tiba pada dua puluh empat.
- Sebagian besar emoji berharga empat, dan banyak dari yang benar-benar diketik orang adalah beberapa titik kode yang disambung jadi satu, sehingga segenggam emoji sudah menghabiskan seluruh anggarannya.
Penghitung bita di bawah bidang kata sandi ada supaya ini menjadi sesuatu yang bisa Anda lihat mendekat, bukan sesuatu yang Anda temukan sesudahnya. Dan pemotongannya jatuh pada bita, bukan pada karakter, persis seperti yang dilakukan setiap implementasi rujukan — jadi karakter multibita yang duduk di atas batasnya kehilangan sebagian dirinya dan menyisakan sisanya. Itu perilaku yang kompatibel dan bukan cacat, dan halaman ini mengatakannya ketika hal itu terjadi.
Sekarang bagian yang menjelaskan semua sisanya: pemotongan itu tidak terlihat pada jawabannya. Penjadwalan kunci mencampurkan tepat tujuh puluh dua bita kunci ke dalam keadaannya dan tidak pernah menggulung kunci yang lebih panjang, jadi meng-hash kata sandi seratus bita dan meng-hash tujuh puluh dua bita pertamanya menghasilkan digest yang sama persis. Tidak ada yang bisa dideteksi implementasi mana pun dan tidak ada yang bisa dilaporkannya, itulah sebabnya tidak ada pustaka yang melempar galat dan sebabnya dua kata sandi panjang yang berbeda tetapi sama pada tujuh puluh dua bita pertamanya sama-sama cocok dengan satu hash tersimpan. Halaman ini pun tidak bisa menolak kata sandi panjang — kalau Anda memeriksanya terhadap hash yang dihasilkan sistem nyata dengan memotong, Anda butuh jawabannya — jadi ia memberi jawaban itu dan memberitahu apa yang terpotong.
Varian mengubah awalannya dan bukan digest-nya
Varian tampak seperti nomor versi, padahal bukan. Ketiga yang ditulis alat ini tidak berurutan, tidak ada yang menggantikan yang lain, dan memilih di antaranya adalah keputusan kompatibilitas dan bukan keputusan keamanan.
- $2b$ adalah yang dipilih OpenBSD dan yang dikeluarkan Python, Node serta Go hari ini. Ia bawaan di sini dan jawaban yang benar ketika tidak ada yang memaksa varian lain.
- $2a$ adalah yang lebih tua, dan sejumlah pemasangan Java serta Spring Security berumur panjang masih berharap melihatnya.
- $2y$ adalah yang ditulis password_hash milik PHP dan karenanya Laravel, jadi hash yang ditempel ke dunia itu biasanya menginginkannya.
Yang memisahkan ketiganya adalah cara mereka memperlakukan kunci yang lebih panjang dari 255 bita, dan bcrypt sudah berhenti membaca pada tujuh puluh dua — jadi tidak ada kata sandi yang bisa Anda ketik di sini yang mencapai perbedaan itu. Untuk apa pun yang akan pernah diberikan kepada alat ini, ketiganya menghasilkan dua puluh tiga bita yang sama dan hanya berbeda pada empat karakter di depan. Ganti variannya dan digest-nya tidak bergerak.
Ada dua lagi dan alat ini menyebut namanya alih-alih menghitungnya. $2x$ bukan perbaikan: Openwall mencetaknya justru untuk mereproduksi bug perluasan tanda, supaya hash yang dibuat kode yang rusak itu tetap bisa diperiksa, dan menerapkannya di sini berarti menaruh cacat yang sudah diketahui di dalam alat ini. $2$ adalah yang asli, dari sebelum bita nol terakhir ditambahkan ke kuncinya. Tidak ada perangkat masa kini yang mengeluarkan salah satunya; kalau Anda memegang satu, ia keluar dari sistem yang begitu tua sampai variannya menjadi hal terkecil dari yang Anda temukan.
Cost dan berapa harganya di mesin Anda sendiri
Cost adalah faktor kerja, dari 4 sampai 31, dan ia eksponen: setiap langkah melipatgandakan waktunya. Itulah seluruh maksud bcrypt. Hash kata sandi memang harus lambat, karena penyerang yang memegang tabel curian membayar harga yang sama pada setiap tebakan, dan melipatgandakan cost memotong separuh jumlah tebakan per detik yang didapat uangnya.
Berapa lama cost tertentu benar-benar berjalan adalah fakta tentang mesin yang menjalankannya, bukan angka yang bisa dituliskan lebih dulu — ponsel dan server terpaut dua orde besaran. Maka halaman ini mengukur alih-alih mengutip: ia menjalankan satu hash pendek di perangkat Anda sendiri saat halaman dimuat lalu mengekstrapolasi dari sana, dan itulah sebabnya perkiraan di samping kendali cost kosong sesaat lalu muncul. Di atas beberapa detik ia bertanya sebelum mulai, supaya angka yang salah ketik tidak terbaca sebagai halaman yang membeku.
Untuk memilih angka: 12 adalah yang dikeluarkan Laravel dan paket bcrypt Python secara bawaan dan hari ini menjadi lantai yang masuk akal untuk produksi. Cost yang lebih rendah untuk data uji, karena rangkaian uji yang menyemai lima puluh pengguna tidak seharusnya menghabiskan satu detik per pengguna. Cost di atas 15 sebaiknya diukur terhadap lalu lintas masuk Anda yang sebenarnya sebelum dirilis, karena setiap kali masuk pun membayar harganya.
# Apache: write an htpasswd line at cost 12
htpasswd -nbBC 12 alice "correct horse battery staple"
# PHP and Laravel: password_hash emits $2y$
php -r 'echo password_hash("correct horse battery staple", PASSWORD_BCRYPT);'
# Python: bcrypt emits $2b$, and gensalt takes the cost
python -c "import bcrypt; print(bcrypt.hashpw(b'correct horse battery staple', bcrypt.gensalt(12)))"Salt dan kapan hash yang dibuat di sini bukan untuk disimpan
Salt adalah enam belas bita acak yang diambil baru untuk setiap hash, dan ia disimpan terbuka di dalam string itu sendiri. Ia bukan rahasia dan tidak pernah dimaksudkan menjadi rahasia — tugasnya membuat dua kata sandi yang identik menghasilkan dua hash yang tidak berhubungan, sehingga tabel yang dicuri tidak bisa diserang satu kamus prakomputasi pada satu waktu.
Itu juga sebabnya kata sandi yang sama memberi Anda hash yang berbeda setiap kali Anda menekan tombolnya di sini. Ini bukan kesalahan dan jawaban yang lama tidak basi: salt baru adalah bcrypt yang bekerja. Setiap hash itu cocok dengan kata sandinya, karena salt-nya ikut berjalan di dalam string yang diperiksa.
Bidang salt lanjutan ada untuk satu tugas: menghasilkan kembali hash milik orang lain dengan persis, supaya dua implementasi bisa dibandingkan. Tempel satu hash utuh ke dalamnya dan cost serta variannya mengikuti dengan sendirinya, sehingga kata sandi yang benar menghasilkan kembali masukannya karakter demi karakter. Apa pun yang Anda buat dengan cara itu adalah untuk dibandingkan dan bukan untuk disimpan — salt yang dipakai dua kali adalah salt yang berhenti mengerjakan tugasnya.
Hash bcrypt tidak bisa dibalik
Orang datang ke halaman seperti ini mencari cara mendekripsi hash bcrypt. Cara itu tidak ada, dan alasannya bukan karena sulit: kata sandinya tidak ada di dalam string itu. Enam puluh karakter membawa varian, cost, enam belas bita acak dan dua puluh tiga bita keluaran, dan tidak ada susunan dari semua itu yang memuat kata sandi sepanjang apa pun. Tidak ada yang dienkripsi, jadi tidak ada yang bisa didekripsi.
Yang bisa dilakukan situs mana pun — dan yang dilakukan situs-situs yang mengiklankan dekripsi — adalah menebak. Ambil daftar kata sandi umum, hash setiap satunya terhadap salt Anda pada cost Anda, lalu lihat apakah ada yang cocok. bcrypt dirancang justru untuk membuat hal itu mahal, dan itulah gunanya cost, dan alat ini tidak menawarkannya dalam bentuk apa pun.
Versi jujur dari pertanyaan itu biasanya pertanyaan lain, dan pertanyaan itu punya jawaban: apa yang ada di dalam string ini, dan apakah kata sandi yang ini menghasilkannya? Keduanya ada di halaman ini. Tempel hash-nya untuk melihat semua yang dibawanya, dan tambahkan kata sandi untuk mendapat ya atau tidak.
Pertanyaan yang sering diajukan
- Apakah kata sandi saya dikirim ke server?
- Tidak. Semuanya terjadi di tab peramban ini — hashing-nya berjalan dalam Web Worker di mesin Anda sendiri, kata sandinya tidak pernah masuk ke URL, dan tidak ada yang ditulis ke penyimpanan peramban. Buka panel jaringan Anda, ketik kata sandi dan tekan tombolnya: tidak ada permintaan yang keluar. Itulah bedanya halaman ini dengan dua situs yang berada di atasnya untuk pertanyaan yang sama.
- Apakah hash bcrypt bisa didekripsi kembali menjadi kata sandinya?
- Tidak, dan bukan karena sulit. Kata sandinya tidak ada di dalam string itu: yang ada di sana adalah varian, cost, salt dan dua puluh tiga bita keluaran, dan tidak satu pun dari itu memuat masukannya. Apa pun yang menawarkan diri mendekripsi satu hash sedang menebak kata sandi umum terhadap salt Anda, dan bcrypt memang dirancang khusus untuk membuat hal itu lambat.
- Mengapa kata sandi yang sama memberi hash berbeda setiap kali?
- Karena salt acak yang baru diambil pada setiap jalannya, dan salt itu bagian dari string. Setiap hash itu cocok dengan kata sandi yang sama — pemeriksanya membaca salt dari hash yang Anda tempel, jadi ia tidak perlu tahu jalan yang mana yang menghasilkannya.
- Kata sandi saya terpotong pada tujuh puluh dua bita. Mengapa tidak ada galat?
- Karena tidak ada yang bisa dideteksi. bcrypt mencampurkan tepat tujuh puluh dua bita kunci ke dalam keadaannya dan tidak pernah membaca lebih jauh, jadi kata sandi panjang dan tujuh puluh dua bita pertamanya menghasilkan digest yang sama — pemotongan itu tidak meninggalkan jejak yang bisa disadari pustaka. Halaman ini memberitahu Anda bahwa hal itu terjadi, dan itulah paling banyak yang bisa dilakukan implementasi mana pun dengan jujur.
- Mengapa kata sandi saya menabrak batasnya pada tiga puluh enam karakter?
- Karena batasnya tujuh puluh dua bita dan bukan tujuh puluh dua karakter, dan huruf Ibrani, Arab, Rusia serta Yunani masing-masing berharga dua bita dalam UTF-8. Huruf Jepang, Korea dan Tionghoa berharga tiga, jadi di sana batasnya tiba pada dua puluh empat karakter, dan sebagian besar emoji berharga empat. Huruf Indonesia sendiri berharga satu bita, jadi kata sandi Indonesia biasa baru menabrak batas itu pada tujuh puluh dua. Penghitung di bawah bidangnya menunjukkan jumlah bita sambil Anda mengetik.
- Varian mana yang sebaiknya saya pilih?
- Yang diharapkan sistem tempat Anda menempelkannya: $2y$ untuk PHP dan Laravel, $2a$ untuk Spring Security yang lebih tua, $2b$ di tempat lain. Ini keputusan kompatibilitas dan bukan keputusan keamanan — pada panjang berapa pun yang bisa diberikan ke alat ini, ketiganya menghasilkan digest yang identik dan hanya berbeda pada empat karakter di depan itu.
- Cost berapa yang sebaiknya saya pakai?
- 12 adalah bawaan yang umum dan lantai yang masuk akal untuk produksi. Pakai cost rendah untuk data uji supaya rangkaian uji Anda tidak membayar perentangan kunci lima puluh kali, dan ukur apa pun di atas 15 terhadap lalu lintas masuk Anda yang sebenarnya lebih dulu, karena setiap kali masuk yang berhasil membayar harga yang sama dengan yang dibayar penyerang.
- Apakah hash yang dibuat di sini aman ditaruh di tabel pengguna sungguhan?
- Untuk menyemai basis data, menulis data uji atau menambahkan baris htpasswd, ya — salt-nya berasal dari sumber acak kriptografis peramban Anda. Tetapi ini halaman coretan dan bukan layanan kredensial: kalau Anda mengetik sendiri salt-nya, hasilnya berhenti aman untuk disimpan, dan halaman ini mengatakannya saat itu juga; kata sandi yang layak dilindungi lebih baik dicetak di tempat ia akan tinggal.
- Mengapa hash saya dimulai dengan $2y$ padahal kode yang membuatnya menyebut bcrypt?
- Karena password_hash milik PHP menulis $2y$, dan Laravel dibangun di atasnya. Ia algoritma yang sama dengan $2b$; variannya mencatat implementasi mana yang menulis string itu. Pemeriksa yang menolaknya sedang menolak variannya, bukan gagal mencocokkan kata sandinya.
- Saya menempel hash dan ia bilang salt-nya ditulis dengan ejaan lain. Apakah ia rusak?
- Tidak. Dua puluh dua karakter bisa mengodekan lebih banyak bit daripada yang dibutuhkan enam belas bita, jadi empat bit di ujungnya dibuang dan sebagian salt punya lebih dari satu ejaan yang terurai menjadi bita yang sama. Sistem nyata pernah mengeluarkannya, jadi halaman ini membaca hash semacam itu alih-alih menolaknya, dan memberitahu Anda ejaan kanoniknya.
Alat terkait
- Pendekode / pemverifikasi JWT
Dekode dan verifikasi JSON Web Token — tanda tangan dan klaim.
- Pembuat hash
MD5, SHA-1, SHA-256, SHA-384, dan SHA-512 sekaligus.
- Pendekode sertifikat & PEM
Baca sertifikat X.509 atau CSR tanpa OpenSSL.
- Pembuat HMAC
Tandatangani pesan dengan kunci, atau verifikasi tanda tangan webhook.