2012-06-02 3 views
0

로그인 페이지에서 나오는 일반 암호로 해시 암호를 데이터베이스에서 확인하는 데 큰 어려움이 있습니다. 해시 - 암호와 일반 암호를 비교하는 방법은 무엇입니까?

protected void Button1_Click(object sender, EventArgs e) 
{ 

    SHA384CryptoServiceProvider sh = new SHA384CryptoServiceProvider(); 
    byte[] plainbytes = Encoding.ASCII.GetBytes(TextBox2.Text); 
    var sha = sh.ComputeHash(plainbytes); 
    byte[] hashbytes = sh.Hash; 
    SqlConnection con = new SqlConnection(constr); 
    SqlCommand cmd = new SqlCommand("RegisterUser",con); 
    cmd.CommandType = CommandType.StoredProcedure; 
    SqlParameter param = null; 
    param = cmd.Parameters.Add("@username",SqlDbType.VarChar,10); 
    param.Value = TextBox1.Text; 
    param = cmd.Parameters.Add("@password", SqlDbType.VarChar, 20); 
    param.Value = BitConverter.ToString(hashbytes); 
    try 
    { 
     con.Open(); 
     cmd.ExecuteNonQuery(); 
     Label4.Text = "Successfully added account!!!"; 
    } 
    catch (Exception ex) 
    { 
     throw new Exception("Exception adding account"+ex.Message); 
    } 
    finally 
     { 
      con.Close(); 
     } 
} 

방법 ... 로그인 페이지에서 오는 하나이 암호를 비교 사람을 나를 도와 ...

: 어떻게이 두 passwords.Here을 비교하여 사용자를 확인하는 등록 페이지 내 코드입니다 SALT와 HASH에 대한

코드 : -

private static string CreateSalt(int size) 

{ 

    RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider(); 

    byte[] buff = new byte[size]; 

    rng.GetBytes(buff); 

    return Convert.ToBase64String(buff); 

} 

private static string CreatePasswordHash(string pwd, string salt) 

{ 

    string saltAndPwd = String.Concat(pwd, salt); 

    string hashedPwd = 

    FormsAuthentication.HashPasswordForStoringInConfigFile(saltAndPwd, "SHA1"); 

    hashedPwd = String.Concat(hashedPwd, salt); 

    return hashedPwd; 

} 

protected void btnregister_Click(object sender, EventArgs e) 

{ 

    int saltSize = 5; 

    string salt = CreateSalt(saltSize); 

    string passwordHash = CreatePasswordHash(txtPassword.Text, salt); 

    try 

    { 

     StoreAccountDetails(txtUserName.Text, passwordHash); 

    } 

    catch (Exception ex) 

    { 

     lblMessage.Text = ex.Message; 

    } 

} 

private void StoreAccountDetails(string userName,string passwordHash) 

{ 

    SqlConnection conn = new SqlConnection(constr); 

    SqlCommand cmd = new SqlCommand("INSERT INTO Users VALUES(@userName, @passwordHash)", conn); 

    SqlParameter sqlParam = null; 

    sqlParam = cmd.Parameters.Add("@userName", SqlDbType.VarChar,20); 

    sqlParam.Value = userName; 

    sqlParam = cmd.Parameters.Add("@passwordHash ", SqlDbType.VarChar,50); 

    sqlParam.Value = passwordHash; 

    try 

    { 

     conn.Open(); 

     cmd.ExecuteNonQuery(); 

     lblMessage.Text = "User Added Successfully!!!"; 

    } 

    catch(Exception ex) 

    { 

    throw new Exception("Exception adding account. " + ex.Message); 

    } 

    finally 

    { 

     conn.Close(); 

    } 

} 

private bool VerifyPassword(string suppliedUserName,string suppliedPassword) 

{ 

    bool passwordMatch=false; 

    SqlConnection conn = new SqlConnection(constr); 

    SqlCommand cmd = new SqlCommand("SELECT PasswordHash FROM Users WHERE UserName = @userName", conn); 

    SqlParameter sqlParam = cmd.Parameters.Add("@userName",SqlDbType.VarChar,20); 

    sqlParam.Value = suppliedUserName; 

    try 

    { 

     conn.Open(); 

     SqlDataReader reader = cmd.ExecuteReader(); 

     reader.Read(); 

     string dbPasswordHash = reader.GetString(0); 

     int saltSize = 5; 

     string salt = CreateSalt(saltSize); 

     reader.Close(); 

     string hashedPasswordAndSalt =CreatePasswordHash(suppliedPassword, salt); 

     passwordMatch = hashedPasswordAndSalt.Equals(dbPasswordHash); 

    } 

    catch (Exception ex) 

    { 

     throw new Exception("Execption verifying password. " +ex.Message); 

    } 

    finally 

    { 

     conn.Close(); 

    } 

    return passwordMatch; 
} 


