NET Programming.

Hash کردن یک رشته و چگونگی مقایسه آن

Hash کردن به معنای تولید کدی منحصربه فرد و یکتا و غیرقابل بازگشت برای یک رشته است )بدین معنا که نمی توان فهمید کد تولید شده نتیجه چه رشته ای است) از این رو داده های مهم در جداول پایگاه داده یا هرجای دیگر باید Hash شوند تا در صورت نفوذ هکرها به پایگاه داده نتوانند به محتوای ان داده پی ببرند.

یکی از این داده های مهم که حتما باید Hash شود Password کاربران است .

برای Hash کردن داده در .Net الگوریتمی با نام MD5 برای این کار در نظر گرفته شده است .

الگوریتم MD5 به تولید بایتهایی از رشته داده شده می پردازد در این مقاله سعی خواهم کرد به چگونگی استفاده از این الگوریتم بپردازم.

فرض من این است که پایگاه داده ای در SQL Server با نام Test1 و جدولی به نام users که دارای دو فیلد username و userpassword است داریم برای ساخت جدول از دستور زیر استفاده کنید.

create table users(username varchar(50) primary key,userpassword varbinary(50))

همانگونه که می بینید فیلدی را که می خواهید کد Hash در آن ذخیره شود باید از نوع varbinary باشد.

همچنین فرمی با دو کنترل Textbox به نامهای txtusername و txtpassword به همراه یک کنترل button داریم در این فرم کاربر می تواند username و password خود را وارد کند و برنامه آنرا در جدول users ذخیره می کند البته پسورد کاربر hash می شود.

برای استفاده از الگوریتم های Hashing در ابتدا فضای نام System.Security.Cryptography را به برنامه اضافه کنید.

حال ما تابعی به نام Hash را می نویسیم ،کار این تابع گرفتن یک رشته و دادن یک مقدار Hash است. این مقدار آرایه ای از بایتها است.

C#.NET
private Byte[] hash(string str)
{
 MD5CryptoServiceProvider crypt=new MD5CryptoServiceProvider();
 Byte[] bytes;
 bytes=System.Text.ASCIIEncoding.ASCII.GetBytes(str);
 return crypt.ComputeHash(bytes);
}


VB.NET
Private Function hash(ByVal str As String) As Byte()
    Dim crypt As New MD5CryptoServiceProvider()
    Dim bytes() As Byte
    bytes = System.Text.ASCIIEncoding.ASCII.GetBytes(str)
    Return crypt.ComputeHash(bytes)
End Function

حال به مثال خود برمی گردیم .

در ابتدا متغیرهای زیر را به صورت سراسری تعریف کنید:

C#.NET
private SqlConnection con;
private SqlCommand com;


VB.NET
Private con As SqlConnection
Private com As SqlCommand

حال به مثال خود برمی گردیم .

در ابتدا متغیرهای زیر را به صورت سراسری تعریف کنید:

C#.NET
private SqlConnection con;
private SqlCommand com;


VB.NET
Private con As SqlConnection
Private com As SqlCommand

در رویداد Load فرم دستورات زیر را بنویسید

C#.NET
con = new SqlConnection();
con.ConnectionString = "Data Source=.;Initial Catalog=Test1;Integrated Security=True";


VB.NET
con = New SqlConnection
con.ConnectionString = "Data Source=.;Initial Catalog=Test1;Integrated Security=true"

در رویداد click کنترل Button دستورات زیر را بنویسید:

C#.NET
byte[] hashvalue;
hashvalue = hash(txtpassword.Text);
con.Open();
com = new SqlCommand();
com.Connection = con;
com.CommandText = "insert into users values(@username,@userpassword)";
com.Parameters.AddWithValue("@username", txtusername.Text);
com.Parameters.AddWithValue("@userpassword", hashvalue);
com.ExecuteNonQuery();
con.Close();


VB.NET
Dim hashvalue() As Byte
hashvalue = hash(txtpassword.Text)
con.Open()
com = New SqlCommand
com.Connection = con
com.CommandText = "insert into users values(@username,@userpassword)"
com.Parameters.AddWithValue("@username", txtusername.Text)
com.Parameters.AddWithValue("@userpassword", hashvalue)
com.ExecuteNonQuery()
con.Close()

حالا برنامه را اجرا کنید . و در فرم username و password هایی را وارد کنید.
اگر به SQL Server رفته و نتیجه دستور زیر را ببینید:

select *from users

