24 ส.ค. 2022 เวลา 07:25 • วิทยาศาสตร์ & เทคโนโลยี
การเข้ารหัสลับ (Encryption) เบื้องต้น สำหรับนักพัฒนา
บทความ “การเข้ารหัสลับ (Encryption) เบื้องต้น สำหรับนักพัฒนา” นี้ใช้แหล่งข้อมูลส่วนใหญ่จาก e-book ชื่อ Practical Cryptography for Developers
อวจ: ที่อยู่ในบทความนั้นย่อมาจาก เอาไว้จำ จุดประสงค์ของผู้เขียนมีไว้เพื่อสรุปความสำหรับผู้อ่านที่มีความเข้าใจอยู่บ้างแล้ว หรืออ่านหัวข้อนั้นแล้วให้สามารถจำนิยามของหัวข้อนั้นได้
สาร ในบทความนี้ไม่ใช่ สารเคมี แต่เป็นข้อความ (message)
ในปัจจุบันอินเทอร์เน็ตเข้ามาเป็นส่วนหนึ่งของชีวิตทุกคน แต่กระนั้นความสะดวกสบายที่มาพร้อมกับอินเทอร์เน็ต ก็ไม่ได้นำมาเฉพาะข้อดีเพียงอย่างเดียว หากมองในด้านความปลอดภัยด้วยนั้น อินเทอร์เน็ตจึงเป็นเหมือนดาบสองคม เนื่องจากว่าหากนักพัฒนา หรือผู้ใช้งานขาดความเข้าใจ ก็จะทำให้เกิดช่องโหว่ให้ผู้ไม่ประสงค์ดีโจมตีระบบ หรือเกิดการโจรกรรมทางไซเบอร์ได้
และหนึ่งในหัวใจสำคัญของการสื่อสารระหว่างผู้ใช้งาน (Client) กับแม่ข่าย (Server) นั่นก็คือ การเข้ารหัสลับ (Encryption) โดยบทความนี้จะค่อย ๆ ปูนิยามของศัพท์ต่าง ๆ ที่เกี่ยวข้อง เช่น การเข้ารหัส (Encoding), ฟังก์ชันแฮช (Hashing function) เป็นต้น จนนำไปสู่เรื่องการเข้ารหัสลับ (Encryption) ทีละหัวเรื่อง ดังต่อไปนี้
การเข้ารหัส (Encoding)
อวจ: ด <-> d ; เสียง “ด” ในภาษาไทย คือเสียง “d” ในภาษาอังกฤษ
ผู้เขียนใช้ภาษาไทยว่า การเข้ารหัส เพื่อแปลคำว่า Encoding และ การเข้ารหัสลับ เพื่อแปลคำว่า Encryption เนื่องจากทั้งสองสิ่งนี้แตกต่างกันอย่างมาก การเข้ารหัสนั้นไม่ได้ทำเพื่อรักษาความลับของสาร แต่ทำเพื่อความสะดวกในการรับส่งสาร หรืออ่านสารได้ง่ายขึ้น ตัวอย่างเช่น การแปลงเลขฐานสองเป็นฐานสิบ หรือการแปลงเลขฐานสิบเป็นสายอักขระ (byte array) หรือการแปลงสายอักขระเป็นสาร base64 เป็นต้น
รูปที่ 1 ตัวอย่างการเข้ารหัส, แหล่งอ้างอิง
การเข้ารหัสนั้น สามารถย้อนกลับได้ง่ายด้วย การถอดรหัส (Decoding) ถ้าหากเรารู้ว่าสารที่เรารับมาถูกเข้ารหัสมาแบบใด เราก็จะสามารถถอดรหัสสารนั้นเป็นสิ่งที่เราต้องการได้ เช่น การแปลงสาร base64 เป็นสายอักขระ
ตัวอย่าง การเข้ารหัสจากสายอักขระเป็นสาร base64 และถอดรหัสจากสาร base64 เป็นสายอักขระ ในภาษา python
เกร็ด: ภาษาคาราโอเกะ ภาษาลู หรือคำผวน ก็เป็นการเข้ารหัสเช่นกัน 🙂
ฟังก์ชันแฮช (Hashing function)
อวจ: คิดถึง -> 345e28e423062ecb7dad358f1b47e4abb836a0cd77cf9f47cf6e6478f8d43403 ; ให้แฮชของความคิดถึง แทนความซาบซึ้งในใจ (เพราะจำไม่ได้ 555)
การแฮชนั้นคล้ายกับการเข้ารหัสตรงที่ ถ้าเรามีสาร และฟังก์ชันการแฮช เราก็สามารถ ผลิต เลขแฮชได้ แต่กลับกัน หากเราได้เลขแฮชมา เราจะไม่สามารถรู้ได้ว่า สารก่อนเข้าฟังก์ชันแฮชเขียนไว้ว่าอย่างไร ซึ่งจะนำไปสู่คุณสมบัติของฟังก์ชันแฮช คุณสมบัติของฟังก์ชันแฮชนั้นมีสองประการ คือ
ไม่สามารถย้อนกลับได้
แทบจะไม่มีสิทธิ์ชนกัน
คำว่า แทบจะไม่มีสิทธิ์ชนกัน นั้น แน่นอนว่าอาจจะเกิดการชนกันได้ แต่เกิดขึ้นยาก อภิมหาโคตรยาก เรียกว่า การพยายามจะหาสารสองอันที่จะให้ผลลัพธ์เลขแฮชเดียวกัน ก็เหมือนกับการควานหาฝุ่นในจักรวาลก็ปานนั้น แต่ในอนาคตก็ไม่แน่ว่า Quantum Computer อาจจะทำให้ SHA-2 ที่ได้รับความนิยมอยู่ในปัจจุบันถูกโค่นลงได้สักวัน อันนี้ก็เป็นเรื่องของอนาคตที่เราต้องติดตามกันต่อไป
ตัวอย่าง ฟังก์ชันแฮชในภาษา python ในที่นี้ ผู้เขียนขอใช้ตัวอย่างฟังก์ชัน sha256 หรือ SHA-2 มาเป็นตัวอย่าง
เกร็ด: ยังมีกลุ่มฟังก์ชันที่มีแนวคิดคล้ายกับฟังก์ชันแฮชอีกสองอย่าง คือ check digit และ checksum แต่ต่างกันตรงความยากในการชนกัน เช่น
หมายเหตุ: วิธีการคำนวน check digit นำมาจาก ที่นี่
ฟังก์ชัน MAC
อวจ: mac_func(สาร, รู้กันแค่เรา) -> ตัวเทียบว่าสารถูกต้อง ; นายเอส่งจดหมายรัก(สาร)หาน้องบีโดยใช้กระดาษสองแผ่นเสมอ(รู้กันแค่เรา) แต่วันหนึ่งไปรษณีย์ทำปลิวหายไปแผ่นหนึ่ง น้องบีจึงรู้ว่าจดหมายนั้นไม่ครบถ้วน(ไม่ถูกต้อง)เพราะไม่ครบสองแผ่น
MAC ในที่นี้ย่อมาจาก Message Authenticaion Code ไม่ได้เกี่ยวข้องกับ MAC Address หรือ Media Access Control Address แต่อย่างใด MAC มีไว้เพื่อทำหน้าที่พิสูจน์ว่าสารที่เราได้รับมาถูกต้องสมบูรณ์หรือไม่
รูปที่ 2 การทำงานของ MAC
เนื่องจากการคำนวน MAC โดยวิธีใช้ hash_func(key + msg) นั้นไม่ปลอดภัยจากการโจมตีแบบ Length Extension Attack ดังนั้นฟังก์ชัน MAC ที่ปลอดภัยและได้รับความนิยมคือ HMAC (Hash-based MAC) โดยมีหน้าตาคือ mac = HMAC(key, msg, hash_func)
ตัวอย่างฟังก์ชัน HMAC ในภาษา python
ฟังก์ชัน KDF
อวจ: kdf_func(เกลือ, รหัสผ่าน, อย่างอื่นถ้ามี) -> รหัสผ่านที่แปลงแล้ว
KDF ย่อมาจาก Key Derivation Functions ฟังจากชื่อแล้วแอบน่ากลัวว่าจะเกี่ยวกับ Derivative ในคณิตศาสตร์ใช่ไหม แต่ไม่ใช่เช่นนั้น ฟังก์ชันนี้ไม่ได้เกี่ยวกับการคำนวน Derivative ผู้อ่านจึงไม่ต้องกังวล
โดยในหัวข้อนี้จะพาผู้อ่านสู่ความเข้าใจ KDF ผ่านการจัดการรหัสผ่านระดับต่าง ๆ ในการจัดการรหัสผ่าน (password) นั้นแน่นอนว่าเราไม่สามารถหลีกหนีเรื่องความปลอดภัยไปได้ และการเก็บรหัสผ่านของผู้ใช้ที่สามารถนำไปใช้งานกับระบบได้ทันทีก็เปรียบเสมือนการเก็บระเบิดเวลาไว้ในระบบ ผู้เขียนขอกล่าวถึง การจัดการรหัสผ่านโดยเริ่มตั้งแต่ระดับ อย่าหาทำ ไปจนถึงระดับ ควรทำ
ระดับ อย่าหาทำ หรือเกรียนสุด
วิธีการที่ง่ายสุด (และเกรียนที่สุดด้วย) นั่นคือการเก็บรหัสผ่านแบบ โต้ง ๆ ได้มาอย่างไรก็เก็บไปอย่างนั้นซะเลย ตัวอย่างเช่น ผู้ใช้งานกรอกรหัสผ่านตอนลงทะเบียนมาเป็น “hello123” ก็นำรหัสผ่านนี้เขียนลงในฐานข้อมูลตารางผู้ใช้เป็น “hello123” นั่นเอง แม้ว่าการจัดการรหัสผ่านของผู้ใช้โดยวิธีนี้จะไม่มีความซับซ้อน และไม่ต้องใช้ library อื่นจากภายนอกเลย แต่ผู้เขียนกล่าวได้เลยว่าการทำแบบนี้
กรณีดีที่สุด คือ การรอให้คนอื่นมาด่าเราว่า ทำไมทำอะไรหละหลวมแบบนี้เปลี่ยนแปลงซะ หรือกรณีร้ายที่สุดคือระบบถูกเล่นงาน ผู้โจมตีระบบได้ครอบครองรหัสผ่านผู้ใช้งานระบบโดยสมบูรณ์ ถือเป็นความวิบัติใหญ่หลวงอย่างมาก ดังนั้นผู้เขียนกราบวิงวอนผู้อ่านทุกท่านว่า อย่าหาทำ วิธีนี้เลย
ระดับดีขึ้นมานิด (แต่ยังไม่พอ)
ระดับที่ดีขึ้นมาอีกขึ้นหนึ่ง คือ การใช้ฟังก์ชันแฮชมาครอบตัวรหัสผ่านของผู้ใช้ตอนลงทะเบียน และตอนลงชื่อเข้าใช้งาน ตัวอย่างเช่น หากผู้ใช้งานกรอกรหัสผ่านตอนลงทะเบียนมาเป็น “good_to_guess” ก็จะถูกนำไปผ่านฟังก์ชันแฮชก่อนนำไปเก็บลงฐานข้อมูล ตัวอย่าง ในภาษา python
การทำเช่นนี้ถือว่าดีกว่าการเก็บแบบโต้ง ๆ อย่างแน่นอน แต่ตัวอย่างด้านบนก็ยังไม่ควรทำอยู่ดี เพราะหากผู้โจมตีระบบสามารถลงทะเบียนสมัครสมาชิกได้ และสามารถเข้าถึงฐานข้อมูลตารางผู้ใช้งานได้อีก ผู้โจมตี อาจ คาดเดารหัสผ่านของผู้ใช้คนอื่นได้ ตัวอย่างเช่น บังเอิญผู้โจมตีใส่รหัสผ่านเป็น “good_to_guess” เหมือนกับผู้ใช้ด้านบน จะส่งผลให้ hashed_password นั้น เหมือนกัน นั่นก็แปลว่าผู้โจมตีรู้รหัสผ่านของผู้ใช้คนนั้นโดยปริยาย
การใช้ฟังก์ชันแฮชมาครอบนั้น ยังสามารถทำให้ดีได้อีกระดับหนึ่ง คือ เติมเกลือเข้าไปด้วยซึ่งก็ถือว่าดีกว่าเดิม เพราะผู้โจมตีไม่สามารถล่วงรู้รหัสผ่านของผู้ใช้งานคนอื่นได้ หากกรอกรหัสผ่านเหมือนกัน ตัวอย่างในภาษา python
อย่างไรก็ดีวิธีการนี้ก็ยังไม่ปลอดภัยจากการโจมตีแบบ Length Extension Attack อยู่ดี ดังนั้นเราก็ควรเลี่ยงวิธีนี้เช่นกัน
ระดับพอได้ (แต่ยังดีได้อีก)
วิธีการคือใช้ HMAC เป็น KDF เลย ซึ่งเรียกว่า HKDF (HMAC-based KDF) หรือ hmac_func(salt, password, hash_func) ตัวอย่างเช่น เราสามารถใช้ตัวอย่างรหัสต้น HMAC มาเป็นแปลงเป็นตัวอย่างได้ เช่น
อย่างไรก็ดี วิธีนี้ก็ยังปลอดภัยน้อยกว่าแนวทางสุดท้ายนั่นก็คือ
ควรทำ ทำเถอะไม่ยากเลย
สิ่งที่ควรทำที่สุดก็คือ การใช้ library เพื่อใช้เป็น KDF ตัวอย่างเช่น Bcrypt, Scrypt หรือ Argon2 โดยหลักแล้ว สิ่งที่เราจะต้องเก็บเพิ่มนอกเหนือจาก hashed_password และ salt คือ setting ของอัลกอริทึมที่เราเลือกใช้ ซึ่งโดยส่วนใหญ่ library ใหม่ ๆ จะเก็บสามสิ่งมัดรวมไว้เป็นสายอักขระเดียว เพื่อให้เราสามารถเก็บไว้ในฐานข้อมูลได้ง่าย จากที่จะต้องเก็บข้อมูลในหลายคอลัมน์เป็นคอลัมน์เดียว ในที่นี้ขอตัวอย่าง ใน python ของ Argon2
การเข้ารหัสลับ (Encryption)
การเข้ารหัสลับ (Encryption) นั้น ทำเพื่อรักษาความลับของสาร ดังนั้นจะมีเรื่องกุญแจ (Key) เข้ามาเกี่ยวข้อง เนื่องจากการเข้ารหัสลับจะใช้กุญแจทั้งในกระบวนการเข้ารหัสลับ และกระบวนการถอดรหัสลับ เราสามารถแบ่งประเภทการเข้ารหัสลับตามลักษณะของกุญแจที่ใช้ ออกเป็นสองลักษณะใหญ่ดังนี้
  • 1.
    การเข้ารหัสลับแบบกุญแจสมมาตร (Symmetric Key Encryption)
  • 2.
    การเข้ารหัสลับแบบกุญแจอสมมาตร (Asymmetric Key Encryption)
