NET Programming.
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 استفاده شده است.