می بینید که فیلد passowrd به صورت مجموعه ای از بایتها ذخیره شده است که این مجموعه کاملا unique است.

تا اینجا ما نحوه چگونگی تولید و ذخیره یک رشته hash مانند password را گفتیم از اینا به بعد به تکمیل مقاله فرم Login در ابتدای برنامه و چگونگی مقایسه دو مقدار hash می پردازیم بهتر است در ابتدا این مقاله را در آدرس زیر بخوانید:

فرم Login در ابتدای برنامه :

حالا فرض کنید که در ابتدای پروژه یا برنامه خود فرم Login دارید که کار این فرم گرفتن username و پسورد کاربر و در صورت تائید ، وارد شدن به برنامه است

اما در این باره برنامه باید username و password کاربر را در فرم Login گرفته و password وارد شده را hash کرده و با password ذخیره شده مقایسه کند در صورتی که مساوی بود اجازه ورود بدهد.

اما نکته وجود دارد و آن اینکه برای مقایسه دو مجموعه بایت نمی توان ار علامت = استفاده کرد بلکه باید انها را بایت به بایت خواند و هربایت را به تنهایی مقایسه کرد .

حالا فرم Login خود را بسازید (پیش فرض ما همان فرم Login است که قبلا گفته ایم)

برای مقایسه دو مجموعه از بایت تابعی به نام comparetwobytes نوشتیم آنرا به برنامه خود اضافه کنید:


C#.NET
private Boolean comparetwobytes(Byte[] tmphash, Byte[] tmpnewhash)
{
 bool bEqual = false;
 if (tmpnewhash.Length == tmphash.Length)
 {
  int i = 0;
  while ((i < tmpnewhash.Length) && (tmpnewhash[i] == tmphash[i]))
  {
     i += 1;
  }
  if (i == tmpnewhash.Length)
  {
     bEqual = true;
  }
 }
 return bEqual;
}


VB.NET
Private Function comparetwobytes(ByVal tmphash As Byte(), ByVal tmpnewhash As Byte()) As Boolean
        Dim bEqual As Boolean = False
        If tmpnewhash.Length = tmphash.Length Then
            Dim i As Integer
            Do While (i < tmpnewhash.Length) AndAlso (tmpnewhash(i) = tmphash(i))
                i += 1
            Loop
            If i = tmpnewhash.Length Then
                bEqual = True
            End If
        End If
        Return bEqual
End Function

توجه کنید تابع hash نیز باید به قسمت کدنویسی فرم Login نیز اضافه کنید

حالا در رویداد click کنترل Ok دستورات زیر را بنویسید

C#.NET
Byte[] hashvalue;
hashvalue = hash(PasswordTextBox.Text);
com=new SqlCommand();
con.Open();
com.Connection = con;
com.CommandText = "select * from users";
SqlDataReader reader = com.ExecuteReader();
Boolean value = false;
while (reader.Read())
{
 if((UsernameTextBox.Text == reader.GetString(0)) && (comparetwobytes((byte[])reader.GetValue(1), hashvalue)))
  {
     value = true;
     break;
  }
}
if(value)
    MessageBox.Show("نام کاربری و رمز ورودی صحیح است");
else
    MessageBox.Show("نام کاربری یا رمز ورودی اشتباه است");
con.Close();


VB.NET
Dim hashvalue As Byte()
hashvalue = hash(PasswordTextBox.Text)
com = New SqlCommand
con.Open()
com.Connection = con
com.CommandText = "select * from users"
Dim reader As SqlDataReader
reader = com.ExecuteReader
Dim value As Boolean = False
While reader.Read
   If UsernameTextBox.Text = reader.GetString(0) And  comparetwobytes(reader.GetValue(1), hashvalue) = True Then
       value = True
       Exit While
   End If
EndWhile
If value Then
MessageBox.Show("نام کاربری و رمز ورودی صحیح است")
Else
    MessageBox.Show("نام کاربری یا رمز ورودی اشتباه است")
End If
con.Close()

حالا برنامه را اجرا کنید .

در نوشتن بعضی از کدها از msdn استفاده شده است.



دیدگاه شما :

نام             

ایمیل         

وب سایت  

پیام
                  



Warning: mysql_connect() [function.mysql-connect]: Can't connect to MySQL server on '207.158.5.107' (10060) in C:\HostingSpaces\mobtaker\mobtakercode.com\wwwroot\2005.php on line 472
نمی تواند به سرویس دهنده متصل شودCan't connect to MySQL server on '207.158.5.107' (10060)