Hash function

😘 ลองเปลี่ยนข้อความธรรมดาให้เป็นฟามลับกันมุ้ย

อะไรก็ตามแต่ที่เกี่ยวกับการทำ Computer Security นั้น เรามักจะเปลี่ยนของธรรมดาให้เป็นความลับเสมอ เพื่อป้องกันไม่ให้คนร้ายแอบเอาไปใช้ได้ แต่คำถามแรกของเราคือ เราจะเปลี่ยนของพวกนั้นให้เป็นความลับได้ยังไงดีหว่า? 🤔

แนะนำให้อ่าน บทความนี้เป็นส่วนหนึ่งของคอร์ส 👦 Security พื้นฐาน ถ้าเพื่อนๆสนใจอยากรู้หลักในการรักษาความปลอดภัยตั้งแต่เริ่มต้นเลย ก็กดอ่านที่ตัวสีฟ้าๆได้เลยนะ

😥 ปัญหา

ดช.แมวน้ำ เชื่อว่าเราทุกคนมีฟามลับที่ไม่อยากให้คนอื่นรู้กันหมดนั่นแหละ เช่น รหัสบัตรเครดิต/เดบิต รหัสผ่านอีเมล์ รหัสปลดล็อคมือถือ หรือพูดง่ายๆคือ รหัสผ่านต่างๆ นั่นเอง ซึ่งปรกตินั้นจะมีแค่เราเท่านั้นที่รู้รหัสลับพวกนั้นชิมิ? แต่ถ้าเราคิดดูดีๆก็จะพบว่า ยังมีอีกคนที่รู้รหัสลับของเราด้วย นั่นก็คือผู้ให้บริการของเรายังไงล่ะ เช่น เหล่าธนาคารเจ้าของบัตรเครดิต/เดบิต ผู้ให้บริการอีเมล์ต่างๆ หรือตัวมือถือเองที่รู้รหัสปลดล็อคจอมือถือ (ถ้าผู้ให้บริการไม่รู้รหัสลับของเราแล้วเขาจะรู้ได้ไงว่าเราใส่รหัสลับถูก 🤣)

จากที่ว่ามานั่นหมายความว่า สมมุติว่าเราเก็บความลับได้ดีฝุดๆ แต่ผู้ให้บริการโดน hack ระบบเสียเอง ความลับของเราก็จะไม่เป็นความลับอีกต่อไปอ่ะจิ ซึ่งเราในฐานะ Programmer ซึ่งมีหน้าที่เขียนโค้ดเพื่อป้องกันเรื่องเหล่านี้ จะรับมือกับการที่ถูก hack ได้ยังไงดีนะ? ... หรือต่อให้ไม่ถูก hack ก็ได้ แค่เราหรือเพื่อนร่วมงานเข้าไปอ่านข้อมูลใน database แล้วเห็น password ผู้ใช้ในระบบได้ ก็ถือว่าระบบเราตกเรื่อง Security เรียบร้อยแบ้ว!!

🤠 เรื่องนี้มีวิธีการป้องกันเยอะม๊วก ไม่ว่าจะเป็นระดับ Hardware, Software, Peopleware, Network บลาๆ แต่สิ่งที่เป็นขั้นต่ำที่สุดและมีประสิทธิภาพที่สุดคือจุดที่เราเขียนโค้ดนี่แหละ เพราะการป้องกันระดับอื่นๆเป็นการกันแค่เปลือกเท่านั้น สุดท้ายถ้าคนร้าย หรือ เรานี่แหละเป็นคนร้าย สามารถเข้าถึงความลับได้ก็จบกันถ้าเราไม่ได้ป้องกันเอาไว้ (แล้วจะป้องกันยังไงให้แม้แต่คนเขียนเองก็โกงระบบตัวเองไม่ได้หว่า?)

ถ้าอยากเห็นภาพมากขึ้นลองไปอ่าน 🦉 นิทานเรื่องที่สอง ที่ป๋มได้เขียนไว้ได้นะ

