Care este motivul specific pentru a prefera bcrypt sau PBKDF2 față de SHA256-crypt în hașurile de parole? (Securitatea informațiilor, Parole, Hash, Bcrypt)

ilkkachu a intrebat.

Știm că, pentru a încetini spargerea parolelor în cazul unei scurgeri a bazei de date de parole, parolele ar trebui salvate numai în format hașurat. Și nu numai atât, ci hașurate cu o funcție puternică și lentă, cu posibilitatea de a varia numărul de runde.

Adesea, algoritmi precum PBKDF2, , bcrypt și scrypt sunt recomandate pentru acest lucru, bcrypt fiind cel care pare să primească cele mai multe voturi, de exemplu aici, aici și aici.

Dar cum rămâne cu hașurile bazate pe SHA256 și SHA512 implementate cel puțin în glibc (descriere, , specificația) și utilizate în mod implicit cel puțin pe unele distribuții Linux pentru conturile de logare obișnuite? Există vreun motiv pentru a nu le utiliza sau pentru a prefera bcrypt în locul hașurilor bazate pe SHA-2?

Desigur, bcrypt este semnificativ mai vechi (1999) și, prin urmare, mai bine stabilit, dar hash-urile SHA-2 sunt deja vechi de nouă ani (2007), iar scrypt este chiar mai tânăr cu puțin (2009), dar pare să fie menționat mai des. Este doar o practică acceptată sau există un alt motiv?Există vreo slăbiciune cunoscută în hash-urile bazate pe SHA-2 sau a verificat cineva?

Notă: Mă refer în special la hașurile de parole cu mai multe runde descrise în documentele legate și marcate cu codurile $5$ și $6$ în crypt hașuri, nu o singură rundă a funcțiilor de hash SHA256 sau SHA512 simple..

Am văzut că întrebarea aceasta este marcată ca fiind un posibil duplicat al. Răspunsurile de acolo nu au nicio mențiune despre hașurile SHA256-crypt / SHA512-crypt, care este ceea ce caut.

Comentarii

  • Posibil duplicat al Întrebare: Cum să hashăm parolele în siguranță? –  > Por sethmlarson.
  • „Slăbiciunea” hașurilor care nu au runde cu număr semnificativ de runde și nu sunt intensive în memorie este viteza sau ușurința de implementare într-un GPU/ hardware specializat. Ați citit răspunsurile pe care le-ați legat? Sunt mai bune decât orice răspuns pe care ți l-aș putea da eu. –  > Por sethmlarson.
  • @Oasiscircle, ei bine, specificația la care am dat link afirmă „Numărul implicit de runde pentru ambii algoritmi este de 5.000.” și „maxim pentru N = 999.999.999”. Dacă asta nu este suficient de semnificativ în comparație cu bcrypt, aș fi fericit să văd asta ca răspuns. –  > Por ilkkachu.
  • Funcțiile SHA nu sunt intensive în memorie ca Blowfish (cu care este construit bcrypt) și, prin urmare, pot fi mai ușor de paralelizat într-un GPU/ hardware specializat. Acesta este motivul pentru care a avea mai multe runde cu SHA este mult mai puțin semnificativ decât mai multe runde de bcrypt. Notă laterală, nu pot vizualiza documentul dvs. de specificații de unde mă aflu în prezent. –  > Por sethmlarson.
  • @ilkkachu Nu, hashing-ul iterat nu este suficient de bun. Atacatorii pot rula SHA în paralel pe un GPU și pot obține o creștere semnificativă a vitezei. SHA este, de asemenea, utilizat în mineritul de bitcoin, astfel încât există o mulțime de ASIC-uri care îl pot forța brutal. –  > Por Navin.
5 răspunsuri
Thomas Pornin

Principalul motiv pentru a utiliza o funcție de hashing specifică pentru parole este de a face viața mai grea pentru atacatori sau, mai exact, de a-i împiedica să-și facă viața mai ușoară (în comparație cu cea a apărătorului). În special, atacatorul poate dori să calculeze mai multe hash-uri pe secundă (adică să încerce mai multe parole pe secundă) cu un buget dat, folosind un GPU.

