A jelszavak tárolása azon kevés szoftverfejlesztési területek egyike, ahol létezik valódi, publikált, karbantartott és ingyenesen elérhető helyes válasz. Ugyanakkor azon területek egyike is, amelyeket a leginkább következetesen rontanak el, mert a rossz válaszok valamikor helyesek voltak, és azóta sem nézte meg őket senki újra.
A hiba ritkán egzotikus. Egy 2016-ban épült rendszerről van szó, amely 2012-ben aktuális tanácsokat követett, még mindig fut, még mindig fogad bejelentkezéseket, és abba a hash függvénybe azóta nem nézett bele senki, hogy az azt megíró kolléga elhagyta a céget.
Ha csak egyetlen dolgot viszel magaddal: használj Argon2id-t, ha pedig nem tudsz, használj bcryptet. Ebben a cikkben minden más csak részlet. Egy általános célú hash, például a SHA-256, nem jelszó-hash, függetlenül attól, hányszor alkalmazod, mert a sebessége tervezési cél, és éppen a sebesség az, amit meg akarsz tagadni attól a támadótól, aki megszerezte az adatbázisodat.
A jelszótárolásnak pontosan egy helyes formája van
Olyan hash értéket tárolj, amelyet szándékosan lassú, sok memóriát igénylő függvény állított elő, jelszavanként egyedi véletlen salt kíséretében, a saját hardveredre hangolt paraméterekkel.
Az OWASP jelszótárolási útmutatója pontosan megfogalmazza az aktuális ajánlásokat, és érdemes őket számként idézni, nem pedig elvként.
| Algoritmus | Ajánlott paraméterek | Mikor használd |
|---|---|---|
| Argon2id | 19 MiB memória, 2 iteráció, 1 fokú párhuzamosság | Első választás |
| scrypt | N=2^17 (128 MiB), r=8, p=1 | Ha az Argon2id nem érhető el |
| bcrypt | Work factor 10 vagy több, 72 byte jelszóhatár | Örökölt rendszerek |
| PBKDF2-HMAC-SHA256 | 600 000 iteráció | Ahol FIPS-140 megfelelés kötelező |
Két megjegyzés a táblázathoz. Az Argon2id értéke minimum, és a több memória kevesebb iterációval egyenértékű csere, ezért a 47 MiB memóriát 1 iterációval használó beállítás az alapértékkel összemérhető biztonságot ad. A bcrypt 72 byte-os korlátja pedig valódi csonkolás, nem érvényesítési szabály: minden, ami 72 byte fölött van, csendben elveszik, ami akkor számít, ha hosszú jelmondatokat fogadsz el, vagy ha a bemenetet előre lehasheled.
Ezeket a paramétereket a hardver fejlődésével felfelé módosítják. A megvalósításkor a forrást olvasd, ne ezt a táblázatot.
A salt nem opcionális, és nem is elegendő
A salt egy egyedi véletlen érték, amelyet minden hash mellé eltárolunk. A célja szűk és fontos: biztosítja, hogy két azonos jelszavú felhasználó eltérő hash értéket kapjon. Ez érvényteleníti az előre kiszámított szivárványtáblákat, és megakadályozza, hogy a támadó egyetlen jelszót feltörve minden olyan fiókot megszerezzen, amely ugyanazt a jelszót használta.
Amit a salt nem tesz meg, az az, hogy bárkit lelassítson. Aki megszerezte az adatbázisodat, a saltokat is megszerezte, hiszen azoknak olvashatónak kell lenniük a bejelentkezés ellenőrzéséhez. A puszta saltolás egy gyors hash mellett azt jelenti, hogy a támadó minden jelszót külön-külön támad, óriási sebességgel, vagyis pontosan az a helyzet áll elő, amelyet el akartál kerülni.
A lassúságnak az algoritmusból kell jönnie. Pontosan ez a lényege a sok memóriát igénylő függvénynek: szándékosan fogyaszt erőforrást, hogy a célhardverrel felszerelt támadó sokkal kisebb előnyhöz jusson, mint amekkorát egy gyors hash ellen szerezne.
A pepper, vagyis minden jelszóra alkalmazott titkos érték, amelyet az adatbázison kívül tárolsz, valódi réteget ad hozzá, mert egy puszta adatbázismentés önmagában már kevés lesz. Üzemeltetési terhet is jelent, hiszen a cseréje a következő bejelentkezéskor újrahashelést kíván, az elvesztése pedig minden fiókot kizár. Nagy értékű rendszereknél megéri, a legtöbb helyen elhagyható.
A hibák, amelyek évekig életben maradnak
Gyors hash salttal. A SHA-256 salttal felelősségteljesnek látszik, de nem az. A sebesség maga a sebezhetőség.
Titkosítás hashelés helyett. A titkosítás tervezésénél fogva visszafordítható, tehát létezik hozzá kulcs, és aki megszerzi, minden jelszót nyílt szövegben megkap. A jelszó soha nem lehet visszaállítható, csak ellenőrizhető.
Egyszer beállított és soha nem emelt work factor. Egy 2015-ben választott bcrypt költségérték a 2026-os hardver ellen lényegesen gyengébb. Emeld meg a következő sikeres bejelentkezéskor, amikor egy pillanatra a kezedben van a nyílt szöveg, és újra tudsz hashelni.
Csonkolás vagy karakterkorlátozás. A nagyjából 64 karakter alatti maximális hossz vagy bizonyos karakterek tiltása általában azt jelzi, hogy a jelszót olyan módon tárolják, amelynek számít a tartalma. Pedig nem szabadna számítania, hiszen amúgy is hasheled.
Időzítést kiszivárogtató összehasonlítás. Az ellenőrzésnek állandó idejű összehasonlítást kell használnia. A szabványos könyvtárak függvényei ilyenek, a kézzel írt egyenlőségvizsgálatok nem.
A jelszó naplózása. Bekerül egy hibanaplóba, egy kéréskövetésbe vagy egy monitorozó rendszerbe, és onnantól három olyan helyen van jelen, amelyek hozzáférés-védelme gyengébb az adatbázisénál.
Meglévő rendszer migrálása
Nem tudod újrahashelni azt, ami nincs meg, hiszen csak hash értékeket tartasz. A járható út az, hogy bejelentkezéskor frissítesz.
Amikor egy felhasználó sikeresen hitelesíti magát, a nyílt szövegű jelszava egy pillanatra a memóriában van. Ellenőrizd a régi hash ellen, majd azonnal számíts újat az aktuális algoritmussal, és cseréld le a tárolt értéket. Néhány hónap alatt a legtöbb aktív fiók átvándorol anélkül, hogy a felhasználó bármit észlelne belőle.
Rekordonként tartsd nyilván az algoritmust, hogy a kettő egymás mellett létezhessen, és tűzz ki egy dátumot, amely után a megmaradt régi hash értékek érvénytelenné válnak, az érintett felhasználóknak pedig jelszót kell állítaniuk. A gyenge hash értékkel álló, alvó fiókok pontosan azok, amelyeket a támadó keres.
Ne csomagold be a régi hash értéket az új algoritmusba rövidítésként. Működik, viszont a gyenge hash marad a tényleges biztonsági határ, miközben minden modernnek látszik.
Ami többet számít az algoritmusnál
A helyes hashelés akkor véd meg, amikor az adatbázis kiszivárog. A gyakoribb támadás ellen semmit nem tesz, vagyis az ellen, hogy valaki máshonnan szerzett valódi jelszóval jelentkezzen be.
A bejelentkezés sebességkorlátozása, a többfaktoros hitelesítés elérhetősége, az új jelszavak ellenőrzése ismert kiszivárgott listákon, valamint a credential stuffing mintázataira adott riasztás mind ezt a kérdést kezeli, és a mindennapokban mind többet számít, mint az Argon2id és a bcrypt közötti választás. Az API-biztonság kontrolljai ugyanebbe a problémacsaládba tartoznak.
Mindkettőt érdemes megcsinálni, és a sorrendről érdemes őszintén beszélni: a hashelést egyszer tedd rendbe, mert olcsó és tartós, utána pedig a folyamatos energiát a bejelentkezési útvonalra fordítsd, mert a támadások valójában ott érkeznek. A Mecanik mindkettőt átvizsgálja az alkalmazásbiztonsági elemzés keretében.
Gyakran ismételt kérdések
Melyik a legjobb jelszó-hash algoritmus 2026-ban? Az Argon2id, legalább 19 MiB memóriával, 2 iterációval és 1 fokú párhuzamossággal. Ha nem érhető el, a scrypt N=2^17, r=8, p=1 beállítással alternatíva, a bcrypt 10 vagy nagyobb work factor mellett örökölt rendszerekhez való, a PBKDF2-HMAC-SHA256 pedig 600 000 iterációval lefedi a FIPS-140 követelményeket.
Elég a jelszavakat saltolni? Nem. A salt biztosítja, hogy azonos jelszavak eltérő hash értéket adjanak, érvényteleníti a szivárványtáblákat, és megakadályozza, hogy egyetlen feltört jelszó minden azt használó fiókot megnyisson. A támadót nem lassítja le, mert a saltoknak olvashatónak kell lenniük a bejelentkezések ellenőrzéséhez. A lassúságnak szándékosan memóriaigényes algoritmusból kell jönnie.
Miért ne használjunk SHA-256-ot jelszavakhoz? Mert a sebessége tervezési cél, és éppen a sebesség az, amit meg akarsz tagadni az adatbázisodat birtokló támadótól. Egy általános célú hash nem jelszó-hash, függetlenül attól, hányszor alkalmazzák, és attól is, hogy saltolják-e.
Van a bcryptnek jelszóhossz-korlátja? Igen, 72 byte, és minden, ami ezen túl van, csendben csonkolódik, nem pedig visszautasításra kerül. Ez akkor számít, ha hosszú jelmondatokat fogadsz el, vagy ha a bemenetet a bcryptnek átadás előtt lehasheled, mert a csonkolás minden hibajelzés nélkül történik meg.
Hogyan frissítsem a jelszó-hasheket a felhasználók jelszava nélkül? Bejelentkezéskor. Amikor a felhasználó hitelesíti magát, egy pillanatra nálad van a nyílt szövege, tehát ellenőrizd a régi hash ellen, és azonnal hashelj újra az aktuális algoritmussal. Rekordonként tartsd nyilván az algoritmust, hogy a kettő együtt létezhessen, és tűzz ki egy dátumot, amely után a megmaradt régi hash értékek érvénytelenné válnak, az érintett felhasználóknak pedig jelszót kell állítaniuk.
Hozzászólások