😉 วิธีการแก้ปัญหา

เราก็แค่ทำให้ ความลับไม่สามารถเอาไปใช้งานได้ตรงๆ ก็เพียงพอแล้ว เช่น สมมุติว่าเราเก็บ Username & Password ของคนในระบบเป็นแบบด้านล่าง เมื่อคนร้ายเข้าถึงข้อมูลนี้ได้ เขาก็จะรู้เลยว่าทุกคนใช้รหัสผ่านอะไรชิมิ

Id

Username

Password

1

saladpuk

1234

2

thaksin

homesick

3

prayut

1234

ซึ่งเมื่อเรานำหลัก Security เข้ามาใช้ เราก็จะเปลี่ยนให้ความลับไม่สามารถเอาไปใช้งานได้ตรงๆ ก็จะทำให้ข้อมูลเราเปลี่ยนเป็นราวๆนี้

Id

Username

Password

1

saladpuk

fd4438f5b856bb685004b84221ba794b

2

thaksin

f679b30fde31dff10304dc357300c52b

3

prayut

3d54cf99f817a21cd9fd2b7218e58fec

จะเห็นว่าตารางอันใหม่ด้านบนนั้น เราได้แปลงรหัสผ่านทุกคนเป็นอย่างอื่นไปเรียบร้อยแล้ว ซึ่งผู้ใช้ทุกคนก็ยังคงสามารถใช้รหัสผ่านอันเดิมเข้าสู่ระบบได้เหมือนเดิม แถมคนที่สร้างระบบก็ไม่สามารถรู้ได้ว่ารหัสผ่านแต่ละคนคืออะไร และจะเห็นว่าผู้ใช้ saladpuk และ prayut ที่ใช้รหัสผ่านเดียวกัน พอดูในตารางใหม่เราก็ไม่สามารถเดาได้เลยว่าเขาใช้รหัสผ่านเดียวกันด้วย

😅 อยากทำเป็นอ่ะ

การที่เราจะทำเรื่องนี้ได้แบบถูกหลักจะทำให้ระบบเรามีความปลอดภัยสูงขึ้น ซึ่งเราต้องอาศัยความรู้พื้นฐานที่เรียกว่าการทำ Hash กับ HMAC และถ้าจะให้ดีควรรู้เรื่องการทำ Salt กับ Pepper ด้วย ซึ่งกระป๋มได้เล่านิธานเพื่อให้เข้าใจง่ายๆแล้วในบทความ 🦉 นิทานเรื่องแรก กับ 🦉 นิทานเรื่องที่สอง ถ้าสนใจก็ไปอ่านต่อได้กั๊ฟ

(ในบทความนี้จะขอสอนแค่ Hash ตัวเดียวก่อนนะ ส่วนตัวอื่นๆจะเป็นบทความถัดไป)

😎 Hash Functions

การที่เราจะ เปลี่ยนข้อความธรรมดาเป็นข้อความลับ นั้นมีหลายวิธี ซึ่งแต่ละวิธีก็มีหลาย Algorithms ให้เราเลือกใช้เลย โดยในรอบนี้ตัวพื้นฐานที่เราจะมามาเป็นพระเอกของเราคือเจ้าตัวที่ชื่อว่า Hash นั่นเองกั๊ฟ ซึ่งรายละเอียดของมันรบกวนเพื่อนไปอ่านต่อที่บทความนี้นะ 💔 จดหมายถูกแก้ไข ตรงนี้แมวน้ำขอสรุปแบบย่อๆไว้ละกันว่า

  • การทำ Hash เป็นการแปลงข้อความธรรมดาให้เป็นข้อความอื่นที่มีความยาวเท่ากันเสมอ

  • ผลลัพท์ที่ได้ไม่สามารถคำนวณย้อนกลับเพื่อไปหาว่าข้อความจริงๆคืออะไรได้

  • ข้อความตั้งต้นเหมือนกันจะได้ผลลัพท์เดียวกันเสมอ

  • ข้อความตั้งต้นต่างกันบางทีก็อาจจะได้ผลลัพท์เดียวกัน

