2011-09-26 74 views
2

我最近在我正在進行的項目中爲我的密碼實施了哈希處理,而且我似乎無法弄清楚發生了什麼問題。HashPasswordForStoringInConfigFile - 對於相同密碼的不同哈希

似乎HashPasswordForStoringInConfigFile()函數爲相同的密碼返回不同的值。

我有下面的代碼實現,其實際上非常類似於MSDN文檔上使用推薦的算法。

我知道SHA1哈希算不算很安全,但這是一個研究應用程序,在這一點上我並不太擔心它。

public const int DefaultSaltSize = 5; 
    private static string CreateSalt() 
    { 
     RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider(); 
     byte[] buffer = new byte[DefaultSaltSize]; 
     rng.GetBytes(buffer); 
     return Convert.ToBase64String(buffer); 
    } 

    public static string CreateHash(string password) 
    { 
     string salt = CreateSalt(); 
     string saltAndPassword = String.Concat(password, salt); 
     string hashedPassword = FormsAuthentication.HashPasswordForStoringInConfigFile(saltAndPassword,"SHA1"); 
     hashedPassword = string.Concat(hashedPassword,salt); 
     return hashedPassword; 
    } 

    public static bool VerifyPassword(string username, string password,AccountDataContext context) 
    { 
     var user = context.UserAccounts.FirstOrDefault(p => p.UserName == username); 
     if (user != null) 
     { 
      string salt = user.Password.Substring(user.Password.Length - DefaultSaltSize); 
      string hashedPassword = CreateHash(password); 
      return hashedPassword.Equals(user.Password); 
     } 
     return false; 

    } 

簡而言之,如果我有以下代碼。

string password1 = "password"; 
string password2 = "password"; 

var hashedPassword1 = CreateHash(password1); 
var hashedPassword2 = CreateHash(password2); 

var match = hashedPassword1.Equals(hashedPassword2); 

//match should be True, but it is turning out False. 

看來,FormsAuthenticationForStoringInConfigFile()沒有返回在CreateHash()方法和密碼1密碼2相同的哈希值。

我理解與應用的鹽他們是不一樣的,但如果你在代碼中看到,我比較兩個hashedPasswords相等之前刪除鹽。

什麼可能導致password1和password2被不同地散列?

回答

4

您的代碼在散列之前將密碼(隨機值)添加到密碼中。這是一件好事。

這意味着如果用戶A和用戶B使用相同的密碼,則密碼散列值將會不同。

您的VerifyPassword方法未使用原始鹽來對比較散列密碼,而是調用CreateHash,該代碼調用CreateSalt並創建新鹽。

你可以嘗試這樣的:

public static string CreateHash(string password) 
{ 
    return CreateHash(password, CreateSalt()); 
} 

private static string CreateHash(string password, string salt)  
{   
    string saltAndPassword = String.Concat(password, salt);   
    string hashedPassword = 
     FormsAuthentication.HashPasswordForStoringInConfigFile(
         saltAndPassword,"SHA1");   
    hashedPassword = string.Concat(hashedPassword,salt);   
    return hashedPassword;  
} 

    public static bool VerifyPassword(string username, 
        string password,AccountDataContext context) 
    { 
     var user = context.UserAccounts.FirstOrDefault(p => p.UserName == username); 
     if (user != null) 
     { 
      string salt = user.Password.Substring(user.Password.Length - DefaultSaltSize); 
      string hashedPassword = CreateHash(password, salt); 
      return hashedPassword.Equals(user.Password); 
     } 
     return false; 

    } 
1

即使VerifyPassword看起來像它剝離了非散列字符串的鹽部分,但你說的應該返回true代碼實際上不叫VerifyPassword。

您的代碼只生成兩個鹽醃散列,然後使用String.Equals來比較它們。

當您使用VerifyPassword而不是String.Equals時會發生什麼?

+0

它不起作用,我爲了簡潔而忽略了呼叫,我應該包括它 – TheJediCowboy

0

此代碼根本不起作用。爲什麼它被標記爲正確答案?

鹽的缺省長度設置爲5

創建鹽當花費5字節數組變得8個字符不是5

驗證密碼然後用於鹽僅需5個字符關的字符串不是8,所以驗證將總是失敗,因爲它使用5個字符作爲salt,而不是用於創建哈希密碼的8個字符。

以下是更新後的代碼,以使上述代碼有效。

private const int DEFAULT_SALT_SIZE = 5; 

    private static string CreateSalt() 
    { 
     RNGCryptoServiceProvider rngCryptoServiceProvider = new RNGCryptoServiceProvider(); 
     byte[] buffer = new byte[DEFAULT_SALT_SIZE]; 
     rngCryptoServiceProvider.GetBytes(buffer); 
     return Convert.ToBase64String(buffer); 
    } 

    public static string CreateHash(string password) 
    { 
     return CreateHash(password, CreateSalt()); 
    } 

    private static string CreateHash(string password, string salt) 
    { 
     string saltAndPassword = String.Concat(password, salt); 
     string hashedPassword = FormsAuthentication.HashPasswordForStoringInConfigFile(saltAndPassword, "SHA1"); 
     hashedPassword = string.Concat(hashedPassword, salt); 
     return hashedPassword; 
    } 

    public static bool VerifyPassword(string userpassword, string password) 
    { 
     byte[] bytePassword = Convert.FromBase64String(userpassword); 
     byte[] byteSalt = new byte[DEFAULT_SALT_SIZE]; 
     Array.Copy(bytePassword, bytePassword.Length - DEFAULT_SALT_SIZE, byteSalt, 0, DEFAULT_SALT_SIZE); 
     string salt = Convert.ToBase64String(byteSalt); 
     string hashedPassword = CreateHash(password, salt); 
     return hashedPassword.Equals(userpassword); 
    } 

這就是我所說的。

 string hashedPassword = Security.CreateHash("password"); 
     if (Security.VerifyPassword(hashedPassword, "password")) 
     { 
      Response.Write("Valid"); 
     } 
     else 
     { 
      Response.Write("Not Valid"); 
     } 

只要密碼匹配,就返回true,否則返回false。

這給你我認爲是有意的這不僅包括哈希裏面的鹽,而且將它添加到哈希的外部,所以它可以作爲1列值存儲在數據庫中,然後使用使用存儲的鹽值在用戶輸入的密碼上重新創建散列並獲得匹配。

相關問題