ในบทความนี้ จะกล่าวถึงเฉพาะกุญแจสมมาตรก่อน ส่วนกุญแจอสมมาตรจะอยู่ในบทความถัด ๆ ไป
การเข้ารหัสลับแบบกุญแจสมมาตร (Symmetric Key Encryption)
อวจ: encrypt(สาร, กุญแจ, อย่างอื่นถ้ามี) -> สารที่แปลงแล้ว ; decrypt(สารที่แปลงแล้ว, กุญแจ, อย่างอื่นถ้ามี) -> สาร
การเข้ารหัสลับ และการถอดรหัสลับโดยใช้กุญแจสมมาตรนั้น เราจะใช้กุญแจ ดอกเดียวกัน ทั้งการเข้ารหัสลับ และการถอดรหัสลับ ดังรูป
รูปที่ 3 การเข้ารหัสลับแบบกุญแจสมมาตร
โดยปกติแล้ว การเข้ารหัสลับแบบกุญแจสมมาตรจะไม่ได้ใช้อัลกอริทึมเข้ารหัสลับอย่างเดียว แต่จะมีการตัดสารออกเป็นก้อน (Block) ภายในกล่อง “กระบวนการเข้ารหัสลับแบบกุญแจสมมาตร” ด้านล่าง คือ P0 จนถึง Pn โดยแต่ละก้อนมีขนาดเท่า ๆ กัน แล้วจึงนำก้อนแต่ละก้อนไป ผสมผสานกับฟังก์ชันอื่น (มีรายละเอียดใน รูปที่ 5) กระบวนการของการเข้ารหัสแบบกุญแจสมมาตรโดยทั่วไปจะประกอบด้วย
  • KDF
  • กระบวนการเข้ารหัสลับแบบกุญแจสมมาตร (Block Cipher Mode & Block Cipher Algorithm)
  • MAC
