Wednesday, December 19, 2007

Cryptography Simplified in Microsoft.NET

ตอนที่ 2 เพิ่มความปลอดกัยของ Hash Algorithm ด้วย Salt

จาก ตอนที่ 1 บทนำ และ Hash Algorithm ได้กล่าววิธีการเข้่ารหัสแบบ on-way หรือ แบบทางเดียว (ถอดรหัสไม่ได้) โดยได้เสนอวิธีของการทำ Hash ด้วย RSA และ SHA1 พร้อมกับ แสดงตัวอย่างของโค้ดไปบ้างแล้ว มาตอนที่ 2 นี้ผมก็ยังอยู่ในเรื่องของ Hash ครับ ซึ่งเป็นเรื่องของการใช้้ Hash อย่างปลอดภัยครับ

เพิ่ม Salt ใน Hash เพื่อควารมปลอดภัยยิ่งขึ้น

ปัญหาอย่างหนึ่งของการ Hash คือ หากมี user 2 คนกำหนด Password เหมือนกัน เขาทั้งคู่ก็จะได้ Hash data เดียวกันทุกประการ ดังนั้นถ้าผมเป็น Hacker แล้วสามารถเข้าไปดูใน table ที่เก็บรหัสผ่านได้ ผมก็จะเห็น user 2 คนมี Hash data เหมือนกัน ผมสามารถเดาได้ว่า Password นั้นน่าจะเป็นเพียงคำง่ายๆ ก็จะลองทำ dictionary attack ดู เรามีวิธีแก้ไข คือ การเพิ่มคำที่เป็นเอกลักษณ์(Unique) เข้าไปใน Password แล้วจึงค่อยทำการ Hash

คำที่เป็นเอกลักษณ์นี้ก็คือ Salt นั่นเอง

แต่ในการใช้ Salt นั้น เราก็ต้องเก็บ Salt ไว้ด้วยเช่นกัน เพื่อใช้เป็นส่วนหนึ่งของ Password ในการ Hash เมื่อ user ทำการล๊อกอินเข้าสู่ระบบ และเพื่อเป็นการปลอดภัยของ Salt เช่นกัน เราจึงควรเก็บ Salt ไว้แยกออกจากตารางที่เก็บ User id และ Password

วิธีในการเพิ่ม Salt เข้าไปใน Password

ขอยกตัวอย่างวิธีที่ง่ายที่สุดก่อนคือ การนำข้อมูลส่วนอื่นๆ ของ user เช่น ชื่อ นามสกุล อีเมลล์แอดเดรส หรือ รหัสพนักงาน เข้าไปใน Password แล้วจึงทำการ Hash แต่วิธีนี้มีข้อเสียคือ เนื่องจากเราต้องเก็บ Salt ไว้แยกจากตารางข้อมูล user id และ Password ดังนั้นมันดูเป็นการตั้งใจเกินไปหากเราจะแยกเก็บ ชื่อ หรือ นามสกุล ออกไปจากตารางนี้ และ Hacker ก็ฉลาดมากพอที่จะเข้าใจในสิ่งที่เรากำลังทำอยู่

วิธีที่ดีกว่า คือ การสร้างคำแบบสุ่ม โดยอาศัยคลาสใน .NET Framework ชื่อ RNGCryptoServiceProvider โดยคลาสนี้จะสร้าง array ของ byte แบบสุ่มตามขนาดที่เรากำหนดขึ้นเอง แล้วจึงนำ array ของ byte นี้มาใช้เป็น Salt เพื่อทำการ Hash ต่อไป

โค้ดฟังก์ชันการสร้าง Salt
โดยคืนค่ากลับมาเป็น String ที่สุ่มมาแล้ว

Private Function CreateSalt() As String
Dim byteSalt(8) As Byte
Dim rng As New Security.Cryptography.RNGCryptoServiceProvider

rng.GetBytes(byteSalt)

Return Convert.ToBase64String(byteSalt)
End Function


เมื่อเราทำการ Hash ก็ให้ Concat ค่า Salt กับ Password เข้าด้วยกันแล้วจึงทำการ Hash

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
SaltTextBox.Text = CreateSalt()
TextBox2.Text = HashText(SaltTextBox.Text & TextBox1.Text)
End Sub


ส่วนฟังก์ชัน Hash ยังคงเดิม

Private Function HashText(ByVal TextToHash As String) As String
Dim SHA1 As System.Security.Cryptography.SHA1CryptoServiceProvider
Dim byteValue() As Byte
Dim byteHash() As Byte

' Instanciate SHA1
SHA1 = New System.Security.Cryptography.SHA1CryptoServiceProvider
byteValue = System.Text.Encoding.UTF8.GetBytes(TextToHash)

byteHash = SHA1.ComputeHash(byteValue)

SHA1.Clear()

Return Convert.ToBase64String(byteHash)
End Function


ผลลัพธ์ เมื่อทำการ Hash ข้อมูลเดียวกันด้วย Salt 2 ครั้ง ก็จะได้ Hash data ไม่เหมือนกัน




อย่าลืมว่าการใช้ Salt เราต้องเก็บค่า Salt ไว้ด้วยเพื่อใช้ในการ Hash ข้อมูลเมื่อ user ทำการล๊อกอินเข้ามา โดยต้องหาที่เก็บ Salt ให้ปลอดภัยด้วย
.

3 comments:

yawaiam said...

ขอขอบคุณที่ไปแวะเยี่ยมเยียน
อยากฝากความคิดเห็นในบล็อกนี้
แต่ไม่มีความรู้เรื่องที่คุณ NooM เขียนเลย
ไว้ไปคอมเมนท์ที่ fitla ดีกว่านะ

yawaiam said...

หวังอะไรได้ดั่งที่วาดหวัง
ขอพลังจงอยู่คู่เสมอ
ให้ก้าวมั่นสิ่งใดสมใจเธอ
มีความสุขอยู่เสมอ..ทุกคืนวัน

Anonymous said...

เขียนเป็นโปรแกรมแจกเลยสิครับ :D