Hash hasło w C#? Bcrypt/PBKDF2

Szukałem msdn i innych zasobów, jak to zrobić, ale nie znalazłem jasnych rozwiązań. To jest najlepsze, co znalazłem.http://blogs.msdn.com/b/shawnfa/archive/2004/04/14/generating-a-key-from-a-password.aspx?Redirected=true

Chciałbym hashować hasła w C# używając bcrypt lub PBKDF2(który wydaje się być związany z bcrypt). Lubię eksperymentować z tym, ile rund zajmuje mój komputer, aby hashować hasło. Jednak wszystko wydaje się być o szyfrowanie podczas gdy wszyscy mówią o haszowaniu. Nie mogę tego rozgryźć. Jak hashować hasło? Wygląda bardziej jak PBKDF2 (Rfc2898?) jest generatorem liczb losowych i używam GetBytes (amount), aby wybrać, jak duży jest mój rozmiar hasha.

Jestem zdezorientowany. Jak dokładnie hashować hasło za pomocą bcrypt/PBKDF?

Author: TrueWill, 2012-07-10

7 answers

PBKDF2

Byłeś naprawdę blisko. Podany link pokazuje, jak można wywołać funkcję Rfc2898DeriveBytes , Aby uzyskać wyniki skrótu PBKDF2. Jednak zniechęcił Cię fakt, że w przykładzie użyto klucza pochodnego do celów szyfrowania (pierwotna motywacja dla PBKDF1 i 2 polegała na tworzeniu funkcji pochodnych "klucza" odpowiednich do użycia jako kluczy szyfrowania). Oczywiście nie chcemy używać wyjścia do szyfrowania, ale jako hash na jego własne.

Możesz spróbować SimpleCrypto.Net biblioteka napisana dokładnie w tym celu, jeśli chcesz PBKDF2. Jeśli spojrzysz na implementację , zobaczysz, że w rzeczywistości jest to tylko cienka owijka (zgadłeś) Rfc2898DeriveBytes .

BCrypt

Możesz wypróbować implementację C# o nazwie (co jeszcze) BCrypt.NET Jeśli chcesz poeksperymentować z tym wariantem.

Zastrzeżenie: nie używałem ani nie testowałem żadnego z biblioteki, z którymi się połączyłem... YMMV

 31
Author: paracycle,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-09 21:30:38

Zajęło mi wieki (dni zajęło mi) znalezienie kodu, aby hashowane hasła działały!! więc położyłem go tutaj dla wygody.

Musisz przeczytać dokumentację i teoretyczną1 theory2 i wtedy niektóre lub możesz być otwarty na luki bezpieczeństwa. Bezpieczeństwo to bardzo ważny temat! KUPUJĄCY UWAŻAJ!

Dodaj pakiet NuGet BCrypt.Net do rozwiązania

const int WorkFactor = 14;
var HashedPassword = BCrypt.Net.BCrypt.HashPassword(Password, WorkFactor); 

Należy dostosować WorkFactor do tego, co jest właściwe patrz dyskusje . Its a Log2 function

"liczba jest log2, więc za każdym razem, gdy komputer podwoi prędkość, dodaj 1 do domyślnej liczby."

Następnie przechowujesz hashowane hasło w db jako passwordFromLocalDB i testujesz przychodzące password w następujący sposób:

if (BCrypt.Net.BCrypt.Verify(password, passwordFromLocalDB) == true)
Powodzenia!
 7
Author: JPK,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:10:36

Na początku tego roku przyglądałem się temu samemu tworzeniu hashów dla naszych ASP.NET Web Forms project, chciałem zrobić to tak samo jak projekty MVC robią to po wyjęciu z pudełka.

Natknąłem się na to pytanie = > ASP.NET Identity default Password Hasher, jak to działa i czy jest bezpieczny? Następnie znalazłem źródło z metodą ByteArraysEqual tutaj => http://www.symbolsource.org/MyGet/Metadata/aspnetwebstacknightly/Project/Microsoft.AspNet.Identity.Core/2.0.0-rtm-140327/Release/Default/Microsoft.AspNet.Identity.Core/Microsoft.AspNet.Identity.Core/Crypto.cs?ImageName=Microsoft.AspNet.Identity.Core

 2
Author: Luke T O'Brien,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:26:17

Dla PBKDF2 może być możliwe użycie systemu.Ochrona.Kryptografia.Rfc2898DeriveBytes.