เรารู้จักกับ KDF และ MAC ไปแล้ว ส่วน Block Cipher Algorithm นั้น เป็นอัลกอริทึมการเข้ารหัสลับแบบกุญแจสมมาตรจริง ๆ เช่น AES และ ChaCha20 ซึ่งจะฝังอยู่ใน Block Cipher Mode ส่วน Block Cipher Mode คือ วิธีจัดการกับข้อมูลที่ตัดเป็นก้อนแล้ว ซึ่งมีหลายวิธี อาทิเช่น CBC, CTR และ GCM ใน Block Cipher Mode แต่ละตัวนั้นก็จะมีคุณสมบัติแตกต่างกันไป แต่ผู้เขียนจะไม่ลงลึกไปกว่านี้ เพราะจะทำให้บทความนี้ยาวเกินไป แต่จะขอยกบางคุณสมบัติคร่าว ๆ อาทิเช่น
  • CBC ต้องมีการทำ Padding ข้อมูลก้อนสุดท้ายด้วยอักขระพิเศษที่กำหนดเนื่องจาก CBC ใช้วิธีการตัดข้อมูลจริง ๆ ไม่ได้ใช้ XOR Operation เหมือนกับวิธีอื่น
  • GCM มีการทำ MAC ให้อยู่ภายในตัวแล้ว แบบ encrypt-then-MAC