SHA-256, în special, beneficiază foarte mult de pe urma implementării pe un GPU. Astfel, dacă folosiți SHA-256-crypt, atacatorii vor fi mai avantajați decât dacă folosiți bcrypt, care este greu de implementat eficient pe un GPU.

Consultați acest răspuns pentru o discuție despre bcrypt vs PBKDF2. Deși SHA-256-crypt nu este PBKDF2, este destul de asemănător în ceea ce privește comportamentul său de performanță pe GPU, astfel încât se aplică aceleași concluzii.

Cazul pentru SHA-512 este puțin mai puțin clar, deoarece GPU-urile existente se descurcă mult mai bine la utilizarea numerelor întregi pe 32 de biți decât pe 64 de biți, iar SHA-512 utilizează în principal operații pe 64 de biți. Este totuși de așteptat ca GPU-urile moderne să permită mai multe hash-uri pe secundă decât procesorul (pentru un buget dat) cu SHA-512-crypt, ceea ce indică din nou bcrypt ca fiind cea mai bună alegere.

Comentarii

  • „Deși SHA-256-crypt nu este PBKDF2, este destul de similar în ceea ce privește comportamentul său de performanță pe GPU, astfel încât se aplică aceleași concluzii.” — exact asta este exact ceea ce căutam. –  > Por ilkkachu.
  • Pentru atacurile brute-force, acest lucru poate fi compensat prin adăugarea unui singur caracter la parolă. Și supercompensată cu două caractere deja. –  > Por neverMind9.
  • Deci, practic, faptul că bcrypt este vechi îl face mai sigur. Nu se aude prea des așa ceva în infosec/tehnologie. –  > Por Hashim Aziz.
700 Software

Familia de hashes SHA-2 a fost concepută pentru a fi rapidă. BCrypt a fost conceput pentru a fi lent. Ambele sunt considerate robuste. Cu destule runde sau factori de lucru, oricare dintre ele poate dura mai mult decât cealaltă, dar eu aș înclina spre cea care a fost proiectat să fie lent. (dacă încărcarea serverului este o problemă, factorul de lucru este reglabil)

În plus, aș înclina spre BCrypt, deoarece este de obicei o implementare compilată (C sau C++).

SHA-ul cu mai multe runde poate fi implementat cu ușurință în limbaj de nivel înalt, cel puțin pentru iterație, dacă nu și pentru hash-ul propriu-zis. Limbajele de nivel înalt sunt mai puțin eficiente pentru operațiile matematice de bază, reducând numărul de runde pe care hardware-ul de producție le poate efectua pe milisecundă.

În timp ce ambii algoritmi pot fi implementați fie în limbaje de nivel înalt, fie în limbaje de nivel scăzut, fie într-un hibrid; în BCrypt opțiunile disponibile dictează că sunteți mai multe șanse de a ajunge la o implementare eficientă. (vă pune pe un teren de joc mai echitabil cu atacatorul).

În ceea ce privește exemplul dvs. specific din /etc/shadow este foarte probabil ca, în ambele cazuri, să fiți doar pe algoritmi de nivel scăzut (eficienți). (SHA sau BCrypt) În acest exemplu, v-aș sugera să consultați documentația sistemului de operare pentru a optimizați rundele (factor de lucru) în funcție de viteza hardware-ului -vs- cât de puternic doriți să fie hash-ul.

scrypt (cu un factor de lucru suficient de mare) are avantajul suplimentar de a avea cerințe suplimentare de RAM/memorie (nu doar CPU), ceea ce îl face mai rezistent la GPU decât SHA, BCrypt sau PBKDF2.

Editare: Mulțumesc lui Thomas pentru că a precizat că BCrypt este mai rezistent la GPU decât SHA-2 și că SHA-2 și PBKDF2 sunt practic echivalente din acest punct de vedere.

