W świecie bezpieczeństwa aplikacji webowych prawidłowe przechowywanie haseł to jeden z kluczowych elementów ochrony danych użytkowników. Choć temat ten może wydawać się trywialny, rzeczywistość pokazuje, że do dziś wiele systemów pada ofiarą włamań właśnie z powodu niewłaściwego przechowywania haseł. W jednym z moich poprzednich wpisów, Bezpieczne przechowywanie haseł – sprawdź, czy robisz to dobrze, omówiłem podstawowe zasady bezpiecznego przechowywania haseł. Dziś chciałbym skupić się na Argon2id – obecnym standardzie w kryptograficznym haszowaniu haseł – i wyjaśnić, dlaczego to właśnie jego powinieneś używać w swoich aplikacjach.
Dlaczego Argon2id?
Argon2id jest obecnie uznawany za najlepszy algorytm haszowania haseł, co potwierdzają liczne badania i rekomendacje, m.in. ze strony OWASP. W 2015 roku Argon2 wygrał prestiżowy konkurs Password Hashing Competition (PHC), a jego wersja „id” łączy najlepsze cechy dwóch podejść: Argon2i (odpornego na ataki typu side-channel) oraz Argon2d (skoncentrowanego na bezpieczeństwie przed atakami GPU). Dzięki temu Argon2id oferuje:
- Odporność na ataki brute-force – dzięki wykorzystaniu dużej ilości pamięci, koszt ataków słownikowych i brute-force znacząco wzrasta.
- Elastyczność konfiguracji – Argon2id pozwala dostosować parametry haszowania, takie jak czas, użycie pamięci i liczba rdzeni, co pozwala zoptymalizować bezpieczeństwo i wydajność w zależności od potrzeb aplikacji.
- Lepszą ochronę przed atakami sprzętowymi – atakujący wykorzystujący GPU lub FPGA do łamania haseł napotykają znaczne trudności z powodu dużego zapotrzebowania na pamięć operacyjną przez Argon2id.
Parametry Argon2id i aktualne rekomendacje
Jednym z największych atutów Argon2id jest możliwość dostosowania parametrów haszowania do dostępnych zasobów systemowych oraz wymagań bezpieczeństwa. Jak wskazuje OWASP Password Storage Cheat Sheet, najważniejsze parametry Argon2id to:
Czas (time cost)
Określa liczbę iteracji haszowania t, co bezpośrednio wpływa na czas potrzebny do wygenerowania skrótu. Wyższa wartość oznacza większe bezpieczeństwo, ale kosztem wydajności.
Pamięć (memory cost)
Parametr m definiuje ilość pamięci (w kilobajtach), jaką algorytm będzie wykorzystywał podczas haszowania. Zalecana wartość zależy od dostępnej pamięci RAM.
Liczba rdzeni (parallelism)
Parametr p określa, ile równoległych wątków może być używanych podczas procesu haszowania.
Rekomendacje OWASP
Rekomendacje są następujące:
- m=47104 (46 MiB), t=1, p=1
- m=19456 (19 MiB), t=2, p=1
- m=12288 (12 MiB), t=3, p=1
- m=9216 (9 MiB), t=4, p=1
- m=7168 (7 MiB), t=5, p=1
Rozmiar soli
Sól (ang. salt) to losowy ciąg znaków, który jest dodawany do każdego hasła przed jego haszowaniem. Jej głównym celem jest uniemożliwienie ataków słownikowych i używania precomputowanych tablic, takich jak tablice tęczowe (rainbow tables).
Rekomendacje OWASP dotyczące soli:
- Długość soli: Minimum 16 bajtów.
- Unikalność: Każde hasło powinno mieć generowaną losową sól, co wyklucza możliwość jej ponownego użycia.
- Przechowywanie: Sól powinna być przechowywana razem z hashem w bazie danych.
Implementacja Argon2id w Spring Security
W przypadku Argon2id nie wystarczy zaimportowanie najnowszej wersji Spring Secutiry (na dzień pisania tego tekstu jest to 6.4.2).
Mimo, że Spring Security dostarcza nam klasy Argon2PasswordEncoder niezbędne jest również dodanie następującej zależności:
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk18on</artifactId>
<version>1.79</version>
</dependency>
Bouncy Castle to biblioteka kryptograficzna w Javie, która wspiera szeroką gamę algorytmów szyfrowania, podpisywania, haszowania oraz innych mechanizmów bezpieczeństwa. W przypadku Argon2id jest ona wykorzystywana do generowania skrótów haseł w sposób zgodny z najnowszymi standardami.
Konfiguracja Argon2PasswordEncoder
Po dodaniu zależności należy skonfigurować PasswordEncoder w aplikacji.
@Configuration
public class SecurityConfiguration {
@Bean
public PasswordEncoder passwordEncoder() {
return Argon2PasswordEncoder.defaultsForSpringSecurity_v5_8();
}
}
Metoda defaultsForSpringSecurity_v5_8() tworzy instancję kodera haseł z domyślnymi ustawieniami zalecanymi przez Spring Security w wersji 6.4.2.
Domyślne parametry
Domyślne wartości parametrów Argon2id w Spring Security to:
- Długość soli (saltLength): 16 bajtów
- Równoległość (parallelism): 1 wątek
- Pamięć (memory): 16 MB (16384 KB)
- Liczba iteracji (iterations): 2
Czy domyślne parametry spełniają wymagania OWASP?
- Pamięć: Domyślne ustawienie Spring Security to 16 MB (16384 KB), co spełnia minimalne wymaganie OWASP dla 2 iteracji, czyli 19456 KB. Jednak lepiej byłoby podnieść ten parametr dla wyższego bezpieczeństwa.
- Iteracje: Domyślna wartość to 2, co jest zgodne z rekomendacjami OWASP.
- Równoległość: Wartość 1 jest wystarczająca i zgodna z OWASP.
Wniosek:
Domyślne parametry są odpowiednie dla aplikacji o umiarkowanym obciążeniu, jednak dla aplikacji o wysokim poziomie bezpieczeństwa zaleca się dostosowanie ustawień, np. zwiększenie pamięci do wartości sugerowanej przez OWASP.