Error bcrypt 72 Byte: Kenapa Kata Sandi Pendek Juga Gagal
Dua masalah yang berbeda menghasilkan pesan yang sama, dan hanya satu di antaranya yang benar-benar berkaitan dengan kata sandi Anda.
Kalau kata sandi Anda memang melewati batas 72 byte bcrypt, bcrypt hanya membaca 72 byte pertama dan membuang sisanya. Kami melakukan hashing terhadap dua kata sandi 82 byte yang 72 byte pertamanya identik, dengan salt yang tetap. Keduanya menghasilkan $2a$10$abcdefghijklmnopqrstuu.hioaszd4nGKdJlcuRzR1xqPIcN/X.S, dan bcrypt.compareSync(p2, hash(p1)) mengembalikan true. Kata sandi kedua bisa dipakai untuk masuk ke akun milik kata sandi pertama.
Kalau kata sandi Anda jelas-jelas pendek tetapi tetap muncul pesan ini:
password cannot be longer than 72 bytes, truncate manually if necessary (e.g. my_password[:72])
(artinya: kata sandi tidak boleh lebih panjang dari 72 byte), maka pesan itu keliru soal penyebabnya. Pada passlib 1.7.4 dengan bcrypt 5.0.0, kata sandi 14 byte pun memicunya.
Biang keroknya adalah sebuah probe swauji (self-test) tetap sepanjang 255 byte di dalam passlib. Probe itu jalan sekali saat backend diinisialisasi, jauh sebelum kata sandi Anda sampai ke pemanggilan hashing. bcrypt 5.0.0 menolak probe tersebut, eksepsinya lolos ke luar, dan Anda membaca keluhan tentang kata sandi yang tidak pernah diketik siapa pun.
Dan monkey patch __about__ yang mendominasi hasil pencarian untuk error ini tidak memperbaikinya. Kami menjalankannya ulang di proses yang bersih, dengan patch dipasang sebelum import passlib, dan ValueError tetap muncul tanpa perubahan.
Triase 30 detik: Anda yang mana
| Kata sandi Anda | Kapan error muncul | Akar masalah | Lanjut ke |
|---|---|---|---|
| Lebih panjang dari 72 byte | Saat Anda memanggil hash | Memang terlalu panjang. bcrypt 5.0 melempar error, bcrypt 4.x memotong diam-diam | Bagian 2 dan 3 |
| Di bawah 72 byte, memakai passlib | Pada pemanggilan pertama dalam proses | Probe 255 byte milik passlib. Tidak ada hubungannya dengan kata sandi Anda | Bagian 4 |
| Mengandung huruf Tionghoa, Jepang, atau emoji | Terlihat pendek, padahal tidak | Karakter bukan byte | Bagian 3 |
| Mulai gagal setelah upgrade dependensi | Setelah deploy | Perubahan yang memutus kompatibilitas di bcrypt 5.0 | Bagian 4 dan 5 |
Kalau Anda ada di baris kedua, langsung lompat ke depan. Dua bagian berikutnya tidak akan membantu Anda, dan perbaikannya berbeda.
Apa yang dilakukan batas 72 byte bcrypt terhadap kata sandi Anda
Kenapa bcrypt berhenti di 72
bcrypt dibangun di atas Blowfish, dan kata sandi Anda dimasukkan sebagai kunci Blowfish. Blowfish memperluas kuncinya menjadi P-array berisi 18 subkunci, masing-masing selebar 32 bit. Itu berarti 18 × 4 = 72 byte bahan kunci, dan loop ekspansinya berputar kembali ke awal kunci begitu ke-18 slot sudah terisi.
Jadi plafon itu bersifat struktural, bukan akibat implementasi yang malas atau buffer yang lupa dinaikkan. Setiap implementasi bcrypt yang patuh spesifikasi punya batas yang sama, di platform mana pun. Itu sebabnya angka 72 muncul di Python, Node, Go, Java, maupun PHP.
Dua kata sandi berbeda, satu hash
bcrypt password truncation adalah properti keamanan, bukan sekadar ketidaknyamanan soal panjang.
Dengan bcryptjs 3.0.3 dan salt tetap $2a$10$abcdefghijklmnopqrstuv, kami melakukan hashing terhadap dua kata sandi yang masing-masing berukuran 82 byte:
| Kata sandi | Nilai | Byte |
|---|---|---|
| p1 | "A"×72 + "XXXXXXXXXX" | 82 |
| p2 | "A"×72 + "ZZZZZZZZZZ" | 82 |
Keduanya menghasilkan digest yang sama:
$2a$10$abcdefghijklmnopqrstuu.hioaszd4nGKdJlcuRzR1xqPIcN/X.S
Dua kata sandi berbeda, satu hash: true. Konsekuensinya:
bcrypt.compareSync(p2, hash(p1)) // true
Penyerang yang tahu 72 byte pertama dari sebuah frasa sandi panjang bisa menempelkan apa saja di belakangnya dan tetap lolos autentikasi. Setiap byte di luar batas itu menyumbang tepat nol terhadap kekuatan hash yang tersimpan, sehati-hati apa pun pengguna Anda memilihnya. Kalau Anda ingin mencocokkan hash yang sudah ada dengan kata sandi kandidat tanpa repot menulis skrip, Anda bisa membuat dan memverifikasi hash bcrypt langsung di peramban dan menyaksikan sendiri perilaku yang sama.
Di mana persisnya batas itu jatuh
Kami mempersempit titik potongnya satu byte demi satu byte, dengan mempertahankan awalan yang sama dan mengubah tepat satu byte sesudahnya:
| Byte awalan yang identik | Byte N+1 berbeda pada | Hash sama? |
|---|---|---|
| 70 | 71 | false |
| 71 | 72 | false |
| 72 | 73 | true |
| 73 | 74 | true |
Byte ke-72 masih dihitung. Byte ke-73 adalah yang pertama tidak dihitung. Potongannya tegas, tanpa peredupan bertahap atau pencampuran parsial, dan uji serupa terhadap pustaka yang Anda pakai hanya butuh beberapa baris kode kalau ingin memastikannya secara lokal.
Karakter bukan byte
bcrypt menghitung byte UTF-8, sedangkan pengguna Anda mengetik karakter. Untuk ASCII kedua angka itu kebetulan sama, dan justru karena itulah masalah ini langsung menggigit begitu tim Anda merilis produk di luar pasar berbahasa Inggris.
| Jenis karakter | Contoh | Byte per karakter | 72 byte setara |
|---|---|---|---|
| Huruf Latin ASCII | A | 1 | 72 karakter |
| Aksara Han Tionghoa | 密 | 3 | 24 karakter |
| Kana Jepang | あ | 3 | 24 karakter |
| Emoji | 🔒 | 4 | 18 karakter |
| Kiril | я | 2 | 36 karakter |
| Umlaut Jerman | ü | 2 | 36 karakter |
Kami mengonfirmasi kedua ujung ekstremnya: dengan kata sandi berhuruf Tionghoa, perbedaan setelah karakter ke-24 diabaikan (true), dan dengan kata sandi emoji, perbedaan setelah karakter ke-18 diabaikan (true).
Frasa sandi Tionghoa sepanjang 25 karakter terlihat berlimpah di kolom kata sandi. Padahal ia sudah melewati garis batas. Pengguna yang memilih 20 emoji sudah kelebihan dua karakter dan tidak akan pernah diberi tahu.
Mengukur panjang byte di kode Anda sendiri
Pemeriksaan panjang yang ditulis berdasarkan jumlah karakter akan lolos padahal nilai di baliknya sudah terlalu panjang. Ukurlah byte:
# Python
len(pw.encode("utf-8"))
// Node.js
Buffer.byteLength(pw, "utf8")
// Go
len([]byte(pw))
Di peramban yang tidak punya Buffer, new TextEncoder().encode(pw).length memberi angka yang sama. Pasang pemeriksaan ini di depan pemanggilan hashing Anda dan kembalikan pesan validasi yang jelas, alih-alih membiarkan pustaka yang memutuskan untuk Anda pada pukul 3 dini hari. Kalau sekalian Anda meninjau ulang kebijakan panjang minimum, cara kekuatan kata sandi sebenarnya diukur membahas apa yang Anda dapat dari aturan panjang dan apa yang tidak.
Kenapa kata sandi pendek juga gagal: probe 255 byte milik passlib
Kata sandi Anda hanya empat belas karakter, tetapi pustakanya bersikeras panjangnya lebih dari 72 byte. Kasus inilah yang membuat kebanyakan orang lari ke mesin pencari.
Mereproduksinya
Tiga baris, pada Python 3.14.5 dengan bcrypt 5.0.0 dan passlib 1.7.4:
from passlib.hash import bcrypt
bcrypt.hash("short-password") # 14 byte
# ValueError: password cannot be longer than 72 bytes, truncate manually if necessary (e.g. my_password[:72])
Empat belas byte masuk, keluhan soal 72 byte keluar. Error passlib bcrypt itu nyata, tetapi angka di dalamnya menggambarkan sesuatu yang sama sekali lain.
Jejak pemanggilan lengkapnya
Berikut yang benar-benar berjalan, ditelusuri melalui passlib 1.7.4:
- Pemanggilan pertama memicu inisialisasi backend:
_calc_checksum→_stub_requires_backend()→set_backend(). _load_backend_mixinmembacabcrypt.__about__.__version__. Atributnya tidak ada, sehinggaAttributeErrordilempar. passlib menelannya dan mencetak(trapped) error reading bcrypt version.- Inisialisasi berlanjut ke
_finalize_backend_mixin(passlib/handlers/bcrypt.py:421), yang memanggildetect_wrap_bug(IDENT_2A). detect_wrap_bug(berkas yang sama,:378) memverifikasi sebuah probe tetap sepanjang 255 byte.- bcrypt 5.0.0 melempar
ValueErroruntuk apa pun yang melewati 72 byte, jadi probe itu meledak menimpa dirinya sendiri. - Eksepsinya merambat keluar sampai ke titik pemanggilan Anda. Anda melihat pesan tentang 72 byte yang sejak awal tidak pernah membahas masukan Anda.
Seluruh rangkaian ini terjadi sekali per proses, pada hash atau verify yang pertama. Itu sebabnya kegagalannya selalu bisa direproduksi, dan sebabnya apa pun yang Anda kirimkan tidak mengubah hasilnya.
Seperti apa bentuk probe-nya
secret = (b"0123456789" * 26)[:255]
Konstanta itu berasal dari bug wraparound pada bcrypt milik BSD yang diungkap Openwall pada 2012, di mana kunci panjang berputar kembali ke awal dan runtuh menjadi hash yang lebih lemah. passlib memeriksa saat startup apakah backend yang baru saja dimuat mengidap cacat itu, dan menolak memercayainya kalau iya.
Sebut saja apa adanya. detect_wrap_bug bukan bug passlib. Itu kode defensif yang melakukan persis seperti yang dirancang, memakai vektor uji yang sudah sahih selama lebih dari satu dekade. Yang berubah adalah bcrypt 5.0.0 kini memperlakukan masukan 255 byte sebagai error alih-alih sebagai sesuatu untuk di-hash, sehingga swauji yang tadinya lulus berubah menjadi swauji yang tak tertangkap. Diskusi pyca/bcrypt di issue #1082 membahas benturan antara kedua pustaka ini.
Kenapa patch __about__ tidak memperbaikinya
Cari error ini dan Anda akan diberi tahu, berulang kali, bahwa bcrypt menghapus __about__ dan bahwa memulihkannya akan memperbaiki passlib. Kedua paruh pernyataan itu keliru. Pengukurannya:
| Versi | hasattr(bcrypt, "__about__") | Mencetak peringatan trapped | passlib berfungsi |
|---|---|---|---|
| bcrypt 5.0.0 | False | Ya | Tidak (ValueError) |
| bcrypt 4.3.0 | False | Ya | Ya |
bcrypt 4.3.0 juga tidak punya __about__. Ia mencetak baris (trapped) error reading bcrypt version yang sama persis. Dan passlib berjalan di atasnya tanpa keluhan. Jadi atribut yang hilang itu bukan garis pemisah antara berfungsi dan rusak. Perubahan perilaku ValueError di 5.0.0 lah pemisahnya.
Artinya patch populer itu mustahil bekerja, dan memang tidak:
import bcrypt, types
bcrypt.__about__ = types.SimpleNamespace(__version__=bcrypt.__version__) # sebelum mengimpor passlib
from passlib.hash import bcrypt as pl
pl.hash("short-password")
# tetap ValueError: password cannot be longer than 72 bytes, ...
Kami menjalankan ini di proses yang bersih, dengan patch dipasang sebelum import passlib, justru supaya tak seorang pun bisa menyalahkan urutan impor. Tetap gagal. Patch itu hanya membungkam peringatan yang tidak berbahaya. Probe 255 byte di langkah 4 adalah tahap terpisah yang sejak awal tidak pernah menengok __about__, dan ia tetap meledak bagaimanapun juga.
Apa yang sebenarnya diubah bcrypt 5.0
Perubahan yang memutus kompatibilitas di bcrypt 5.0 hanya satu baris perilaku, tetapi radius ledakannya besar:
| Masukan | bcrypt 4.3.0 | bcrypt 5.0.0 |
|---|---|---|
| 72 byte | OK | OK |
| 73 byte | OK (dipotong diam-diam) | ValueError |
| 100 byte | OK (dipotong diam-diam) | ValueError |
| 255 byte | OK (dipotong diam-diam) | ValueError |
Pemotongan di kolom 4.x itu bukan kiasan. Pada 4.3.0, hash(73 byte) dan hash(100 byte) yang dibangun dari awalan yang sama keluar identik: true.
Jadi bcrypt 5.0 justru pustaka yang lebih benar di sini. Pustaka hashing yang tidak sanggup menghormati masukannya sebaiknya berhenti dan mengeluh, bukan membuang bahan kunci diam-diam. Itu tidak lantas membuat upgrade-nya tanpa rasa sakit. Kode yang bertahun-tahun diam-diam kehilangan byte sekarang melempar error, dan kalau jalur kode itu berada di balik passlib, ia melempar error bahkan sebelum masukan Anda terlibat.
Tabel itu punya dua konsekuensi, dan keduanya mendarat pada tim yang berbeda. Kalau Anda memanggil bcrypt secara langsung, upgrade-nya terlihat: Anda mendapat eksepsi saat registrasi atau login, di lokasi kode yang Anda miliki, dengan stack trace yang menunjuk ke pemanggilan hashing Anda sendiri. Tambahkan pemeriksaan panjang byte di depannya dan urusan selesai dalam satu sore.
Kalau Anda lewat passlib, upgrade-nya tak terlihat sampai ia menjadi total. Kegagalannya tidak sebanding dengan berapa banyak pengguna Anda yang punya kata sandi panjang, sebab ia sama sekali tidak bergantung pada masukan pengguna. Setiap hash dan setiap verify dalam proses itu gagal, mulai dari pemanggilan pertama, pada basis kode yang tidak mengubah apa pun soal penanganan kata sandi. Itulah sebabnya hal ini muncul sebagai insiden deployment alih-alih laporan bug, dan sebabnya teks error itu mengirim orang mencari ke tempat yang persis salah.
Cara memperbaikinya
Kalau Anda bisa mengubah kodenya
Tinggalkan passlib dan panggil bcrypt secara langsung. Rilis terakhir passlib adalah 1.7.4 dan proyeknya sudah lama sepi, jadi lapisan itu memberi Anda sangat sedikit manfaat pada proyek yang hanya butuh bcrypt:
import bcrypt
password = "correct horse battery staple".encode("utf-8")
hashed = bcrypt.hashpw(password, bcrypt.gensalt(rounds=12))
bcrypt.checkpw(password, hashed) # True
hashpw dan checkpw sama-sama menerima byte, jadi lakukan encoding di batas sistem dan biarkan sisa kode Anda tetap bekerja dengan str. Anda melewati deteksi backend dan probe swauji sekaligus, jadi hilang pula mode kegagalan yang melapor tentang kata sandi yang tidak Anda kirim. Kalau Anda ingin melihat langsung hash yang dihasilkan, atau memverifikasi hash buatan aplikasi Anda, generator bcrypt berjalan sepenuhnya di peramban Anda. Server yang memakai bcrypt untuk HTTP Basic Auth punya kendala struktural yang sama dalam format berkas yang berbeda, dan panduan htpasswd menjelaskannya langkah demi langkah.
Kalau Anda belum bisa mengubah kodenya hari ini
Kunci di bawah versi 5:
bcrypt<5
Kami memverifikasi bcrypt 4.3.0 dengan passlib 1.7.4 dan kombinasi itu berfungsi. Tapi pahami betul apa yang baru saja Anda beli. Ini torniket, bukan perbaikan. Anda bertahan di versi yang perilakunya terhadap bcrypt long password adalah membuang byte diam-diam, yaitu persis masalah yang ingin dihentikan oleh 5.0. Beri tanggal kedaluwarsa pada penguncian versi itu dan rencanakan perpindahannya.
Kalau pengguna Anda memang mengetik frasa sandi panjang
Lakukan hashing kata sandi lebih dulu dengan SHA-256, encode digest-nya ke base64, lalu berikan hasilnya ke bcrypt:
import base64, hashlib, bcrypt
def prehash(password: str) -> bytes:
return base64.b64encode(hashlib.sha256(password.encode("utf-8")).digest())
hashed = bcrypt.hashpw(prehash(pw), bcrypt.gensalt(rounds=12))
bcrypt.checkpw(prehash(pw), hashed)
Keluarannya selalu 44 byte, jauh di bawah 72, berapa pun panjang masukannya. Dan cara ini memulihkan properti yang dirusak oleh pemotongan: dua kata sandi 82 byte dari bagian pembuka, setelah dilewatkan ke sini, menghasilkan checkpw(prehash(p2), hash(prehash(p1))) = False. Tabrakannya lenyap.
Jangan buang langkah base64-nya; ia mengerjakan sesuatu yang nyata. Digest SHA-256 mentah adalah biner sembarang dan bisa mengandung byte NUL, yang ditangani secara tidak konsisten oleh berbagai implementasi bcrypt. base64 memberi Anda string ASCII bebas NUL dengan panjang tetap. Terapkan fungsi yang sama saat registrasi dan saat login, atau setiap hash yang sudah ada akan berhenti terverifikasi.
Yang tidak boleh dilakukan
Monkey patch __about__ tidak berfungsi. Bagian 4 memuat pengukurannya. Kalau ada anggota tim Anda yang hendak menempelkannya, empat baris di atas akan menghemat satu sore mereka.
Memotong sendiri dengan pw[:72] lebih buruk daripada tidak melakukan apa-apa. Cara itu mengubah kegagalan yang nyaring kembali menjadi kegagalan yang senyap, dan ia menciptakan ulang tabrakan dari bagian 2 di dalam kode Anda sendiri. Anda akan merakit dengan tangan persis perilaku yang ingin dihapus oleh bcrypt 5.0, dan tidak seperti versi pustakanya, versi Anda tidak akan pernah memperingatkan siapa pun. Kalau Anda butuh kata sandi panjang tetap berfungsi, lakukan pre-hash. Kalau tidak, validasi panjang byte-nya dan tolak dengan pesan yang jelas.
Bagaimana dengan hash yang sudah ada di basis data Anda
Baris mana yang terdampak
Hanya akun yang pemiliknya mendaftar dengan kata sandi di atas 72 byte. Untuk kebanyakan produk konsumen jumlahnya kecil, dan untuk apa pun yang murni ASCII biasanya berarti para penggemar frasa sandi panjang. Untuk produk dengan pengguna yang mengetik huruf Tionghoa, Jepang, atau emoji, bagian 3 berlaku dan himpunan yang terdampak bisa jauh lebih besar daripada dugaan audit yang buta terhadap byte.
Anda tidak bisa mengenali baris-baris ini dari hash-nya. Digest bcrypt berlebar tetap dan tidak menyimpan catatan apa pun tentang panjang masukannya. Kalau Anda dulu mencatat panjang kata sandi saat registrasi, catatan itulah satu-satunya inventaris Anda. Kebanyakan tim tidak mencatatnya, dan merekonstruksinya setelah kejadian tidak mungkin dilakukan, jadi rencanakanlah dengan asumsi tidak tahu, bukan dengan asumsi punya daftar.
Anda tidak bisa menghitung ulang secara massal
Tidak ada teks polos untuk di-hash ulang, dan itulah seluruh inti dari menyimpan hash. Jadi migrasinya harus malas: perbarui tiap akun pada saat pemiliknya berhasil melakukan autentikasi berikutnya, selagi Anda sejenak memegang teks polosnya di memori.
def login(user, password: str) -> bool:
if not verify_legacy(password, user.password_hash):
return False
if needs_rehash(user.password_hash):
user.password_hash = hash_new_scheme(password)
save(user)
return True
Verifikasi dengan skema lama dulu, baru setelah itu lakukan hash ulang. Membalik urutan kedua langkah itu berarti menimpa hash tersimpan sebelum Anda memastikan kata sandinya benar. Simpan penanda skema di samping setiap hash supaya needs_rehash menjadi perbandingan field alih-alih tebakan, dan siapkan diri untuk ekor panjang berisi akun tidur yang tidak pernah login. Akun-akun itu Anda tangani saat reset kata sandi, bukan dengan paksaan.
Kapan migrasi penuh sepadan
Kalau Anda toh sedang menulis jalur rehash malas, itulah momen termurah yang akan pernah Anda dapat untuk mengganti algoritma di bawahnya. Plafon 72 byte tidak ada di Argon2id, dan perbandingan mendalam antara Argon2id dan bcrypt membahas kapan perpindahan itu sepadan dan kapan bertahan di bcrypt justru pilihan yang tepat. OWASP Password Storage Cheat Sheet adalah rujukan untuk mencocokkan parameter Anda.
Jangan memulai migrasi semata-mata karena error ini. Kalau kata sandi Anda nyaman berada di bawah 72 byte, bcrypt tetap pilihan yang sehat dan bagian 6 sudah menyelesaikan masalah Anda.
FAQ
Kenapa bcrypt bilang kata sandi saya lebih panjang dari 72 byte padahal pendek?
Karena pesan itu membahas probe internal passlib, bukan kata sandi Anda. Pada pemanggilan pertama, passlib menjalankan detect_wrap_bug dengan string uji tetap sepanjang 255 byte. bcrypt 5.0.0 melempar ValueError untuk apa pun di atas 72 byte, sehingga probe-nya gagal dan error muncul di titik pemanggilan Anda. Kata sandi 14 byte pun memicunya.
Apakah bcrypt benar-benar mengabaikan semua yang lewat dari 72 byte?
Ya — bcrypt mengabaikan setiap byte setelah 72, sepenuhnya. Dua kata sandi 82 byte yang 72 byte pertamanya sama menghasilkan hash identik $2a$10$abcdefghijklmnopqrstuu.hioaszd4nGKdJlcuRzR1xqPIcN/X.S, dan masing-masing terverifikasi terhadap hash milik yang lain. Batasnya presisi: perbedaan di byte ke-72 mengubah hash, perbedaan di byte ke-73 tidak.
Apakah batas 72 byte itu masalah keamanan?
Ya, batas 72 byte bcrypt adalah masalah keamanan untuk frasa sandi panjang. Siapa pun yang tahu 72 byte pertama bisa menambahkan byte sembarang dan lolos autentikasi, jadi setiap byte melewati batas itu tidak menambah apa pun. Untuk kata sandi di bawah 72 byte, hal ini sama sekali tidak berpengaruh. Pre-hash dengan SHA-256 menghapus paparan itu jika masukan panjang harus dihitung penuh.
72 byte itu berapa karakter?
Tergantung pengkodean (encoding): 72 byte bcrypt tidak selalu berarti 72 karakter. 72 huruf ASCII, 36 karakter Kiril atau umlaut, 24 aksara Han Tionghoa, 24 kana Jepang, atau 18 emoji. bcrypt menghitung byte UTF-8 dan bukan karakter, jadi ukurlah dengan len(pw.encode("utf-8")) di Python atau Buffer.byteLength(pw, "utf8") di Node.
Apakah menambal __about__ memperbaiki error passlib?
Tidak, menambal __about__ tidak memperbaiki error passlib bcrypt. Kami menerapkan patch itu sebelum import passlib di proses yang bersih dan ValueError tetap muncul. bcrypt 4.3.0 juga tidak punya __about__ dan berfungsi baik dengan passlib, yang membuktikan bahwa atribut yang hilang bukan penyebabnya. Patch itu hanya membungkam peringatan (trapped) error reading bcrypt version.
Haruskah saya menurunkan versi bcrypt ke bawah 5.0?
Menurunkan bcrypt ke bawah 5.0 boleh sebagai penambal sementara. bcrypt 4.3.0 dengan passlib 1.7.4 berfungsi. Tapi 4.x memotong diam-diam apa pun yang lewat dari 72 byte, dan itulah perilaku yang ingin dihentikan oleh 5.0, jadi perlakukan penguncian versi itu sebagai sementara dan beralihlah ke memanggil bcrypt secara langsung.
Bisakah saya memotong sendiri kata sandinya ke 72 byte?
Jangan memotong sendiri kata sandi ke 72 byte. pw[:72] menciptakan ulang tabrakan yang dijelaskan di atas di dalam kode Anda sendiri, secara senyap, tanpa peringatan pustaka apa pun yang bisa menangkapnya. Pilihlah pre-hash dengan SHA-256 dan base64 supaya masukan panjang tetap berbeda satu sama lain, atau validasi panjang byte-nya di awal dan tolak dengan pesan error yang jelas.
Apa yang terjadi pada kata sandi yang sudah di-hash sebelum saya memperbaikinya?
Semua hash bcrypt yang sudah ada tetap terverifikasi, karena jalur verify Anda memotong dengan cara yang sama seperti jalur hash. Hanya akun yang didaftarkan dengan kata sandi di atas 72 byte yang melemah, dan Anda tidak bisa menghitungnya ulang tanpa teks polos. Lakukan hash ulang secara malas pada login berhasil berikutnya, dan tangani akun tidur saat reset kata sandi.