Zmiana hasła z szyfrowanego na Hashowany

Znajduję zaskakująco mało informacji na temat konwersji istniejącej bazy danych z zaszyfrowanych haseł na hasła zaszyfrowane. (Udało mi się znaleźć trochę więcej informacji na temat konwersji w inny sposób, ale nie było to zbyt pomocne.)

Jak większość ludzi wie, zmiana ustawienia passwordFormat w sieci.config dotyczy tylko nowych użytkowników. Mam bazę danych z kilkuset użytkowników i chciałbym przekonwertować ich do korzystania z hashowanych haseł bez zmiany tych istniejących haseł.

Czy ktoś czy ktoś wie, jak można do tego podejść? Dzięki za wskazówki.

Author: Jonathan Wood, 2011-02-09

4 answers

To jest podejście, które chciałbym zacząć, aby zobaczyć, jak daleko mam:

  1. utwórz dwa Membershipprovidery w mojej sieci.config, Jeden dla zaszyfrowanych haseł i jeden dla zaszyfrowanych.
  2. przeprowadź pętlę przez wszystkich użytkowników za pomocą zaszyfrowanego dostawcy haseł. (SqlMembershipProvider.GetAllUsers )
  3. Pobierz hasło użytkownika za pomocą zaszyfrowanego dostawcy haseł. (MembershipUser.GetPassword)
  4. Zmień hasło użytkownika na to samo hasło za pomocą dostawcy hashowanego hasła. (MembershipUser.ChangePassword )

Więc byłoby coś takiego:

    <membership defaultProvider="HashedProvider">
        <providers>
            <clear />
            <add name="HashedProvider" connectionStringName="MembershipConnectionString" enablePasswordRetrieval="false"  requiresQuestionAndAnswer="false" applicationName="MyApp" passwordFormat="Hashed"  type="System.Web.Security.SqlMembershipProvider" />
            <add name="EncryptedProvider" connectionStringName="MembershipConnectionString" enablePasswordRetrieval="true" requiresQuestionAndAnswer="false" applicationName="MyApp" passwordFormat="Encrypted" type="System.Web.Security.SqlMembershipProvider" />
        </providers>
    </membership>

Kod:

SqlMembershipProvider hashedProvider = (SqlMembershipProvider)Membership.Providers["HashedProvider"];
SqlMembershipProvider encryptedProvider = (SqlMembershipProvider)Membership.Providers["EncryptedProvider"];

int unimportant;
foreach (MembershipUser user in encryptedProvider.GetAllUsers(0, Int32.MaxValue, out unimportant ))
{
    hashedProvider.ChangePassword(user.UserName, user.GetPassword(), user.GetPassword());
}
 12
Author: Greg,
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
2011-02-10 15:52:33

Rozwiązanie Grega to dobry początek, ale nie wpłynie na istniejących użytkowników. SqlMembershipProvider chroni istniejących użytkowników i hasła, przechowując w tabeli PasswordFormat (0=Wyczyść, 1=zaszyfrowany, 2=zaszyfrowany) wraz z hasłami. Zmiana formatu hasła dostawcy dotyczy tylko wstawiania do tabel użytkowników. Aby przekonwertować hasła istniejących użytkowników na Hashowane, musisz zmienić parametr PasswordFormat dla każdego wpisu. Oto prosty sposób na to:

void HashAllPasswords()
{
    var clearProvider = Membership.Providers["SqlProvider_Clear"];
    var hashedProvider = Membership.Providers["SqlProvider_Hashed"];
    int dontCare;
    if (clearProvider == null || hashedProvider == null) return;
    var passwords = clearProvider.GetAllUsers(0, int.MaxValue, out dontCare)
        .Cast<MembershipUser>().ToDictionary(u => u.UserName, u => u.GetPassword());

    using (var conn = new SqlConnection(
           ConfigurationManager.ConnectionStrings[0].ConnectionString))
    {
        conn.Open();
        using (var cmd = new SqlCommand(
               "UPDATE [aspnet_Membership] SET [PasswordFormat]=1", conn))
            cmd.ExecuteNonQuery();
    }

    foreach (var entry in passwords)
    {
        var resetPassword = hashedProvider.ResetPassword(entry.Key, null);
        hashedProvider.ChangePassword(entry.Key, resetPassword, entry.Value);
    }
}
 13
Author: Dan Walton,
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-03-15 04:20:48

Ze względów bezpieczeństwa zdecydowanie właściwą decyzją jest przejście z zaszyfrowanych haseł na skróty w bazie danych.

Ogólnie rzecz biorąc, aby utworzyć hasze z istniejących zaszyfrowanych haseł, należy najpierw odszyfrować je, a następnie je zaszyfrować. Pamiętaj, że stracisz (gdy w końcu przełączysz) oryginalne hasła. Zamiast tego będziesz miał unikalny odcisk palca (hash) haseł użytkowników.

Pomyśl także o używanie soli do hashowania (obrona przed tęczowymi tablicami itp.), a także zajrzyj do algorytmów slow hashujących, takich jak BCrypt (Codeplex & Artykuł: Jak bezpiecznie przechowywać hasło ) ze względów bezpieczeństwa zamiast szybkich jak MD5 .

Należy również pamiętać, że w przyszłości zmiana algorytmu hashującego będzie o wiele trudniejsza niż zmiana go z szyfrowania na hash. Więc chcesz zrobić to dobrze za pierwszym razem;)

 2
Author: Martin Buberl,
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
2011-02-09 18:41:19

Ostrzegałbym Cię przed przypadkowym haszowaniem haseł, ponieważ istnieje wiele zastrzeżeń do tego podejścia. Ten wpis na blogu o hasaniu haseł był dla mnie bardzo wnikliwy i myślę, że powinieneś go przeczytać. Dlaczego chcesz hashowane hasła zamiast zaszyfrowane?

 1
Author: Jeffrey Greenham,
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
2011-02-09 18:24:23