2013-09-29 2 views
4

Я снова и снова читал код, чтобы узнать, где происходит ошибка, но я не могу его найти. Я скопировал этот код из stackoverflow, который никогда не проверял его или не понимал, как это исправить. Я получаю пароли из веб-сервиса, хеширования, соления и сохранения его в SqlServer 2008. Переменные на SqlServer объявляются как почта как nvarchar (64), хэш как varbinary (128) и соль как 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; 

     } 


    } 

И следующий метод является один я использую для проверки де пароль, он всегда возвращает ложь

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

      } 

     } 

    } 

Любые идеи, что может быть неправильно?

EDIT: Я нашел ссылку, где я получил код хэширования https://stackoverflow.com/a/4330586/1861617

+1

Являются ли хэш и соль одинаковыми при сохранении и подтверждении данных? – Sam

+0

Да, я сохраняю хэш и соль в одном ряду. Затем загрузите ту же строку и подтвердите ее с помощью пароля. –

+0

Вы пытались установить точки останова в любом месте вашего кода и после выполнения на 100% убедиться, что переменные содержат то, что, по вашему мнению, они хранят (и для проверки кода ведет себя как ожидалось)? Кроме того, вы получаете какие-либо ошибки? – Sam

ответ

0

После проверки с ответом Десоби и до сих пор не получилось. Я перепроверил и понял, что 20 байт составляют 120 бит, поэтому varbinary не смог сохранить целую соль. После увеличения его до 256 он работал.

0

Использования кода в тестовом проекте (Windows Forms с текстовым полем + кнопкой + наклейкой) Я добавил это:

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

Мое предположение, что ваше определение для CLAS USERDATA является 'некорректный'?