Zobacz MSDN tutaj: http://msdn.microsoft.com/en-us/library/system.security.cryptography.rfc2898derivebytes.aspx

 1
Author: Jay S,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-07-10 12:23:23

PBKDF2 używa HMACSHA1, jeśli chcesz bardziej nowoczesne i konfigurowalne rozwiązanie powinieneś spojrzeć na ten API za pomocą HMACSHA256 lub 512 z rozciąganiem klucza, tak jak PBKDF2

Https://sourceforge.net/projects/pwdtknet/

Przykładowe GUI zawarte w kodzie źródłowym pokazały, jak uzyskać hash z hasła, w tym tworzenie Crypto random salt.....enjoy :)

 1
Author: thashiznets,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-04 03:45:12

PBKDF2

W przykładzie w http://msdn.microsoft.com/en-us/library/system.security.cryptography.rfc2898derivebytes.aspx, Gdy dojdziesz do linii "Rfc2898DeriveBytes k1 = new Rfc2898DeriveBytes (pwd1, salt1, moje);", k1 to hash. Powodem, dla którego przykładem jest szyfrowanie, jest to, że Rfc2898DeriveBytes został pierwotnie zaprojektowany do tworzenia kluczy szyfrowania.

Jeśli nie podasz salt, Rfc2898DeriveBytes utworzy swój własny, ale nie wiem, czy RNGCryptoServiceProvider lepiej radzi sobie z losowością kryptograficzną.

Według OWASP ( https://www.owasp.org/index.php/Using_Rfc2898DeriveBytes_for_PBKDF2 ), podstawowe użycie SHA1 przez Rfc2898DeriveBytes oznacza, że jest dobre tylko dla hashów o długości do 160 bitów. Jeśli utworzysz dłuższy hash, atakujący nadal musi martwić się tylko o pierwsze 160 bitów, ale sprawiłeś, że hashowanie/uwierzytelnianie haseł jest droższe dla siebie bez żadnych korzyści.

Oto przykładowy kod do hashowania hasła Rfc2898DeriveBytes (przechowuj hash, salt i iteracje w DB):

public class Rfc2898PasswordEncoder
{
    private int _byteLength = 160 / 8; // 160 bit hash length

    public class EncodedPassword
    {
        public byte[] Hash { get; set; }
        public byte[] Salt { get; set; }
        public int Iterations { get; set; }
    }

    public EncodedPassword EncodePassword(string password, int iterations)
    {
        var populatedPassword = new EncodedPassword
        {
            Salt = CreateSalt(),
            Iterations = iterations
        };

        // Add Hash
        populatedPassword.Hash = CreateHash(password, populatedPassword.Salt, iterations);

        return populatedPassword;
    }

    public bool ValidatePassword(string password, EncodedPassword encodedPassword)
    {
        // Create Hash
        var testHash = CreateHash(password, encodedPassword.Salt, encodedPassword.Iterations);

        return testHash == encodedPassword.Hash;
    }

    public byte[] CreateSalt()
    {
        var salt = new byte[_byteLength]; // Salt should be same length as hash

        using (var saltGenerator = new RNGCryptoServiceProvider())
        {
            saltGenerator.GetBytes(salt);
        }

        return salt;
    }

    private byte[] CreateHash(string password, byte[] salt, long iterations)
    {
        byte[] hash;
        using (var hashGenerator = new Rfc2898DeriveBytes(password, salt, (int)iterations))
        {
            hash = hashGenerator.GetBytes(_byteLength);
        }

        return hash;
    }
} 
 0
Author: Phil,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-27 10:13:55

Interesowała mnie odpowiedź, która nie dotyczyła żadnych bibliotek.

Przeczytałem ten artykuł https://crackstation.net/hashing-security.htm które łączy implementację w różnych językach C# wśród nich, które również tutaj linkuję

Https://github.com/defuse/password-hashing/blob/master/PasswordStorage.cs

Co ciekawe, używa Rfc2898DeriveBytes, jak wspomniano kilka razy tutaj.

private static byte[] PBKDF2(string password, byte[] salt, int iterations, int outputBytes){
    using (var pbkdf2 = new Rfc2898DeriveBytes(password, salt)) {
        pbkdf2.IterationCount = iterations;
        return pbkdf2.GetBytes(outputBytes);
    }
}
 0
Author: CyberFox,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-23 03:14:46