2013-09-29 132 views
4

我一直在反覆閱讀代碼以查看錯誤發生的位置,但我無法找到它。我從stackoverflow複製了這段代碼,從來沒有真正檢查過它,或者完全理解它來修復它。 我從Web服務接收密碼,哈希,醃製並將其保存到SqlServer 2008. SqlServer上的變量被聲明爲郵件爲nvarchar(64),哈希爲varbinary(128),salt爲varbinary(128) 。 密碼正在保存,但當我嘗試檢查密碼是否正確時,該方法始終返回false。 這是我的方法。將密碼散列到SqlServer

public int InsertData(string mail,string Password) 
    { 

     int lineas; 
     UserData usuario = HashPassword(Password); 
     using (SqlConnection connection = new SqlConnection(Connection)) 
     using (SqlCommand command = connection.CreateCommand()) 
     { 
      command.CommandText = "INSERT INTO Usuarios (Mail,Hash,Salt) VALUES (@mail,@hash,@salt)"; 

      command.Parameters.AddWithValue("@mail", mail); 
      command.Parameters.AddWithValue("@hash", usuario.Password); 
      command.Parameters.AddWithValue("@salt", usuario.salt); 


      connection.Open(); 
      lineas=command.ExecuteNonQuery(); 
     } 
     usuario = null; 
     return lineas; 
    } 



private UserData HashPassword(string Password) 
    { 
     //This method hashes the user password and saves it into the object UserData 
     using (var deriveBytes = new Rfc2898DeriveBytes(Password, 20)) 
     { 
      byte[] salt = deriveBytes.Salt; 
      byte[] key = deriveBytes.GetBytes(20); // derive a 20-byte key 
      UserData usuario = new UserData(); 
      usuario.Password = key; 
      usuario.salt = salt; 
      return usuario; 

     } 


    } 

而且下一個方法是我使用的一個驗證德密碼,它始終返回false

private bool CheckPassword(string Password, byte[] hash, byte[] salt) 
    { 


     // load salt and key from database 

     using (var deriveBytes = new Rfc2898DeriveBytes(Password, salt)) 
     { 
      byte[] newKey = deriveBytes.GetBytes(20); // derive a 20-byte key 

      if (!newKey.SequenceEqual(hash)) 
       return false; 

      else 
       return true; 

     } 
    } 

這個方法接收登錄信息

public bool ValidateLogIn(string mail, string Password) 
    { 



     using (SqlConnection connection = new SqlConnection(Connection)) 
     using (SqlCommand command = connection.CreateCommand()) 
     { 
      command.CommandText = "Select * from Usuarios where [email protected]"; 
      command.Parameters.AddWithValue("@mail",mail); 
      connection.Open(); 
      using (SqlDataReader reader = command.ExecuteReader()) 
      { 
       reader.Read(); 
       byte[] hash = (byte[])reader["Hash"]; 
       byte[] salt = (byte[])reader["Salt"]; 
       if(CheckPassword(Password,hash,salt)) 
       { 
        /
        UpdateData(mail, Password); 
        return true; 
       } 
       else 
       { 
        return false; 
       } 

      } 

     } 

    } 

任何想法可能是什麼錯誤?

編輯:我發現在那裏我得到的散列碼 https://stackoverflow.com/a/4330586/1861617

+1

保存和驗證數據時散列和salt是否相同? – Sam

+0

是的,我將散列和鹽保存到同一行。然後加載相同的行並根據密碼對其進行驗證 –

+0

您是否嘗試過在代碼中的任意位置設置斷點並將其執行到100%,確保變量持有您認爲它們持有的內容(並驗證代碼是否按預期工作)?另外,你是否收到任何錯誤? – Sam

回答

0

與德羅比的答案檢查後,仍然沒有得到運氣。我重新檢查並實現了20個字節是120位,因此varbinary無法存儲整個鹽。將它增加到256後就可以工作了。

0

在測試項目中使用的代碼(用文本框+按鈕+標籤Windows窗體)的鏈接添加此:

internal class UserData 
    { 
     public byte[] Password { get; set; } 
     public byte[] Salt { get; set; } 
    } 

    public string Connection { get; set; } 

    private void UpdateData(string mail, string password) 
    { 
     // not a clue what to do here.... 
    } 

    private void button1_Click(object sender, EventArgs e) 
    { 
     var password = textBox1.Text; 
     var u = HashPassword(password); 

     var b = new SqlConnectionStringBuilder {DataSource = "127.0.0.1", IntegratedSecurity = true}; 
     Connection = b.ConnectionString; 

     InsertData("[email protected]", password); 

     label1.Text = string.Format("Using direct check: {0}\nVia the database: {1}", 
      CheckPassword(password, u.Password, u.Salt), 
      ValidateLogIn("[email protected]", password)); 
    } 

它返回true;真正沒有任何問題。 (VS2010,.NET4 CP,SQL2008R2)

在我使用這個數據庫:

CREATE TABLE tempdb..t_hash 
    (
     Mail nvarchar(64) NOT NULL PRIMARY KEY (Mail), 
     Hash varbinary(128), 
     Salt varbinary(128) 
    ) 

我最好的猜測是,你爲的UserData CLAS定義是 '有缺陷'?