KDF
| Po angielsku | key derivation function (KDF) |
|---|---|
| Którą formą pisać | po angielsku Polski odpowiednik istnieje, ale w praktyce nikt tak nie pisze. Zostaw angielski, polski trzymaj jako synonim. |
| Inne formy | funkcja wyprowadzania klucza · funkcja derywacji klucza |
| Kategoria | Kryptografia, tożsamość i uwierzytelnianie |
KDF (key derivation function), po polsku funkcja wyprowadzania klucza, to funkcja, która z hasła albo innego sekretu tworzy klucz kryptograficzny o wymaganej długości. NIST w publikacji SP 800-132 opisuje techniki wyprowadzania kluczy głównych z haseł i fraz w celu ochrony przechowywanych danych [1]. KDF dzieli się na dwie grupy o przeciwnych celach. Warianty hasłowe, takie jak PBKDF2, scrypt i Argon2, są celowo kosztowne, żeby spowolnić zgadywanie haseł. Warianty niehasłowe, jak HKDF, są szybkie i służą do uzyskania dobrego materiału klucza z sekretu, który już ma wysoką entropię.
Jak działa
KDF hasłowy przyjmuje hasło, sól i parametry kosztu. W PBKDF2 według RFC 8018 wejściem są hasło, sól, liczba iteracji i żądana długość klucza, a obliczenia opierają się na funkcji pseudolosowej, zwykle HMAC [2]. Każda próba odgadnięcia hasła wymaga powtórzenia całej pracy, więc koszt spada na atakującego wielokrotnie, a na serwer tylko raz na logowanie.
Nowsze funkcje zwiększają nie tylko czas, ale i zużycie pamięci. RFC 7914 opisuje scrypt jako funkcję opartą na obliczeniach pamięciożernych, które utrudniają ataki z użyciem specjalizowanego sprzętu [4]. Argon2, opisany w RFC 9106, ma trzy odmiany [5]. Argon2d korzysta z dostępu do pamięci zależnego od danych i jest przeznaczony głównie dla kryptowalut i dowodów pracy, gdzie ataki czasowe bocznym kanałem nie są zagrożeniem [5]. Argon2i ma dostęp do pamięci niezależny od danych i jest preferowany do haszowania haseł [5]. Argon2id łączy oba podejścia: przez pierwszą połowę pierwszego przebiegu działa jak Argon2i, potem jak Argon2d [5]. Każda implementacja musi obsługiwać Argon2id, a pozostałe odmiany są opcjonalne [5].
KDF niehasłowy działa inaczej. HKDF z RFC 5869 składa się z dwóch etapów: ekstrakcji, która skupia entropię materiału wejściowego w klucz pseudolosowy, i ekspansji, która z tego klucza wytwarza dowolną ilość materiału [3]. RFC zaznacza, że etap ekstrakcji może skupić istniejącą entropię, ale nie może jej zwiększyć [3]. Dlatego HKDF nie nadaje się do haseł; do nich autorzy wskazują funkcje z PKCS #5, które celowo spowalniają ataki słownikowe [3].
Weryfikację hasła przy logowaniu z użyciem KDF pokazuje schemat poniżej.
Odmiany
| Funkcja | Rodzaj | Zalecane parametry |
|---|---|---|
| PBKDF2 | iteracyjna [2] | 600 000 iteracji HMAC-SHA256 [6] |
| scrypt | pamięciożerna [4] | N=2^17, r=8, p=1 [6] |
| Argon2id | pamięciożerna [5] | 19 MiB, 2 iteracje, p=1 [6] |
| bcrypt | haszowanie haseł | koszt co najmniej 10, limit 72 bajtów [6] |
| HKDF | szybka, niehasłowa [3] | tylko dla sekretów o wysokiej entropii [3] |
Parametry w tabeli to minimalne zalecenia OWASP, który jako pierwszy wybór wskazuje Argon2id, a bcrypt traktuje jako rozwiązanie dla starszych systemów [6]. RFC 9106 podaje wyższe ustawienia: Argon2id z jedną iteracją, czterema torami i 2 GiB pamięci, a przy mniejszej pamięci trzy iteracje i 64 MiB [5]. Formalnie bcrypt jest funkcją haszowania haseł, a nie KDF, ale w zestawieniach pojawia się w tym samym szeregu. PBKDF2 pozostaje wyborem tam, gdzie wymagana jest zgodność z FIPS-140 [6]. RFC 8018 ze stycznia 2017 roku, obecna wersja PKCS #5, zaleca PBKDF2 w nowych zastosowaniach, a starszy PBKDF1 zostawia tylko dla zgodności [2].
W WordPressie
WordPress przez lata haszował hasła metodą phpass, a od wersji 6.8 używa bcrypt [7]. Zmiana ma zwiększyć koszt obliczeniowy łamania wykradzionego hasha [7]. Ponieważ bcrypt przyjmuje najwyżej 72 bajty, hasło jest najpierw skracane funkcją SHA-384 [7]. Nowe hashe mają prefiks $wp$2y$, a hasła zapisane wcześniej są przeliczane przy pierwszym logowaniu po aktualizacji albo przy zmianie hasła [7].
Algorytm można zmienić filtrem wp_hash_password_algorithm. Komentarz w kodzie wp_hash_password() ostrzega, że jedynym algorytmem gwarantowanym dostępnym w każdej instalacji PHP jest bcrypt, a inny wybór wymaga sprawdzenia serwera, na przykład funkcją password_algos() [8]. Parametry kosztu ustawia filtr wp_hash_password_options [8]. Przykład konfiguracji Argon2id we wtyczce typu mu-plugin:
if ( in_array( 'argon2id', password_algos(), true ) ) {
add_filter( 'wp_hash_password_algorithm', fn() => PASSWORD_ARGON2ID );
}
Hasła aplikacji i klucze resetowania hasła nie korzystają z wolnego KDF; od wersji 6.8 są haszowane szybkim algorytmem BLAKE2b przez bibliotekę Sodium [7]. Jest to uzasadnione, bo są to długie wartości losowe, a nie hasła wymyślane przez ludzi. Wyjątkiem pozostają hasła chroniące pojedyncze wpisy, które według zapowiedzi na razie nadal korzystają z phpass [7].
Znaczenie
KDF hasłowy nie zapobiega kradzieży bazy, ale decyduje o tym, co atakujący może z nią zrobić. Po wycieku danych szybki skrót pozwala sprawdzać ogromne liczby kandydatów na sekundę, a wolna funkcja z solą ogranicza łamanie haseł do słabych haseł. Sól unieważnia tęczowe tablice, koszt spowalnia atak siłowy (brute force), a pamięciożerność ogranicza przewagę kart graficznych i układów specjalizowanych [4]. KDF jest też podstawą szyfrowania opartego na haśle: SP 800-132 dotyczy właśnie kluczy głównych wyprowadzanych z haseł do ochrony przechowywanych danych [1].
Dobre praktyki
- Hasła tylko przez hasłowy KDF albo funkcję haszowania haseł, nigdy przez sam skrót (hash function) [6].
- Parametry kosztu dobrane do sprzętu i okresowo podnoszone; stare hashe przeliczane przy logowaniu, tak jak robi to WordPress [7].
- HKDF i podobne funkcje tylko do sekretów o wysokiej entropii [3].
- Dodatkowy tajny klucz przechowywany poza bazą, czyli pieprz, jako uzupełnienie, nie zamiennik [6].
- NIST zapowiedział rewizję SP 800-132 [1], więc zalecenia warto sprawdzać w aktualnych wersjach dokumentów.
Przypisy
8- [1] NIST SP 800-132: Recommendation for Password-Based Key Derivation, Part 1: Storage Applications · NIST
- [2] RFC 8018: PKCS #5 — Password-Based Cryptography Specification Version 2.1 · IETF
- [3] RFC 5869: HMAC-based Extract-and-Expand Key Derivation Function (HKDF) · IETF
- [4] RFC 7914: The scrypt Password-Based Key Derivation Function · IETF
- [5] RFC 9106: Argon2 Memory-Hard Function for Password Hashing and Proof-of-Work Applications · IRTF
- [6] Password Storage Cheat Sheet · OWASP
- [7] WordPress 6.8 will use bcrypt for password hashing · Make WordPress Core
- [8] wp_hash_password() · WordPress.org