Bezpieczne mieszanie haseł za pomocą bcrypt

Programowanie

Mieszanie haseł za pomocą klasycznych algorytmów jak MD5, SHA1 czy SHA256 nie jest aktualnie zalecane, a przede wszystkim bezpieczne. Nie zostały do tego stworzone mimo ich powszechnego stosowania jeszcze jakiś czas temu (niestety nadal często spotyka się taką praktykę)


Zacznijmy od tego, iż mieszanie haseł za pomocą klasycznych algorytmów jak MD5, SHA1 czy SHA256 nie jest aktualnie zalecane, a przede wszystkim bezpieczne. Nie zostały do tego stworzone mimo ich powszechnego stosowania jeszcze jakiś czas temu (niestety nadal często spotyka się taką praktykę).

Algorytmy te zostały stworzone w celu obliczania skrótu dużej ilości danych przy zachowaniu wysokiej jego jakości, a więc dla zapewnienia integralności danych. Ich kluczową wadą jest niestety paradoksalnie szybkość generowania takiego skrótu, co można wykorzystać do automatyzacji łamania haseł nimi zahaszowanych.

Framework Play! niestety nie posiada wbudowanych mechanizmów do mieszania wrażliwych danych, a pakiet Apache Commons z klasą DigestUtils (org.apache.commons.codec.digest.DigestUtils) nie rozwiązuje sprawy. Na szczęście mamy na to remedium w postaci funkcji uzyskiwania klucza bcrypt.

Funkcja ta została zaprojektowana przez Niels Provos i David Mazières, bazuje na szyfrze Blowfish oraz wprowadza sól w celu ochrony przez tęczowymi tablicami i atakami typu brute-force z rosnącą mocą obliczeniową. Jest funkcją adaptacyjną gdzie mamy wpływ na czas i liczbę iteracji, a więc można wpłynąć na jakość końcowego rezultatu przez "spowolnienie" funkcji na szybszej maszynie uzyskując tym samym wysoko jakościowy rezultat.

Przykładowo wygenerowanie skrótu dziesięcioznakowego ciągu znaków 100 razy przez algorytm MD5 zajmuje około 10 ms, natomiast używając bcrypt ok. 1000 więcej. O ile mamy tutaj koszt czasowy, w dziedzinie bezpieczeństwa składowania danych rezultat jest bezcenny i stanowi koszmar dla potencjalnego agresora.


Wszystko co musisz zrobić, aby skorzystać z dobrodziejstw algorytmu bcrypt to dodać zależność z repozytorium maven do pliku build.sbt w postaci:

libraryDependencies = Seq(
      javaJdbc,
      javaEbean,
      cache,
      javaWs,
      "org.mindrot" % "jbcrypt" % "0.3m"
)

Mieszamy np. hasła za pomocą:

String passwordHash = BCrypt.hashpw(password, BCrypt.gensalt());

Sprawdzenie poprawności:

if (BCrypt.checkpw(password, passwordHash)) {
     // password OK
}
Opublikowano Kwiecień 2015