protected void btnlogon_Click(object sender, EventArgs e) 

{ 

    bool passwordVerified=false; 

    try 

    { 

     passwordVerified =VerifyPassword(txtUserName.Text, txtPassword.Text); 

    } 

    catch (Exception ex) 

    { 

     lblMessage.Text = ex.Message; 

     return; 

    } 

    if (passwordVerified == true) 

    { 



     lblMessage.Text = "Logon successful: User is authenticated"; 

    } 

    else 

    { 

     lblMessage.Text = "Invalid username or password"; 

    } 

} 
+0

그리고 비교는 실제로 어디에 있습니까? – Regfor

+0

나는 비교 logig를 업데이 트 ... D 코드 ... thnx 수정에 나를 도울 수 ... – biki

+0

당신이 사용하고있는 실제 코드를 게시 할 수 있습니까? 여전히 올바르지 않습니다. searchtable()에서 hashbyte를 사용하고 해당 변수가 존재하지 않기 때문에 알 수 있습니다. –

답변

2

지금 당신은 당신의 코드 아직도 몇 가지 문제를 볼 업데이트 해당 업데이트. 소금을 사용해야하지만, 실제로 일하려면 코드가 필요합니다. 소금을 추가하는 것은 쉽습니다.

"mypassword"의 간단한 SHA 해시는 20 자보다 훨씬 큰 문자열을 생성합니다. base64의 해시 된 암호를 20 자 필드에 맞출 수있는 방법은 없습니다. 큰 해시를 지원하도록 열 크기와 코드를 변경하십시오.

업데이트 여기에 2

해시에 소금과 코드입니다. 사용자 이름과 해시 된 암호와 함께 소금을 저장하려면 RegisterUser 저장 프로 시저를 업데이트해야합니다. 사용자 당 새로운 소금이 필요합니다. 소금 자체는 해시되거나 암호화 될 필요가 없습니다.

또한 LogInUser 저장 프로 시저에서 소금을 반환해야합니다. 아래

읽기 코멘트 :

private byte[] Combine(byte[] a, byte[] b) 
{ 
    byte[] c = new byte[a.Length + b.Length]; 
    System.Buffer.BlockCopy(a, 0, c, 0, a.Length); 
    System.Buffer.BlockCopy(b, 0, c, a.Length, b.Length); 
    return c; 
} 

protected void Button1_Click(object sender, EventArgs e) 
{  
    byte[] salt = new byte[16]; 
    RNGCryptoServiceProvider random = new RNGCryptoServiceProvider(); 
    random.GetNonZeroBytes(salt); 

    SHA384CryptoServiceProvider sh = new SHA384CryptoServiceProvider(); 
    byte[] plainbytes = Encoding.ASCII.GetBytes(TextBox2.Text); 

    var saltedBytes = Combine (salt, plainbytes); 
    var sha = sh.ComputeHash(saltedBytes); 

    SqlConnection con = new SqlConnection(constr); 
    SqlCommand cmd = new SqlCommand("RegisterUser",con); 
    cmd.CommandType = CommandType.StoredProcedure; 

    SqlParameter param = null; 
    param = cmd.Parameters.Add("@username",SqlDbType.VarChar,10); 
    param.Value = TextBox1.Text; 

    param = cmd.Parameters.Add("@password", SqlDbType.VarChar, 128); 
    param.Value = Convert.ToBase64String(sha); 

    // Store salt to use when comparing. 
    param = cmd.Parameters.Add("@salt", SqlDbType.VarChar, 128); 
    param.Value = Convert.ToBase64String(salt); 

    try 
    { 
     con.Open(); 
     cmd.ExecuteNonQuery(); 
     Label4.Text = "Successfully added account!!!"; 
    } 
    catch (Exception ex) 
    { 
     throw new Exception("Exception adding account"+ex.Message); 
    } 
    finally 
    { 
     con.Close(); 
    } 
} 

