2011-02-09 119 views
14

我發現令人驚訝的是,將現有數據庫從加密密碼密碼轉換爲散列密碼的信息很少。 (我能夠找到更多有關轉換另一種方式的信息,但這並沒有多大幫助。)將密碼格式從加密密碼更改爲散列密碼

正如大多數人所知,更改web.config中的passwordFormat設置僅影響新用戶。我有一個數百個用戶的數據庫,我想將它們轉換爲使用哈希密碼而不更改這些現有密碼。

是否有人熟悉如何接近這個?感謝您的任何提示。

回答

12

這是我與我怎麼看遠了啓動方法:

  1. 在我的web.config創建兩個MembershipProviders,一個用於加密密碼和一個用於散列。
  2. 使用加密密碼提供程序遍歷所有用戶。 (SqlMembershipProvider.GetAllUsers
  3. 使用加密密碼提供程序獲取用戶密碼。 (MembershipUser.GetPassword
  4. 使用哈希密碼提供程序將用戶密碼更改爲相同密碼。 (MembershipUser.ChangePassword

所以它會是這樣的:

<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> 

代碼:

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()); 
} 
+1

我正在嘗試將明文密碼更新爲加密密碼。我希望他們哈希,但客戶端沒有。總之,這個解決方案看起來很有前途非常優雅的簡單。希望它有效。 – mikesigs 2011-02-10 15:36:19

1

我會告誡你不要隨意散列你的密碼,因爲這種方法有很多警告。這Blog post about hashing passwords是非常有見識的,我認爲你應該閱讀它。爲什麼你想要散列密碼而不是加密?

+3

感謝您的鏈接,這是一個有趣的閱讀。也就是說,沒有任何方法是100%安全的,哈希密碼是當前密碼存儲的行業標準。爲了方便用戶使用加密密碼(我可以通過電子郵件發送給他們),我建立了自己的網站,但是我收到了抱怨,這給我的用戶帶來了風險,尤其是當他們在多個網站上使用相同的密碼時。 – 2011-02-09 18:41:30

2

出於安全原因,從數據庫中的加密密碼切換到散列絕對是正確的決定。

一般創建哈希出你現有的加密密碼,你應該首先對它們進行解密,然後散列它們。請注意,您將會丟失(當您最終切換時)原始密碼。相反,您將擁有用戶密碼的唯一指紋(散列)。

還考慮使用鹽的散列(防禦rainbow tables等),也有慢的哈希算法出於安全考慮,而不是快速的像MD5一個樣子BCryptCodeplex & Article: How To Safely Store A Password)。

請記住,在未來將切換哈希算法比將其從ecryption更改爲哈希更加費力。所以,你想這樣做正確的第一次;)

+0

是的,我明白什麼是散列密碼,以及如何不能從散列轉換爲原始密碼。而且我知道我需要解密已加密的密碼,然後對它們進行哈希處理。我不知道的是,我可以如何以一種能夠與ASP.NET成員身份協同工作的方式來處理所有記錄。 (順便說一下,ASP.NET成員資格中沒有使用散列密碼的鹽嗎?) – 2011-02-09 18:43:33

+1

ASP.NET成員資格的默認散列算法是SHA1,它們使用編碼爲Base64的salt。 – 2011-02-09 18:48:52

12

格雷格的解決方案是一個良好的開端,但它不會影響現有的用戶。 SqlMembershipProvider通過在表中存儲PasswordFormat(0 = clear,1 = Hashed,2 = Encrypted)和密碼來保護現有的用戶和密碼。更改提供程序密碼格式隻影響對用戶表的插入。爲了將現有用戶的密碼轉換爲哈希,您必須更改每個條目的PasswordFormat參數。這是一個簡單的方法來做到這一點:

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); 
    } 
}