bcrypt 72 bayt hatası: kısa parolalar neden başarısız oluyor
Birbirinden tamamen farklı iki sorun aynı mesajı üretiyor ve bunlardan yalnızca biri parolanızla ilgili.
Parolanız gerçekten de bcrypt’in 72 baytlık sınırını aşıyorsa, bcrypt ilk 72 baytı okur ve gerisini atar. İlk 72 baytı ortak olan 82 baytlık iki parolayı sabit bir salt altında hash’ledik. İkisi de $2a$10$abcdefghijklmnopqrstuu.hioaszd4nGKdJlcuRzR1xqPIcN/X.S değerini üretti ve bcrypt.compareSync(p2, hash(p1)) çağrısı true döndürdü. Yani ikinci parola, birinci parolanın hesabına giriş yapıyor.
Parolanız gözle görülür biçimde kısaysa ve yine de şu hatayı alıyorsanız:
password cannot be longer than 72 bytes, truncate manually if necessary (e.g. my_password[:72])
(anlamı: “parola 72 bayttan uzun olamaz, gerekirse elle kısaltın”)
o zaman mesaj nedeni yanlış gösteriyor. passlib 1.7.4 ile bcrypt 5.0.0 altında 14 baytlık bir parola bile bu hatayı fırlatıyor.
Oradaki suçlu, passlib’in içindeki 255 baytlık sabit bir öz test sondası. Bu sonda, arka uç ilklendirilirken bir kez çalışır; yani parolanız hash’leme çağrısına daha ulaşmadan önce. bcrypt 5.0.0 sondayı reddediyor, istisna dışarı sızıyor ve siz kimsenin yazmadığı bir parola hakkında şikâyet okuyorsunuz.
Bu hata için arama sonuçlarına hâkim olan __about__ monkey patch’i de sorunu çözmüyor. Yamayı import passlib öncesinde uygulayıp temiz bir süreçte yeniden çalıştırdık ve ValueError hiç değişmeden geri geldi.
30 saniyelik triyaj: siz hangisisiniz
| Parolanız | Hata ne zaman çıkıyor | Kök neden | Nereye gidin |
|---|---|---|---|
| 72 bayttan uzun | hash çağrısını yaptığınızda | Gerçekten fazla uzun. bcrypt 5.0 hata fırlatır, bcrypt 4.x sessizce kısaltır | Bölüm 2 ve 3 |
| 72 baytın altında, passlib kullanılıyor | Süreçteki ilk çağrıda | passlib’in 255 baytlık sondası. Parolanızla hiçbir ilgisi yok | Bölüm 4 |
| Çince, Japonca veya emoji içeriyor | Kısa görünüyor ama değil | Karakterler bayt değildir | Bölüm 3 |
| Bir bağımlılık yükseltmesinden sonra bozuldu | Dağıtımdan sonra | bcrypt 5.0 breaking change | Bölüm 4 ve 5 |
İkinci satırdaysanız doğrudan ileri atlayın. Sonraki iki bölümde işinize yarayacak hiçbir şey yok ve çözüm de farklı.
bcrypt 72 baytlık sınırı parolanıza ne yapıyor
bcrypt neden 72’de duruyor
bcrypt, Blowfish üzerine kuruludur ve parolanızı Blowfish anahtarı olarak besler. Blowfish, anahtarını her biri 32 bit genişliğinde 18 alt anahtardan oluşan bir P dizisine genişletir. Bu da 18 × 4 = 72 baytlık anahtar malzemesi eder; genişletme döngüsü 18 gözü doldurduktan sonra anahtarın başına geri döner.
Yani tavan yapısaldır. Üşengeç bir uygulama ya da birinin yükseltmeyi unuttuğu ayarlanabilir bir tampon değildir. Standarda uygun her bcrypt uygulaması, platform ne olursa olsun aynı yerde kesiyor; 72 sayısını Python’da, Node’da, Go’da, Java’da ve PHP’de aynı şekilde görmenizin nedeni budur.
İki farklı parola, tek bir hash
bcrypt’in parolayı kısaltması kulağa sıradan bir uzunluk kuralı gibi geliyor, ama sonucu doğrudan kimlik doğrulamayı ilgilendiriyor.
bcryptjs 3.0.3 ile ve $2a$10$abcdefghijklmnopqrstuv sabit salt’ıyla, her biri 82 bayt uzunluğunda iki parolayı hash’ledik:
| Parola | Değer | Bayt |
|---|---|---|
| p1 | "A"×72 + "XXXXXXXXXX" | 82 |
| p2 | "A"×72 + "ZZZZZZZZZZ" | 82 |
İkisi de aynı özeti üretti:
$2a$10$abcdefghijklmnopqrstuu.hioaszd4nGKdJlcuRzR1xqPIcN/X.S
Dolayısıyla karşılaştırma da onları ayırt edemiyor:
bcrypt.compareSync(p2, hash(p1)) // true
Uzun bir parolanın ilk 72 baytını bilen bir saldırgan, arkasına ne eklerse eklesin kimlik doğrulamasını geçer. Sınırın ötesindeki her bayt, kullanıcılarınız onları ne kadar özenle seçmiş olursa olsun, saklanan hash’in gücüne hiçbir şey katmaz. Elinizdeki bir hash’i bir aday parolayla karşılaştırmak isteyip bunun için betik yazmak istemiyorsanız, bcrypt hash’lerini tarayıcıda üretip doğrulayabilir ve aynı davranışı kendiniz izleyebilirsiniz.
Sınır tam olarak nereye düşüyor
Kesme noktasını bayt bayt daralttık; ortak bir ön ek tutup hemen ardından tam olarak tek bir baytı değiştirdik:
| Aynı olan ön ek baytı | N+1. bayt şurada farklı | Hash aynı mı? |
|---|---|---|
| 70 | 71 | false |
| 71 | 72 | false |
| 72 | 73 | true |
| 73 | 74 | true |
- bayt hâlâ sayılıyor. Saymayan ilk bayt 73. Arada sönümlenme ya da kısmi karışma diye bir şey yok, sınır tek bir baytta keskin biçimde bitiyor. Aynı denemeyi kendi kütüphanenizde birkaç dakikada tekrarlayabilirsiniz.
Karakterler bayt değildir
bcrypt UTF-8 baytlarını sayar, kullanıcılarınız ise karakter yazar. ASCII için bu iki sayı tesadüfen çakışır; ekiplerin İngilizce konuşulan pazarın dışına çıktığı anda bu sorunun onları ısırmasının nedeni de budur.
| Karakter türü | Örnek | Karakter başına bayt | 72 bayt şuna eşit |
|---|---|---|---|
| ASCII Latin harfleri | A | 1 | 72 karakter |
| Çince Han karakterleri | 密 | 3 | 24 karakter |
| Japonca kana | あ | 3 | 24 karakter |
| Emoji | 🔒 | 4 | 18 karakter |
| Kiril | я | 2 | 36 karakter |
| Almanca umlaut | ü | 2 | 36 karakter |
Her iki uçta da doğruladık: Çince bir parolada 24. karakterden sonraki farklar yok sayılıyor (true), emoji bir parolada ise 18. karakterden sonrakiler yok sayılıyor (true).
25 karakterlik bir Çince parola, parola alanında cömert görünür. Oysa çizgiyi çoktan aşmıştır. 20 emoji seçen bir kullanıcı sınırı iki karakter aşmış olur ve bunu ona kimse söylemez.
Kendi kodunuzda bayt uzunluğunu ölçmek
Karakter sayısına göre yazılmış uzunluk denetimleri, alttaki değer çoktan fazla uzunken bile geçer. Baytları ölçün:
# Python
len(pw.encode("utf-8"))
// Node.js
Buffer.byteLength(pw, "utf8")
// Go
len([]byte(pw))
Buffer bulunmayan tarayıcılarda new TextEncoder().encode(pw).length aynı sayıyı verir. Bu denetimi hash’leme çağrınızın önüne koyun ve kararı sabaha karşı 3’te kütüphaneye bırakmak yerine gerçek bir doğrulama mesajı döndürün. Hazır oradayken asgari uzunluk politikanızı da gözden geçiriyorsanız, parola gücünün gerçekte nasıl ölçüldüğü bir uzunluk kuralının size ne kazandırdığını ve ne kazandırmadığını anlatıyor.
Kısa parolalar neden başarısız oluyor: passlib’in 255 baytlık sondası
Çoğu kişiyi arama motoruna gönderen durum şu: parolanız on dört karakter uzunluğunda, kütüphane ise 72 baytı aştığında ısrar ediyor.
Yeniden üretmek
Python 3.14.5 üzerinde, bcrypt 5.0.0 ve passlib 1.7.4 ile üç satır:
from passlib.hash import bcrypt
bcrypt.hash("short-password") # 14 bayt
# ValueError: password cannot be longer than 72 bytes, truncate manually if necessary (e.g. my_password[:72])
İçeri on dört bayt girdi, dışarı 72 bayt şikâyeti çıktı. passlib bcrypt hatası gerçek, ama içindeki sayı bambaşka bir şeyi anlatıyor.
Çağrı yığınının tamamı
Bu bir çıkarım değil. passlib 1.7.4 üzerinden izlenmiş, gerçekte çalışan şey şu:
- İlk çağrı arka uç ilklendirmesini tetikler:
_calc_checksum→_stub_requires_backend()→set_backend(). _load_backend_mixin,bcrypt.__about__.__version__değerini okur. Öznitelik yoktur, bu yüzden birAttributeErrorfırlatılır. passlib bunu yutar ve(trapped) error reading bcrypt versionsatırını yazdırır.- İlklendirme
_finalize_backend_mixiniçine devam eder (passlib/handlers/bcrypt.py:421); burasıdetect_wrap_bug(IDENT_2A)çağrısını yapar. detect_wrap_bug(aynı dosya,:378) sabit 255 baytlık bir sondayı doğrular.- bcrypt 5.0.0, 72 baytı aşan her şey için
ValueErrorfırlatır; dolayısıyla sonda kendi üstüne patlar. - İstisna sizin çağrı noktanıza kadar yayılır. Girdinizle hiçbir zaman ilgisi olmamış bir 72 bayt mesajı görürsünüz.
Bu dizinin tamamı süreç başına bir kez, ilk hash veya doğrulama çağrısında yaşanır. Hatanın bu kadar güvenilir biçimde yeniden üretilebilir ve ne gönderdiğinize bu kadar tümüyle duyarsız olmasının nedeni budur.
Sonda neye benziyor
secret = (b"0123456789" * 26)[:255]
Bu sabit, BSD’nin bcrypt’indeki, Openwall’un 2012’de duyurduğu sarma hatasından geliyor; orada uzun anahtarlar başa sarıyor ve daha zayıf hash’lere çöküyordu. passlib, başlangıçta az önce yüklediği arka ucun bu kusuru taşıyıp taşımadığını denetler ve taşıyan bir arka uca güvenmeyi reddeder.
Adını doğru koyalım. detect_wrap_bug bir passlib hatası değil. On yılı aşkın süredir geçerli olan bir test vektörünü kullanarak, tam da yazılma amacını yerine getiren savunma amaçlı bir koddur. Değişen şey şu: bcrypt 5.0.0 artık 255 baytlık bir girdiyi hash’lenecek bir şey olarak değil, bir hata olarak ele alıyor; bu da geçen bir öz testi yakalanamayan bir öz teste dönüştürüyor. pyca/bcrypt’teki issue #1082 tartışması iki kütüphane arasındaki bu çarpışmayı ele alıyor.
__about__ yaması bunu neden düzeltmiyor
Bu hatayı aratın; size defalarca bcrypt’in __about__ özniteliğini kaldırdığı ve onu geri koymanın passlib’i onardığı söylenecek. Bu cümlenin iki yarısı da yanlış ve bunu gösteren ölçüm şu:
| Sürüm | hasattr(bcrypt, "__about__") | trapped uyarısını yazdırıyor | passlib çalışıyor |
|---|---|---|---|
| bcrypt 5.0.0 | False | Evet | Hayır (ValueError) |
| bcrypt 4.3.0 | False | Evet | Evet |
bcrypt 4.3.0’da da __about__ yok. O da aynı (trapped) error reading bcrypt version satırını yazdırıyor. Ve passlib onun üzerinde hiç şikâyet etmeden çalışıyor. Dolayısıyla eksik öznitelik, çalışan ile bozuk olan arasındaki ayrım çizgisi değil. Ayrım çizgisi 5.0.0’daki ValueError davranış değişikliği.
Bu da o popüler yamanın çalışamayacağı anlamına geliyor ve zaten çalışmıyor da:
import bcrypt, types
bcrypt.__about__ = types.SimpleNamespace(__version__=bcrypt.__version__) # passlib'i import etmeden önce
from passlib.hash import bcrypt as pl
pl.hash("short-password")
# yine ValueError: password cannot be longer than 72 bytes, ...
Bunu temiz bir süreçte, yamayı import passlib öncesinde uygulayarak çalıştırdık; tam da kimse hatayı import sırasına bağlayamasın diye. Yine de başarısız oluyor. Yamanın tek başardığı şey zararsız bir uyarıyı susturmak. 4. adımdaki 255 baytlık sonda ayrı bir aşama; __about__ özniteliğine zaten hiç bakmıyordu ve iki durumda da patlıyor.
bcrypt 5.0 gerçekte neyi değiştirdi
bcrypt 5.0 breaking change tek satırlık bir davranış değişikliği, ama patlama yarıçapı geniş:
| Girdi | bcrypt 4.3.0 | bcrypt 5.0.0 |
|---|---|---|
| 72 bayt | Sorunsuz | Sorunsuz |
| 73 bayt | Sorunsuz (sessizce kısaltılır) | ValueError |
| 100 bayt | Sorunsuz (sessizce kısaltılır) | ValueError |
| 255 bayt | Sorunsuz (sessizce kısaltılır) | ValueError |
4.x sütunundaki kısaltma bir mecaz değil. 4.3.0 altında, aynı ön ekten kurulmuş hash(73 bayt) ve hash(100 bayt) eşit çıkıyor: true.
Yani burada daha doğru olan kütüphane bcrypt 5.0. Anahtar malzemesini sessizce çöpe atmak, hata fırlatmaktan çok daha kötü bir sonuç; kendisine verilen girdiyi karşılayamayan bir hash’leme kütüphanesi de zaten orada durmalıdır. Bu, yükseltmeyi acısız kılmıyor elbette. Yıllardır sessizce bayt kaybeden kod artık hata fırlatıyor; o kod yolu passlib’in arkasındaysa, girdiniz işin içine girmeden önce fırlatıyor.
O tablodan iki sonuç çıkıyor ve bunlar farklı ekiplerin kucağına düşüyor. bcrypt’i doğrudan çağırıyorsanız yükseltme görünür oluyor: kayıt ya da girişte, sahibi olduğunuz bir kod konumunda, kendi hash’leme çağrınızı gösteren bir yığın iziyle bir istisna alıyorsunuz. Önüne bir bayt uzunluğu denetimi ekleyin, işiniz bir öğleden sonrada biter.
passlib üzerinden gidiyorsanız yükseltme, tamamen çökene kadar görünmez kalıyor. Hata, kullanıcılarınızın kaçının uzun parolası olduğuyla orantılı değil; çünkü kullanıcı girdisine hiç bağlı değil. Parola işleme tarafında hiçbir şeyin değişmediği bir kod tabanında, süreçteki her hash ve her doğrulama, ilk çağrıdan itibaren başarısız oluyor. Bunun bir hata raporu olarak değil bir dağıtım olayı olarak ortaya çıkmasının ve hata metninin insanları tam da yanlış yere bakmaya göndermesinin nedeni bu.
Nasıl düzeltilir
Kodu değiştirebiliyorsanız
passlib’i bırakın ve bcrypt’i doğrudan çağırın. passlib’in son sürümü 1.7.4 ve proje uzun zamandır sessiz; dolayısıyla yalnızca bcrypt’e ihtiyaç duyan bir projede bu katman size çok az şey kazandırıyor:
import bcrypt
password = "correct horse battery staple".encode("utf-8")
hashed = bcrypt.hashpw(password, bcrypt.gensalt(rounds=12))
bcrypt.checkpw(password, hashed) # True
hashpw da checkpw de bayt alır; bu yüzden sınırda kodlayın ve kodunuzun geri kalanı str ile çalışmaya devam etsin. Arka uç algılaması da öz test sondası da devreye girmiyor; dolayısıyla hiç vermediğiniz bir parola yüzünden hata almıyorsunuz. Ortaya çıkan hash’e göz atmak ya da uygulamanızın ürettiği bir hash’i doğrulamak isterseniz, bcrypt üretici tümüyle tarayıcınızda çalışıyor. HTTP Basic Auth için bcrypt kullanan sunucularda aynı yapısal kısıt farklı bir dosya biçiminde karşınıza çıkıyor; htpasswd rehberi bunu adım adım anlatıyor.
Kodu bugün değiştiremiyorsanız
Sürümü 5’in altına sabitleyin:
bcrypt<5
bcrypt 4.3.0’ı passlib 1.7.4 ile doğruladık, çalışıyor. Ama ne satın aldığınız konusunda net olun. Bu bir onarım değil, bir turnike. Uzun bir bcrypt parolası karşısındaki davranışı baytları sessizce çöpe atmak olan bir sürümde kalıyorsunuz; oysa 5.0 tam da bunu durdurmak için yayımlandı. Sabitlemeye bir tarih koyun ve geçişi planlayın.
Kullanıcılarınız gerçekten uzun parolalar yazıyorsa
Parolayı önce SHA-256 ile bir kez hash’leyin, özeti base64 ile kodlayın, sonra bunu bcrypt’e verin:
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)
Çıktı, girdi uzunluğu ne olursa olsun her zaman 44 bayt; 72’nin rahatça altında. Ve kısaltmanın yok ettiği özelliği geri getiriyor: giriş bölümündeki o 82 baytlık iki parola bundan geçirildiğinde checkpw(prehash(p2), hash(prehash(p1))) False veriyor. Çakışma ortadan kalkıyor.
base64 adımı gerçek bir iş yapıyor, o yüzden onu atmayın. Ham bir SHA-256 özeti keyfi ikili veridir ve içinde NUL baytları bulunabilir; bcrypt uygulamaları bunları tutarsız biçimde ele alır. base64 size sabit uzunlukta, NUL içermeyen bir ASCII karakter dizisi verir. Aynı işlevi hem kayıtta hem girişte uygulayın, yoksa mevcut bütün hash’ler doğrulanmaz olur.
Yapılmaması gerekenler
İki cazip hamle, ikisi de zararlı.
__about__ monkey patch’i işe yaramıyor. Ölçüm 4. bölümde. Ekibinizden biri onu yapıştırmak üzereyse, yukarıdaki dört satır ona bir öğleden sonra kazandırır.
Parolayı kendi elinizle pw[:72] ile kısaltmak ise hiçbir şey yapmamaktan daha kötü. Gürültülü bir hatayı yeniden sessiz bir hataya çeviriyor ve 2. bölümdeki çakışmayı kendi kodunuzun içinde yeniden yaratıyor. bcrypt 5.0’ın ortadan kaldırmak için yayımlandığı davranışı elle yeniden kurmuş olursunuz; üstelik kütüphane sürümünün aksine sizinki kimseyi asla uyarmayacak. Uzun parolaların çalışması gerekiyorsa ön hash uygulayın. Gerekmiyorsa bayt uzunluğunu doğrulayın ve açık bir mesajla reddedin.
Veritabanınızdaki mevcut hash’ler ne olacak
Hangi satırlar etkileniyor
Yalnızca sahipleri 72 bayttan uzun bir parolayla kayıt olmuş hesaplar. Çoğu tüketici ürününde bu küçük bir küme, salt ASCII olan her şeyde de genelde uzun parola meraklıları demek. Kullanıcıları Çince, Japonca veya emoji yazan ürünlerde ise 3. bölüm devreye giriyor ve etkilenen küme, bayta bakmayan bir denetimin düşündürdüğünden çok daha büyük olabiliyor.
Bu satırları hash’lerden ayırt edemezsiniz. Bir bcrypt özeti sabit genişliktedir ve girdisinin ne kadar uzun olduğuna dair hiçbir kayıt taşımaz. Kayıt sırasında parola uzunluğunu logladıysanız, envanteriniz yalnızca o log. Çoğu ekip bunu yapmamıştır ve sonradan yeniden kurmak mümkün değildir; bu yüzden bir liste üzerinden değil, bilmiyor olmak üzerinden plan yapın.
Toplu olarak yeniden hesaplayamazsınız
Yeniden hash’lenecek bir düz metin yok; zaten hash saklamanın bütün amacı da bu. Dolayısıyla geçiş tembel olmak zorunda: her hesabı, sahibi bir sonraki başarılı kimlik doğrulamasını yaptığında, düz metni kısa süreliğine bellekte tutarken yükseltin.
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
Önce eski şemayla doğrulayın, ancak ondan sonra yeniden hash’leyin. Bu iki adımı ters çevirirseniz, parolanın doğru olduğunu teyit etmeden saklanan hash’i yeniden yazmış olursunuz. Her hash’in yanında bir şema tanımlayıcısı saklayın ki needs_rehash bir tahmin değil bir alan karşılaştırması olsun; ayrıca hiç giriş yapmayan uykudaki hesaplardan oluşan uzun bir kuyruk bekleyin. Onları zorlamayla değil, parola sıfırlamada halledersiniz.
Tam bir geçiş ne zaman değer
Zaten tembel yeniden hash’leme yolunu yazıyorsanız, altındaki algoritmayı değiştirmek için eline geçecek en ucuz an odur. 72 baytlık tavan Argon2id’de yok; Argon2id ile bcrypt’in derinlemesine karşılaştırması bu geçişin ne zaman kendini amorti ettiğini, bcrypt’te kalmanın ne zaman doğru karar olduğunu anlatıyor. Parametrelerinizi karşılaştıracağınız başvuru kaynağı ise OWASP Password Storage Cheat Sheet.
Yalnızca bu hata yüzünden bir geçişe girişmeyin. Parolalarınız 72 baytın rahatça altındaysa bcrypt sağlam bir seçim olmayı sürdürüyor ve 6. bölüm sorununuzu zaten çözdü.
SSS
Parolam kısayken bcrypt neden 72 bayttan uzun olduğunu söylüyor?
Çünkü mesaj sizin parolanızla değil, passlib’in iç sondasıyla ilgili. İlk çağrıda passlib, detect_wrap_bug işlevini sabit 255 baytlık bir test dizisiyle çalıştırıyor. bcrypt 5.0.0, 72 baytı aşan her şey için ValueError fırlattığından sonda başarısız oluyor ve hata sizin çağrı noktanızda yüzeye çıkıyor. 14 baytlık bir parola bile bunu tetikliyor.
bcrypt gerçekten 72 bayttan sonrasını tümüyle yok sayıyor mu?
Evet, bcrypt 72. bayttan sonrasını tamamen yok sayıyor. İlk 72 baytı ortak olan 82 baytlık iki parola aynı $2a$10$abcdefghijklmnopqrstuu.hioaszd4nGKdJlcuRzR1xqPIcN/X.S hash’ini üretiyor ve her biri diğerinin hash’ine karşı doğrulanıyor. Sınır kesin: 72. baytta bir fark hash’i değiştiriyor, 73. baytta bir fark değiştirmiyor.
72 baytlık sınır bir güvenlik sorunu mu?
Uzun parolalar için evet, 72 baytlık sınır bir güvenlik sorunu. İlk 72 baytı bilen herkes arkasına keyfi baytlar ekleyip kimlik doğrulamasını geçebilir; yani sınırın ötesindeki her bayt hiçbir şey katmıyor. 72 baytın altındaki parolalar için ise hiçbir şey değişmiyor. Uzun girdilerin tümüyle sayması gerekiyorsa SHA-256 ile ön hash bu açığı kapatıyor.
72 bayt kaç karakter eder?
72 baytın kaç karakter ettiği kodlamaya bağlı. 72 ASCII harfi, 36 Kiril veya umlaut karakteri, 24 Çince Han karakteri, 24 Japonca kana ya da 18 emoji. bcrypt karakterleri değil UTF-8 baytlarını saydığı için Python’da len(pw.encode("utf-8")), Node’da Buffer.byteLength(pw, "utf8") ile ölçün.
__about__ yaması passlib hatasını düzeltir mi?
Hayır, __about__ yaması passlib hatasını düzeltmiyor. Yamayı temiz bir süreçte import passlib öncesinde uyguladık ve ValueError yine tetiklendi. bcrypt 4.3.0’da da __about__ yok ve passlib ile sorunsuz çalışıyor; bu da eksik özniteliğin neden olmadığını kanıtlıyor. Yama yalnızca (trapped) error reading bcrypt version uyarısını susturuyor.
bcrypt’i 5.0’ın altına düşürmeli miyim?
Geçici çözüm olarak evet, bcrypt’i 5.0’ın altına düşürmek işe yarıyor. bcrypt 4.3.0, passlib 1.7.4 ile çalışıyor. Ama 4.x, 72 baytı aşan her şeyi sessizce kısaltıyor ki 5.0 tam da bu davranışı durdurmak için yayımlandı; bu yüzden sabitlemeyi geçici sayın ve bcrypt’i doğrudan çağırmaya geçin.
Parolayı 72 bayta kendim kısaltsam olmaz mı?
Parolayı 72 bayta kendiniz kısaltmayın. pw[:72] yukarıda anlatılan çakışmayı kendi kodunuzun içinde, sessizce ve yakalayabileceğiniz hiçbir kütüphane uyarısı olmadan yeniden yaratır. Ya SHA-256 ve base64 ile ön hash uygulayın ki uzun girdiler farklı kalsın, ya da bayt uzunluğunu baştan doğrulayıp açık bir hata mesajıyla reddedin.
Bunu düzeltmeden önce hash’lenmiş parolalar ne olacak?
Daha önce hash’lenmiş parolalar doğrulanmaya devam ediyor; çünkü doğrulama yolunuz da hash yolunun kısalttığı gibi kısaltıyor. Yalnızca 72 baytı aşan parolalarla kaydolmuş hesaplar zayıflamış durumda ve düz metin olmadan onları yeniden hesaplayamazsınız. Bir sonraki başarılı girişte tembel biçimde yeniden hash’leyin, uykudaki hesapları da parola sıfırlamada ele alın.