public bool searchtable() 
{   
    SqlConnection con = new SqlConnection(constr); 
    SqlCommand cmd = new SqlCommand("LogInUser",con); 
    cmd.CommandType = CommandType.StoredProcedure; 

    SqlParameter param = null; 
    param = cmd.Parameters.Add("@username",SqlDbType.VarChar,10); 
    param.Value = TextBox1.Text; 

    try 
    { 
     con.Open(); 
     SqlDataReader reader = cmd.ExecuteReader(); 
     reader.Read(); 

     // Get the salt hashed password 
     string dbpassmatch = reader.GetString(0); 

     // Get the salt 
     byte[] salt = Convert.FromBase64String(reader.GetString(1)); 

     // Recreate the salted hashed password 
     byte[] plainbyte = Encoding.ASCII.GetBytes(TextBox2.Text); 
     SHA384CryptoServiceProvider sh = new SHA384CryptoServiceProvider(); 
     var saltedBytes = Combine (salt, plainbytes); 
     var sha = sh.ComputeHash(saltedBytes);    

     // Now it matches what you did in insert. 
     String dbpassword = Convert.ToBase64String(sha); 

     reader.Close(); 

     return dbpassword.Equals(dbpassmatch); 
    } 
    catch (Exception ex) 
    { 
     throw new Exception("Exception adding account" + ex.Message); 
    } 
    finally 
    { 
     con.Close(); 
    } 
} 
+0

당신의 소금은 어디에서 있냐? – ThiefMaster

+0

@ThiefMaster 내 부엌 카운터에. –

+0

@ AndrewFinnell : 감사합니다 친구 ... 해결했습니다 ... – biki

4

간단한. 로그인 페이지에서 오는 암호를 해시하고 해시 코드를 데이터베이스의 해시 코드와 비교합니다.


텍스트는 두 번 모두 동일하게 처리되어야하므로 해당 부분에 대해 단일 기능을 수행하십시오. 바이트로 텍스트를 변환 할 때 UTF-8을 사용하여 ASCII 인코딩은 모든 문자를 처리하지 않습니다

public static string HashString(string value) { 
    SHA384CryptoServiceProvider sh = new SHA384CryptoServiceProvider(); 
    byte[] plainbytes = Encoding.UTF8.GetBytes(value); 
    byte[] hash = sh.ComputeHash(plainbytes); 
    return BitConverter.ToString(hashbytes); 
} 
+0

안녕하세요, 로그인 페이지에서 뭐가 잘못 됐는지 알 수 있습니까? 정말 고생했습니다 ... 도와주세요 ... – biki

+0

@biki : 데이터베이스에 base64로 해시를 저장 했으므로, 따라서 로그인 페이지에서 암호와 동일한 작업을 수행해야합니다. – Guffa

+0

실제로 나는 그것을 시도했지만 결과는 동일합니다 ... 이제 무엇을해야합니까? – biki

0

당신은하지 응용 프로그램 측의 DB 측에 해싱을 할 수 있습니다. 그게 가장 쉬운 것입니다, youll은 저장 프로 시저에 저장된 일반 텍스트로 암호를 보내면 sha1과 같은 암호로 해시합니다 (). 그러면 사용자가 로그인을 수행 할 때 암호를 다시 보내면 저장 프로 시저가 찾을 것입니다 보낸 사용자 이름을 입력 한 다음 암호를 해시하고 등록시 저장된 암호와 비교합니다.

+0

그리고 내가 어떻게 해야하는지 ... 어떤 생각 ?? – biki

+0

이것은 암호화를위한 트릭을 수행해야합니다 : hashbytes ('sha1', 'password') thats for the register. 다음과 같은 select를 할 수 있습니다 : select * from users where userName = _userName 및 password = hashbytes ('sha1', _ password) –

+0

이는 SQL 서버용이고 MySql을 사용하는 경우 SHA1 ('password'); –

2

귀하의 코드는 보안 관점에서 매우 나쁜 :

  1. 사용 소금. 일반적으로 임의의 값 (64 비트 이상)이 데이터베이스의 해시와 함께 저장됩니다.
  2. Rfc2898DeriveBytes Class이 하지만 Encoding.UTF8를 사용하지 마십시오 : .NET 이미 구현을 포함하고 있기 때문에
  3. 는 같은 PBKDF2, bcrypt 또는 scrypt
    PBKDF2 수있는 가장 쉬운 방법이기 때문에, 느린 KDF를 사용합니다.ASCII가 아닌 문자가 포함 된 다른 암호는 매우 약해집니다.

그런 다음 입력 된 암호를 확인하려면 db에서 해시 및 소금을 읽습니다. 후보 암호를 해시에서 읽은 소금으로 해시하고 해시를 비교하십시오.


ASP.net에도 Membership이라는 라이브러리가 있지만 그다지 익숙하지 않습니다.

+0

@codeln : thnx 정보 ...내 코드를 소금으로 수정했습니다 ... 코드에서 뭐가 잘못 되었나요? – biki

+1

@biki'FormsAuthentication.HashPasswordForStoringInConfigFile'은 빠릅니다. 사용하지 마십시오. 'Rfc2898DeriveBytes'가 훨씬 좋습니다. – CodesInChaos

관련 문제