Comentarii

  • Trebuie remarcat faptul că scrypt utilizează o cantitate de memorie configurabilă care depinde de cât de repede trebuie să se finalizeze. Dacă utilizați scrypt pe un server de autentificare ocupat și trebuie să calculeze un hash de parolă în mai puțin de 5 ms sau cam așa ceva, atunci scrypt nu poate utiliza multă memorie RAM și se dovedește a fi mai puțin rezistent la GPU decât bcrypt. Scrypt a fost într-adevăr conceput pentru criptarea pe hard disk (deci timp de calcul între 1 și 5 secunde); nu este neapărat adecvat pentru toate celelalte situații. Acesta este de fapt motivul pentru care a fost creat Concursul de hașurare a parolelor. –  > Por Thomas Pornin.
  • Cred că detaliile de implementare sunt o întrebare puțin diferită de cea a meritelor relative ale algoritmilor, iar acestea ar depinde și de sistem. de exemplu, pe OpenBSD ar fi foarte probabil să aveți $2y$ susținută de libc-ul sistemului, dar nu este așa pe toate Linux-urile. În ceea ce privește bibliotecile limbajelor de programare populare, eu sper că că ar avea implementări în C ale orice (parole) hașuri pe care le acceptă, dar nu pot fi sigur fără să verific. –  > Por ilkkachu.
  • O parte din întrebarea dvs. „Există vreun motiv pentru a nu le folosi” se leagă foarte mult de cât de bine a fost implementat. SHA-256 nu a fost conceput pentru a fi un „hash de parolă”, astfel încât bibliotecile specifice limbajului nu pot fi atât de serios constrânse să îl implementeze în C nativ. Acest lucru face, de asemenea, ca instalările să fie mai ușoare pentru anumiți utilizatori care nu au compilatoarele potrivite configurate. De asemenea, este tentant pentru un dezvoltator să își scrie propria iterație pentru runde. Îmi place să includ detalii de implementare într-un răspuns pentru a împiedica viitorii vizitatori să sară la o concluzie. –  > Por 700 Software.
Luis Casillas

Notă: Mă uit la această întrebare după ce a fost făcută această editare și o iau în considerare:

Notă: Mă refer în mod specific la hash-urile de parole cu mai multe runde descrise de documentele legate și marcate cu codurile $5$ și $6$ în crypt hashes, nu la o singură rundă a funcțiilor hash simple SHA256 sau SHA512.


Dacă ne uităm la algoritmul lung, în 22 de pași, din acest link pe care l-ați furnizat, , aș prefera să întorc o întrebare: de ce ați prefera să folosiți acest algoritm în loc de PBKDF2 cu HMAC-SHA2? Pentru că, cel puțin așa cum este prezentat:

  • definiția PBKDF2 pare mult mai simplă. Acest lucru se datorează faptului că este mai modulară – își amână cea mai mare parte a activității către o funcție pseudoaleatoare furnizată din exterior. Aceasta este în mod normal instanțiată cu HMAC, care, la rândul său, transferă cea mai mare parte a activității sale către o funcție hash externă precum SHA-1 sau SHA-2.
  • Aceasta înseamnă că securitatea PBKDF2 ar trebui să fie mai ușor de analizat.

În schimb, algoritmul din documentul pe care îl furnizați enumeră o mulțime de pași a căror motivație este mai greu de înțeles. De exemplu:

11. For each bit of the binary representation of the length of the
    password string up to and including the highest 1-digit, starting
    from to lowest bit position (numeric value 1):

    a) for a 1-digit add digest B to digest A

    b) for a 0-digit add the password string

    NB: this step differs significantly from the MD5 algorithm.  It
    adds more randomness.

Se adaugă mai multă aleator? Cum face acest lucru? De ce există acest pas – SHA-2 nu adaugă suficientă aleatoritate? Dacă SHA-2 nu este suficient de aleatoriu, de ce să fie folosit? Și acest pas nu introduce o ramificare dependentă de secret în algoritm, ceea ce ridică problema unei posibile atacuri de sincronizare împotriva acestuia?