กระบวนการเข้ารหัสลับจากผู้รับสาร แล้วส่งไปยังช่องทางสื่อสาร จนถึงผู้รับสารดำเนินกระบวนการถอดรหัสลับ สามารถแสดงออกมาเป็นภาพได้ดังนี้
รูปที่ 4 กระบวนการเข้ารหัสจนถึงถอดรหัสลับแบบกุญแจสมมาตร
ซึ่งภายในกล่อง “กระบวนการเข้ารหัสลับแบบกุญแจสมมาตร” จะมีกลไกโดยภาพรวม ดังภาพด้านล่าง
รูปที่ 5 แสดงกลไกภายในกล่อง “กระบวนการเข้ารหัสลับแบบกุญแจสมมาตร” ใน รูปที่ 4
ผลลัพธ์ที่ได้จากกล่อง “กระบวนการเข้ารหัสลับแบบกุญแจสมมาตร” คือ ก้อนสารที่เข้ารหัสแล้วคือ C0 จนถึง Cn ซึ่งถูกนำมารวมกันเป็นก้อนเดียวอีกครั้ง เป็นสารที่ถูกเข้ารหัสลับ (Ciphertext)
การเรียกชื่อของการเข้ารหัสลับแบบกุญแจสมมาตรจะใช้รูปแบบ [ชื่อ Block Cipher Algorithm ที่ใช้]-[ความยาวของกุญแจเป็น bit ที่กับ Block Cipher Algorithm]-[ชื่อ Block Cipher Mode] อาจจะจำย่อๆ เป็น [Block Cipher Algorithm]-[Key Length]-[Block Cipher Mode] ตัวอย่างเช่น ชื่อการเข้ารหัสลับ AES-256-GCM
ผู้เขียนขอจบพื้นฐานการเข้ารหัสลับในตอนแรกไว้เพียงเท่านี้ หากผู้อ่านทุกท่านรู้สึกว่า ต้องการแสดงความเห็น ต้องการให้ข้อมูลเพิ่มเติม หรือพบข้อผิดพลาดประการใด ผู้เขียนขอน้อมรับไว้ทุกสิ่ง เมื่อผู้อ่านเดินทางมาถึงตรงนี้แล้ว ผู้เขียนคิดว่าบทความนี้จะทำให้ผู้อ่านเข้าใจเรื่องการเข้ารหัสลับมากขึ้นไม่มากก็น้อย และจะเป็นการดียิ่งขึ้น หากผู้อ่านสามารถนำไปต่อยอดในการพัฒนาโปรแกรมให้ดียิ่งขึ้น และในตอนต่อไป (อาจจะไม่ใช่เร็ว ๆ นี้) ผู้เขียนจะกล่าวถึง การเข้ารหัสลับแบบกุญแจอสมมาตร กันโดยละเอียดอีกครั้ง ขอบคุณครับ
อีกสักนิดก่อนจากกัน ผู้เขียนขอแนะนำบทความด้านล่างนี้ สำหรับผู้ที่สนใจเกี่ยวกับความลับของข้อมูล และการเข้ารหัสเพิ่มเติม
การจัดทำข้อมูลนิรนาม (Data Anonymization)
Searchable Encryption กลไกการปกป้องข้อมูลบน Cloud ที่คุณไว้วางใจได้
เนื้อหาโดย ประณิธาน ธรรมเจริญพร
ตรวจทานและปรับปรุงโดย เมธิยาภาวิ์ ศรีมนตรินนท์
โฆษณา