2017-03-19 13 views
-1

パスワードのハッシュと塩について複数の質問がありましたが、すべて失敗するようです。私は/塩、それをハッシュするためにこの機能を使用して、データベースにそれを置く:ハッシュされたパスワードとsaltとの比較は常に失敗します

public string HashPassword(string password) 
    { 
     byte[] salt; 
     new RNGCryptoServiceProvider().GetBytes(salt = new byte[16]); 
     var pbkdf2 = new Rfc2898DeriveBytes(PasswordTextbox.Password, salt, 10000); 
     byte[] hash = pbkdf2.GetBytes(20); 
     byte[] hashBytes = new byte[36]; 
     Array.Copy(salt, 0, hashBytes, 0, 16); 
     Array.Copy(hash, 0, hashBytes, 16, 20); 
     string savedPasswordHash = Convert.ToBase64String(hashBytes); 
     return savedPasswordHash; 
    } 

そして私は、この機能を使用して、ユーザの入力と比較してみてください:

public static void UnhashPassword(string hashedPassword, string hashedPasswordFromDatabase) 
    { 
     byte[] hashBytes = Convert.FromBase64String(hashedPasswordFromDatabase); 
     byte[] salt = new byte[16]; 
     Array.Copy(hashBytes, 0, salt, 0, 16); 
     var pbkdf2 = new Rfc2898DeriveBytes(hashedPassword, salt, 10000); 
     byte[] hash = pbkdf2.GetBytes(20); 
     for (int i = 0; i < 20; i++) 
      if (hashBytes[i + 16] != hash[i]) 
       throw new UnauthorizedAccessException(); 
    } 

第二の機能は常に例外をスローします。この回答が他の質問のすべての人にとってうまくいくように思えた理由は何であるか分かりません。

+0

2つのこと:最初の関数に 'password'を渡し、決してそれを使用しません。 2)パスワードの一致を確認する方法は、元のパスワードと同じ方法でパスワードをハッシュし、同じ結果が得られたかどうかを確認することです。あなたがここで間違った終わりをしているのかどうかは分かりませんが、あなたのパスワード名は "unhashPassword"です。パスワードを解体することはできません。ハッシングは一方通行のプロセスです(ハッシュからパスワードを取得することはできません)。 – Chris

+0

@Chris:2番目のメソッドの命名は誤解を招きますが、そのメソッドのコードは実際に#2のポイントで説明したものを正確に実行しています(実際には、下記参照)。 –

+0

あなたの質問を更新してください。どのような種類の例外があなたに届いていて、どの行に表示されていますか? @PeterDunihoがすでに書いたことは別として、本当のプロジェクトであなた自身の暗号化を実際に使ってはいけないのです。 MembershipProviderクラスを調べることをお勧めします。https://msdn.microsoft.com/en-us/library/ms731049(v=vs.110).aspx – Igor

答えて

2

確かに問題を再現する良いMinimal, Complete, and Verifiable code exampleがなければ、何が間違っているかを確実に言うことは不可能です。ただし、次のコード例は期待どおりに作業を行う(resultのすなわち値は、それがValidatePassword()への呼び出しによって初期化されています後trueです:

static void Main(string[] args) 
{ 
    string password = "password"; 
    string hashedPassword = HashPassword(password); 
    bool result = ValidatePassword(password, hashedPassword); 
} 

static string HashPassword(string password) 
{ 
    byte[] salt; 
    new RNGCryptoServiceProvider().GetBytes(salt = new byte[16]); 
    var pbkdf2 = new Rfc2898DeriveBytes(password, salt, 10000); 
    byte[] hash = pbkdf2.GetBytes(20); 
    byte[] hashBytes = new byte[36]; 
    Array.Copy(salt, 0, hashBytes, 0, 16); 
    Array.Copy(hash, 0, hashBytes, 16, 20); 
    string savedPasswordHash = Convert.ToBase64String(hashBytes); 
    return savedPasswordHash; 
} 

static bool ValidatePassword(string password, string hashedPasswordFromDatabase) 
{ 
    byte[] hashBytes = Convert.FromBase64String(hashedPasswordFromDatabase); 
    byte[] salt = new byte[16]; 
    Array.Copy(hashBytes, 0, salt, 0, 16); 
    var pbkdf2 = new Rfc2898DeriveBytes(password, salt, 10000); 
    byte[] hash = pbkdf2.GetBytes(20); 
    for (int i = 0; i < 20; i++) 
    { 
     if (hashBytes[i + 16] != hash[i]) 
     { 
      return false; 
     } 
    } 

    return true; 
} 

上記とあなたの元のコードの間の唯一の材料の変更がありますHashPassword()方法はPasswordTextbox.Passwordではなく、渡されたpassword値を使用していること。

その観察に基づいて、私はあなたが後で検証するとして、独自のシナリオでは、あなたが本当に同じパスワードをハッシュされていないと推測することができます。かどうか、これを0なのでは正しいパスワードを持っていなかったし、後で別のパスワードを渡しているとは言いません。

上記のコード例でコードが正しく動作するように適切な方向に向いていない場合は、質問を改善してMCVEが含まれるようにしてください。

関連する問題