Nu spun nicidecum că algoritmii pe care îi atașați sunt nesiguri. Doar că:

  • Factorul de lucru pe care îl introduc se reduce la același lucru pe care l-ar face PBDKF2–HMAC-SHA2 (un număr mare de iterații SHA2);
  • Ele arată foarte asemănător în linii mari cu ceea ce ai avea dacă ai derula o implementare PBKDF2-HMAC-SHA2, dar cu o complexitate suplimentară al cărei scop nu îl înțeleg;
  • Așadar, cel puțin așa cum sunt prezentate în aceste documente, mi-e mai greu să am încredere în proiectarea lor decât în PBKDF2.

EDIT: După ce am scris toate acestea, m-am dus și am făcut un pic de cercetare în acest algoritm pentru a încerca să îl înțeleg mai bine. În primul rând, din întrebarea proprie „descriere” și „specificații” aflăm că algoritmul a fost derivat dintr-un algoritm mai vechi, bazat pe MD5, prin efectuarea unor modificări relativ minore.

Acest algoritm mai vechi bazat pe MD5 pare cel pe care Poul-Henning Kamp l-a scris pentru FreeBSD-2.0 în 1994., , care pe care nu îl mai consideră sigur. În primul link (în care povestește istoria funcției), el menționează că și glibc a adoptat funcția sa. De asemenea, el face un link către lucrarea din 1999 a lui Provos și Mazières despre bcrypt și menționează că acesta și-a exprimat o anumită dezaprobare și, în mod ciudat au evidențiat același pas care mi-a atras atenția mai sus:

MD5 crypt hașează parola și sarea într-un număr de combinații diferite pentru a încetini viteza de evaluare. Unii pași din algoritm fac să fie îndoielnic faptul că schema a fost concepută din punct de vedere criptografic – de exemplu, reprezentarea binară a lungimii parolei determină la un moment dat ce date sunt hașurate, pentru fiecare bit zero primul octet al parolei și pentru fiecare bit set primul octet al unui calcul hash anterior.

Dar cred că acest lucru explică motivația funcțiilor mai noi despre care întrebați: acestea sunt o modificare foarte minimă a unei funcții mai vechi, care precede majoritatea funcțiilor moderne de hash pentru parole, a cărei concepție a fost pusă sub semnul întrebării, dar probabil că nu este fundamental stricată, ci doar inutil de complexă.

Comentarii

  • M-am întrebat și eu despre structura ușor eh, întortocheată, deși ar trebui să întrebăm autorul despre asta. Vă mulțumesc că ați abordat funcția la care m-am referit, care începe să mi se pară mai necunoscută decât am presupus. După cum am spus, este hash-ul implicit al parolei pentru unele sisteme Linux, așa că nu am ales să o folosesc în sine, dar o face oarecum interesantă pentru a afla mai multe despre ea. (Nota pe care ați citat-o a fost în întrebarea de la început, dintr-un motiv).  > Por ilkkachu.
  • @ilkkachu: Mi-am actualizat răspunsul cu niște materiale suplimentare pe care ar putea fi interesat să le citești. –  > Por Luis Casillas.
Spencer D

Familia SHA-2 în sine nu este neapărat rea. Prin proiectare, nu există cu adevărat defecte de securitate care să facă bcrypt sau scrypt preferabile. Cu toate acestea, problema pe care mulți experți în securitate o au cu SHA este că este prea rapid și nu necesită prea multă memorie. În comparație, o funcție de hashing precum scrypt este mult mai lentă și mai scumpă, ca să spunem așa.

Scrypt necesită o cantitate decentă de memorie pentru a fi calculată. În plus față de toată această memorie, și în mare parte ca urmare a faptului că are nevoie de atât de multă memorie, scrypt necesită mult timp de calcul în comparație cu SHA. Acest răspuns de pe site-ul BitCoin Stack Exchange rezumă destul de bine avantajele lui scrypt: Ce caracteristici ale scrypt() îl fac pe Tenebrix rezistent la GPU? În esență, scrypt este conceput pentru a fi lent și a consuma multă memorie. GPU-urilor nu le place acest lucru. În general, GPU-urile nu au capacitatea de memorie pentru a stoca toată memoria necesară pentru calculul scrypt fără a fi nevoite să recurgă la metode de blocare a execuției (în care GPU blochează toate firele de execuție, deoarece poate prelua valorile din memoria partajată doar una câte una) și, prin urmare, GPU nu pot oferi niciun beneficiu important față de procesoare în ceea ce privește timpul de procesare. Bcrypt este similar.

