Właśnie przeglądałem jeden z artykułów DavidaHaydena na temat Hashing User Passwords .
Naprawdę nie mogę dostać tego, co on chce osiągnąć.
Oto jego kod:
private static string CreateSalt(int size)
{
//Generate a cryptographic random number.
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
byte[] buff = new byte[size];
rng.GetBytes(buff);
// Return a Base64 string representation of the random number.
return Convert.ToBase64String(buff);
}
private static string CreatePasswordHash(string pwd, string salt)
{
string saltAndPwd = String.Concat(pwd, salt);
string hashedPwd =
FormsAuthentication.HashPasswordForStoringInConfigFile(
saltAndPwd, "sha1");
return hashedPwd;
}
Czy istnieje inna metoda C # do mieszania haseł i dodawania do nich soli?
SHA1
nie jest klasy kryptograficznej, więc powinieneś przynajmniej użyćSHA256
, która wyprowadza 256 bitów lub 32 bajty. ALE 256 bitów NIE można łatwo przekonwertować na bazę 64, ponieważ każdy znak base64 koduje 6 bitów, a 256 nie można podzielić w całości przez 6. Zatem potrzebujesz wspólnego mianownika 6 (dla base64) i 8 (dla bitów w bajcie) ponad 256 bitów, co oznacza 264 bitów lub 33 bajty. TLDR: Użyj 33.Odpowiedzi:
W rzeczywistości jest to trochę dziwne, z konwersjami ciągów - które dostawca członkostwa robi, aby umieścić je w plikach konfiguracyjnych. Skróty i sole są binarnymi blokami BLOB, nie trzeba konwertować ich na ciągi, chyba że chcesz umieścić je w plikach tekstowych.
W mojej książce „ Beginning ASP.NET Security” (och, wreszcie pretekst do zepsucia książki) wykonuję następujące czynności
Wytwarzanie soli jest przykładem tego pytania. Możesz przekonwertować tekst na tablice bajtów za pomocą
Encoding.UTF8.GetBytes(string)
. Jeśli musisz przekonwertować skrót na jego ciąg znaków, możesz go użyćConvert.ToBase64String
iConvert.FromBase64String
przekonwertować z powrotem.Należy zauważyć, że nie można używać operatora równości na tablicach bajtów, sprawdza on referencje, dlatego należy po prostu zapętlić obie tablice sprawdzając każdy bajt w ten sposób
Zawsze używaj nowej soli na hasło. Sole nie muszą być trzymane w tajemnicy i mogą być przechowywane obok samego skrótu.
źródło
return array1.Length == array2.Length && !array1.Where((t, i) => t != array2[i]).Any();
Co powiedział cios, ale z nieco mniejszym kodem. Użyj Linq lub
CopyTo
do łączenia tablic.Linq ma również łatwy sposób na porównanie tablic bajtów.
Zanim jednak wdrożysz którykolwiek z tych elementów, sprawdź ten post . W przypadku mieszania haseł może być potrzebny powolny algorytm mieszania, a nie szybki.
W tym celu istnieje
Rfc2898DeriveBytes
klasa, która jest powolna (i może być spowolniona) i może odpowiedzieć na drugą część pierwotnego pytania, ponieważ może wziąć hasło i sól i zwrócić skrót. Zobacz to pytanie, aby uzyskać więcej informacji. Uwaga: Stack Exchange używaRfc2898DeriveBytes
do mieszania haseł ( tutaj kod źródłowy ).źródło
Czytałem, że funkcje mieszające, takie jak SHA256, nie były tak naprawdę przeznaczone do przechowywania haseł: https://patrickmn.com/security/storing-passwords-securely/#notpasswordhashes
Zamiast tego działały funkcje adaptacyjnego pozyskiwania kluczy, takie jak PBKDF2, bcrypt lub scrypt. Oto PBKDF2, który Microsoft napisał dla PasswordHasher w swojej bibliotece Microsoft.AspNet.Identity:
Uwaga: wymaga to zainstalowanego pakietu Microsoft.AspNetCore.Cryptography.KeyDerivation , który wymaga .NET Standard 2.0 (.NET 4.6.1 lub nowszy). W przypadku wcześniejszych wersji .NET zobacz klasę Crypto z biblioteki System.Web.Helpers Microsoftu.
Aktualizacja z listopada 2015 r.
Zaktualizowana odpowiedź w celu użycia implementacji z innej biblioteki Microsoft, która używa mieszania PBKDF2-HMAC-SHA256 zamiast PBKDF2-HMAC-SHA1 (uwaga: PBKDF2-HMAC-SHA1 jest nadal bezpieczny, jeśli iterCount jest wystarczająco wysoki). Możesz sprawdzić źródło, z którego został skopiowany uproszczony kod, ponieważ faktycznie obsługuje sprawdzanie poprawności i aktualizację skrótów zaimplementowanych z poprzedniej odpowiedzi, przydatne, jeśli chcesz zwiększyć iterCount w przyszłości.
źródło
PBKDF2SubkeyLength
do 20 bajtów. To naturalny rozmiar SHA1, a zwiększenie go poza to spowalnia obrońcę bez spowalniania atakującego. 2) Polecam zwiększenie liczby iteracji. Polecam od 10 do 100 000 w zależności od budżetu na wydajność. 3) Ciągłe porównywanie czasu również nie zaszkodzi, ale nie ma większego praktycznego wpływu.Sól służy do dodawania dodatkowego stopnia złożoności skrótu, aby utrudnić pękanie metodą brute-force.
Z artykułu na temat Sitepoint :
Żadna metoda nie robi tego automatycznie w .NET, więc skorzystasz z powyższego rozwiązania.
źródło
Utworzyłem klasę, która ma następującą metodę:
Zatwierdź dane wejściowe
`
źródło
Bah, to jest lepsze! http://sourceforge.net/projects/pwdtknet/ i jest to lepsze, ponieważ ..... wykonuje Key Stretching ORAZ używa HMACSHA512 :)
źródło
Zrobiłem bibliotekę SimpleHashing.Net, aby ułatwić haszowanie za pomocą podstawowych klas dostarczonych przez Microsoft. Zwykłe SHA nie wystarcza do bezpiecznego przechowywania haseł.
Biblioteka korzysta z pomysłu formatu skrótu z Bcrypt, ale ponieważ nie ma oficjalnej implementacji MS, wolę używać tego, co jest dostępne w ramach (tj. PBKDF2), ale jest to trochę zbyt trudne po wyjęciu z pudełka.
To jest szybki przykład korzystania z biblioteki:
źródło
Tak to robię. Tworzę skrót i przechowuję go za pomocą
ProtectedData
interfejsu API:źródło
Czytam wszystkie odpowiedzi i myślę, że wystarczy, szczególnie artykuły @Michael z powolnym haszowaniem i dobre komentarze @CodesInChaos , ale postanowiłem udostępnić mój fragment kodu do haszowania / sprawdzania poprawności, które mogą być przydatne i nie wymagają [ Microsoft.AspNet.Cryptography .KeyDerivation ].
Proszę zwrócić uwagę na funkcję SlowEquals, która jest tak ważna. Wreszcie, mam nadzieję, że ta pomoc i proszę nie wahaj się doradzić mi o lepszych podejściach.
źródło
Użyj
System.Web.Helpers.Crypto
pakietu NuGet firmy Microsoft. Automatycznie dodaje sól do mieszania.Masz hash takie jak to:
var hash = Crypto.HashPassword("foo");
Weryfikujesz hasło w ten sposób:
var verified = Crypto.VerifyHashedPassword(hash, "foo");
źródło
Jeśli nie używasz rdzenia asp.net lub .net, istnieje również prosty sposób w projektach> = .Net Standard 2.0.
Najpierw możesz ustawić żądany rozmiar skrótu, soli i numeru iteracji, który jest związany z czasem trwania generowania skrótu:
Aby wygenerować skrót hasła i sól, możesz użyć czegoś takiego:
Aby sprawdzić, czy hasło wprowadzone przez użytkownika jest prawidłowe, możesz sprawdzić wartości w bazie danych:
Poniższy test jednostkowy pokazuje użycie:
Microsoft Rfc2898DeriveBytes Source
źródło
W odpowiedzi na tę część pierwotnego pytania „Czy istnieje inna metoda C # do mieszania haseł” Można to osiągnąć za pomocą ASP.NET Identity v3.0 https://www.nuget.org/packages/Microsoft.AspNet.Identity. EntityFramework / 3.0.0-rc1-final
źródło
źródło
źródło