เมื่อเข้าใจภาพรวมคร่าวๆของ Hash functions แล้ว ทีนี้ก็อย่างที่บอกว่ามันมีให้เราเลือกใช้หลายตัวเลย เช่น MD5, SHA-1, SHA-256, SHA-384, SHA-512 บลาๆ

เกร็ดความรู้ พวก Security ในสมัยก่อนนั้นเกิดมาตอนที่คอมพิวเตอร์ไม่ได้เร็วมากเท่าปัจจุบัน แต่หลังๆมานี้มือถือที่เราใช้อยู่ก็มีความเร็วมากกว่า Super Computer ในอดีตแบบขาดลอยแล้ว เลยทำให้ Security บางตัวถือว่าไม่ปลอดภัยแล้วในปัจจุบัน เช่น MD5 เป็นต้น ดังนั้นเราควรอัพเดทเรื่อง Security บ่อยๆว่าปัจจุบันเขาแนะนำตัวไหนเป็นขั้นต่ำสุดนั่นเองกั๊ฟ เพราะปัจจุบันคอมพิวเตอร์เป็นไปตามกฎ Moore's law อยู่

🤔 โค้ดเขียนยังไง?

ตามที่เคยบอกไปว่า แต่ละภาษาจะมี library เฉพาะทางของมันเอง เช่นในฝั่งของ .NET ก็จะอยู่ใน System.Security.Cryptography ซึ่งเรามีให้เลือกใช้คือ SHA1, SHA1CryptoServiceProvider, SHA1Manged, SHA256, SHA256CryptoServiceProvider, ... (ไปดูเองเยอะม๊วก 😭 ) โดยในรอบนี้แมวน้ำจะลองเอาข้อความ 3 ข้อความที่ไม่เหมือนกัน ไปเข้ารหัสผ่าน MD5, SHA1, SHA256 และ SHA512 ดูว่าผลลัพท์มันจะเป็นยังไงกันบ้างนะ ตามโค้ดด้านล่างนี้เบย

ข้อความ 3 ตัวที่ไม่เหมือนกัน (ตัวเล็กตัวใหญ่ถือว่าต่างกันนะจ๊ะ)

var plainText1 = "Hello world";
var plainText2 = "hello world";
var longestText = "This is the longest text ever";

สร้าง Method ที่ใช้ในการเข้ารหัส Hash

static string GetHashedText(string text, HashAlgorithm algorithm)
{
	var byteText = Encoding.UTF8.GetBytes(text);
	var byteResult = algorithm.ComputeHash(byteText);
	return string.Join(string.Empty, byteResult.Select(it => it.ToString("X2")));
}

ทดลองเข้ารหัสข้อความทั้ง 3 ผ่าน Hash แต่ละแบบ

Console.WriteLine("MD5");
using var md5 = MD5.Create();
Console.WriteLine(GetHashedText(plainText1, md5));
Console.WriteLine(GetHashedText(plainText2, md5));
Console.WriteLine(GetHashedText(longestText, md5));

Console.WriteLine("\nSHA-1");
using var sha1 = SHA1.Create();
Console.WriteLine(GetHashedText(plainText1, sha1));
Console.WriteLine(GetHashedText(plainText2, sha1));
Console.WriteLine(GetHashedText(longestText, sha1));

Console.WriteLine("\nSHA-256");
using var sha256 = SHA256.Create();
Console.WriteLine(GetHashedText(plainText1, sha256));
Console.WriteLine(GetHashedText(plainText2, sha256));
Console.WriteLine(GetHashedText(longestText, sha256));