Bcrypt este încercat și adevărat pentru hashing-ul parolelor. Există de 17 ani și încă își face treaba. Cu toate acestea, într-o zi, tehnologia GPU va avansa până la punctul în care va fi capabilă să calculeze bcrypt mai rapid și mai eficient decât un CPU. Tehnologia evoluează și se dezvoltă mereu, așa că acest lucru se va întâmpla în cele din urmă. Când va veni acea zi, bcrypt nu va mai fi o alegere atât de bună pentru hashing-ul parolelor, iar criptografii și experții în securitate vor trebui să înlocuiască bcrypt cu un algoritm similar care este mai lent și mai consumator de memorie decât bcryptul existent. Poate că acesta va fi scrypt, dar cine poate spune. Așadar, de ce este SHA dezaprobat?

În general, SHA este descurajat nu din cauza unor defecte de securitate, ci din cauza vitezei și a capacității sale de a fi implementat pe un GPU. Cineva cu mașini/puteri de calcul nelimitate ar putea sparge orice tip de algoritm de hashing, fie că este vorba de SHA, bcrypt sau scrypt, dar acest lucru este teoretic. În practică, un atacator nu va avea un număr nelimitat de mașini pe care să încerce să spargă hash-uri și, prin urmare, cu cât puteți încetini mai mult atacatorul, cu atât îi va fi mai dificil să spargă o parolă. Există o limită de buget pentru orice, iar spargerea parolelor nu face excepție. Atacatorul nu poate sparge parolele decât atât de repede cât îi permite bugetul. (Cea mai bună tehnologie pe care o poate achiziționa în limita bugetului, costul de funcționare a acelei tehnologii (de exemplu, costurile cu energia electrică) etc.) Desigur, ați putea implementa mai multe runde de SHA pentru a încetini serios un atacator, dar de ce să nu folosiți doar bcrypt în acel moment? Printre altele, pe măsură ce tehnologia GPU avansează în viitorul apropiat, va trebui să adăugați din ce în ce mai multe runde/iterații la calculele SHA pentru a-l încetini până la punctul în care este mai lent decât bcrypt. Cu toate acestea, pe măsură ce tehnologia GPU avansează, bcrypt va rămâne neafectat, până în punctul în care tehnologia GPU permite calcularea eficientă a bcrypt. Prin urmare, bcrypt este alegerea preferabilă atunci când este posibil, nu pentru că SHA este nesigur, ci pentru că SHA este prea eficient din punct de vedere al calculului.

Comentarii

  • scrypt și sha256crypt sunt lucruri complet separate. –  > Por Stephen Touset.
  • Și sha56crypt și sha256 (iterat) sunt, de asemenea, foarte diferite. sha256crypt, așa cum este folosit de libc, este o mizerie –  > Por eckes.
Serge Ballesta

Ei bine, unul dintre caracteristici a bcrypt este că este un algoritm foarte lent. Această lentoare oferă o securitate suplimentară pentru atacurile de forță brută. Dar, din același motiv, s-ar putea să nu fie cea mai bună soluție, de exemplu, pentru serverele web foarte utilizate, deoarece aici o mașină foarte încărcată va trebui să facă acest calcul greu la fiecare autentificare.

Dar atâta timp cât sistemul poate accepta acest lucru, timpul suplimentar îi deranjează de fapt pe atacatorii prin forță brută.

Comentarii

  • sha256crypt este, de asemenea, un hash lent. –  > Por Stephen Touset.
  • De ce ar concepe cineva un algoritm de cifrare lent (blowfish) – –  > Por eckes.
  • @eckes Programarea cheilor din Blowfish este cea care este lentă, nu restul cifrului. Programul de chei este un cost de configurare unic, care este suportat de fiecare dată când se utilizează o nouă cheie și este echivalent cu aproximativ 521 de criptări. Ceea ce face bcrypt este să extragă acest program de chei și să îl modifice puțin pentru a-l face mai util ca KDF. –  > Por pădure.