2009-08-31 10 views
17

pracuję na funkcjonalność szyfrowania oparty na klasach odziedziczonych SymmetricAlgorithm takich jak TripleDES, DES itpPasswordDeriveBytes vs Rfc2898DeriveBytes, przestarzały, ale sposób szybciej

Zasadniczo są tam dwie opcje do generowania spójnego klucz i IV do moja klasa algorytmów, PasswordDeriveBytes i Rfc2898DeriveBytes, dziedziczy po klasie abstrakcyjnej DeriveBytes.

Metoda PasswordDeriveBytes.GetBytes() jest oznaczona jako przestarzała w środowisku .NET Framework, podczas gdy zalecana jest Rfc2898DeriveBytes.GetBytes(), ponieważ jest zgodna ze standardem PBKDF2. Jednak na podstawie moich testów wywołanie tej samej metody GetBytes() w klasie Rfc2898DeriveBytes jest prawie 15 razy wolniejsze niż w klasie PasswordDeriveBytes, co prowadzi do nieoczekiwanego użycia procesora (zawsze powyżej 50%).

Here're niektóre dane testowania:

  • Powtórzenia: 100
  • typ Algorytm: DES
  • Oryginalny tekst: "Jestem kluczowym testy, szyfrować mnie proszę"
  • Czas:
    • PasswordDeriveBytes: 99ms
    • Rfc2898DeriveBytes: 1,373ms

Na podstawie testów, złe wykonanie Rfc2898DeriveBytes jest nie do zaakceptowania w środowisku produkcyjnym.

Czy ktoś wcześniej zauważył ten problem? Jakieś rozwiązanie, czy mogę nadal używać standardowego bez uderzania w wydajność? Jakiekolwiek ryzyko użycia przestarzałej metody (może być usunięte w przyszłej wersji)?

Dzięki chłopaki!

Edit:

Prawdopodobnie znalazłem gdzie jest problem ... Domyślna liczba iteracji dla PasswordDeriveBytes liczba wynosi 100, natomiast dla Rfc2898DeriveBytes jest 1000. Po zmieniłem je na ten sam numer jak 1000, realizując Rfc2898DeriveBytes to tylko podwójny czas.

+0

Jak często będziesz uzyskiwania kluczy w środowisku produkcyjnym? A jeśli chodzi o dane dotyczące czasu, kiedy powiedziałeś "100 iteracji" - czy to iteracje na kluczu onee, czy też wygenerowałeś 100 kluczy? Jakiekolwiek perfekcyjne dane oparte na 100 próbach są podejrzane, ale wydaje mi się, że faktycznie testowałeś JEDNĄ próbę. Podobnie jak we wszystkich przypadkach analizy doskonałej, nie jest właściwe wyciąganie wniosków na temat wydajności serwera w oparciu o czas odpowiedzi pojedynczego okresu próbnego. – Cheeso

+0

@Cheeso Test był tylko testem jednostkowym wydajności dla tych dwóch klas i nie został wykonany w prawdziwej aplikacji. "100 iteracji", o których wspomniałem, było trochę mylące, co oznacza, że ​​wykonałem każdy z nich 100 razy. To nie jest prawdziwe testowanie perfekcji, ale tylko porównanie. – tshao

+5

Myślę, że mogłeś przegapić punkt 'Rfc2898DeriveBytes' jest zasadniczo _proigned_, aby był powolny, więc kontrole hash hash (wykonane na log-on, a więc dość rzadko) nie zauważyły ​​wydajności, gdy robią brutalne ataki. Jeśli potrzebujesz generować mnóstwo skrótów 'Rfc2898DeriveBytes' nie jest dla ciebie, ale jeśli potrzebujesz zabezpieczenia przed atakami brutalnej siły, to jest. – Keith

Odpowiedz

25

one nie są tym samym.

Rfc2898DeriveBytes jest implementacją PBKDF2. PasswordDeriveBytes jest implementacją PBKDF1. PBKDF2 generuje inne wyjście, używając innej metody i o wiele większą liczbę rund niż PBKDF1.

Funkcje haszowania haseł, takie jak te, używane do wyprowadzania kluczy, mają być powolne. Właśnie o to chodzi - sprawia, że ​​znacznie trudniej je złamać.

Obie funkcje nie są kompatybilne, a PasswordDeriveBytes nie jest prawie tak bezpieczne.

+0

Dzięki BlackAura. Rozumiem, że implementacja PBKDF2 powinna być powolna, ale czy nie ma najlepszej praktyki używania klasy Rfc2989DeriveBytes, na przykład, jak cache/ponowne użycie tego samego klucza/IV? Uruchomienie metody wielokrotnie wolniej niż w środowisku produkcyjnym jest niedopuszczalne. : P – tshao

+4

Ogólnie rzecz biorąc, chcesz użyć tych funkcji tylko do wygenerowania klucza z hasła. Zwykle dla czegoś takiego jak archiwum chronione hasłem lub podobne. Aby encrpytować archiwum, należy wygenerować losowy IV i wygenerować klucz z hasła i IV. Przechowujesz IV (ale nigdy klucz). Następnie można ponownie użyć klucza dla każdego pliku w archiwum, o ile każdy plik jest zaszyfrowany za pomocą innego kodu IV (również zapisanego w archiwum). Jedynym innym zastosowaniem tych funkcji jest haszowanie hasłem. Zrobiłbyś to raz, kiedy użytkownik się loguje. Do każdego innego zastosowania prawdopodobnie istnieje lepszy sposób. – BlackAura

9

Myślę, że brakuje wam punktu derivebytes. Ma być powolny. Celowo wykorzystuje powolny algorytm, którego nie można przyspieszyć za pomocą sprytnej sztuczki.Typowy parametr "liczba iteracji" powinien znajdować się w zakresie 2^16-2^20 i wprowadzić 0,1-0,5 sekundowe opóźnienie pomiędzy wprowadzeniem hasła i wygenerowaniem klucza. Chodzi o to, aby bronić się przed słabymi hasłami wybranymi przez "leniwych nieuświadomionych użytkowników" i spowolnić poszukiwanie brutalnej siły.

Powiązane problemy