Console.WriteLine("\nSHA-512");
using var sha512 = SHA512.Create();
Console.WriteLine(GetHashedText(plainText1, sha512));
Console.WriteLine(GetHashedText(plainText2, sha512));
Console.WriteLine(GetHashedText(longestText, sha512));

ผลลัพท์

MD5
3E25960A79DBC69B674CD4EC67A72C62
5EB63BBBE01EEED093CB22BB8F5ACDC3
13988F9767E8BADB3E8D98F3A7FD83F6
3E25960A79DBC69B674CD4EC67A72C62

SHA-1
7B502C3A1F48C8609AE212CDFB639DEE39673F5E
2AAE6C35C94FCFB415DBE95F408B9CE91EE846ED
F44FDE2EB97F456F4F7A11B2D96FB6923900E406

SHA-256
64EC88CA00B268E5BA1A35678A1B5316D212F4F366B2477232534A8AECA37F3C
B94D27B9934D3E08A52E52D7DA7DABFAC484EFE37A5380EE9088F7ACE2EFCDE9
756A8392F0F9F4103E9909A508EC8722FB061D81512C59060BEBE6145E57BE0A

SHA-512
B7F783BAED8297F0DB917462184FF4F08E69C2D5E5F79A942600F9725F58CE1F29C18139BF80B06C0FFF2BDD34738452ECF40C488C22A7E3D80CDF6F9C1C0D47
309ECC489C12D6EB4CC40F50C902F2B4D0ED77EE511A7C7A9BCD3CA86D4CD86F989DD35BC5FF499670DA34255B45B0CFD830E81F605DCF7DC5542E93AE9CD76F
ABA075B7537FD45343B98619C9EE5B116F9D2C43348033C249EE6DEFBB8F85DE854D7B6A63CF4365830A2A6F4EA4DF496163701FCC54D4EA41D54C83826E501F

จะเห็นว่าไม่ว่าจะ run กี่ครั้ง เราก็จะได้ผลลัพท์เดิมเสมอ และทุกอย่างก็จะเป็นตามกฎทั้ง 4 ข้อตามที่เคยบอกไว้ และความต่างๆของการเข้า Hash แต่ละแบบก็จะเห็นว่า ยิ่งเลขเยอะมันก็จะได้ผลลัพท์ที่ยาวขึ้น เช่น SHA256 ก็จะสั้นกว่า SHA512 นั่นก็เพราะว่าเลขที่อยู่ด้านหลังนั้นเป็นตัวบอกว่า algorithm นั้นๆมีขนาดเท่าไหร่นั่นเองขอรับ เลขยิ่งเยอะยิ่งป้องกันได้ดี แต่ก็ต้องแลกมากับเวลาในการประมวลผลเช่นกัน ดังนั้นเราต้อง balance มันว่าแต่ละเรื่องควรจะใช้ขนาดไหนถึงจะเหมาะสมนั่นเองฮ๊าฟ (ณ วันที่เขียนบทความนี้ SHA256 ถือว่าเป็นตัวที่ถูกแนะนำให้ใช้ แต่ในอนาคตก็ไม่แน่ผ่านไปอีกซักไม่กี่ปีก็อาจจะถือว่าไม่ปลอดภัยแล้วก็ได้ 😂)

อะเชก็ถือว่าจบไปแล้วสำหรับ Hash เดี๋ยวถัดไปเราจะมาดูตัวที่มีความปลอดภัยมากกว่า Hash บ้างนั่นก็คือ HMAC กั๊ฟป๋ม 😎

เกลียด ชอบ ถูกใจ อยากติดตาม อยากติชมแนะนำด่าทอ หรืออะไรก็แล้วแต่ (ห้ามมายืมเงิน) จิ้มลงมาที่เพจนี้ได้เลย Mr.Saladpuk และจะเป็นประคุณอันล้นพ้นถ้ากด Like + Follow + Share ให้ด้วยขอรับ น้ำตาจิไหล 🥺

Last updated