การเข้ารหัสข้อมูลจาก Angular และถอดรหัสข้อมูลบน .NET 5 โดยใช้อัลกอริทึมแบบอสมมาตร (Asymmetric key algorithms)
สวัสดีครับผู้อ่านทุกท่าน วันนี้ผมมีบทความมาฝาก ว่าด้วยเรื่องของการเข้ารหัสข้อมูลนั่นเอง บทความนี้ผมจะเลือกใช้ Angular สำหรับทำ Frontend เล็ก ๆ เพื่อยกตัวอย่างให้เห็นการประยุกต์ใช้งาน Library ที่ใช้สำหรับเข้ารหัสข้อมูลด้วย Public key ผ่าน Javascript และการประยุกต์ใช้งานบนฝั่ง API (.NET 5) เพื่อถอดรหัสข้อมูลด้วย Private key
ก่อนจะเริ่มเข้าสู่รายละเอียด ผมขออธิบายคำศัพท์ที่เกี่ยวข้องสักเล็กน้อย สำหรับผู้ที่ไม่ได้อยู่ในแวดวงไอที จะได้ทำความเข้าใจไปด้วยกันครับ
อัลกอริทึมแบบอสมมาตร (Asymmetric key algorithms)
คือขั้นตอนหรือลำดับการประมวลผลในการเข้ารหัสข้อมูล โดยใช้กุญแจสองดอกเป็นเครื่องมือในการเข้ารหัส ดังนี้
กุญแจสาธารณะ (Public key) คือกุญแจที่เราเปิดเผยต่อสาธารณชนบนเครือข่ายอินเทอร์เน็ต ใครก็สามารถนำกุญแจนี้ไปใช้เข้ารหัสข้อมูลได้ แต่จะไม่สามารถถอดรหัสข้อมูลออกมาอ่านได้
กุญแจส่วนตัว (Private key) คือกุญแจที่เราต้องเก็บรักษาเป็นความลับยิ่งชีพ เพราะเราต้องใช้มันถอดรหัสข้อมูลที่ถูกเข้ารหัสด้วยกุญแจสาธารณะ (Public key) หากเราทำกุญแจนี้หาย เราจะไม่สามารถถอดรหัสข้อมูลนั้นได้เลย กุญแจนี้ห้ามเปิดเผยให้ใครรู้เด็ดขาด
เพื่อให้เห็นภาพที่ชัดเจนมากขึ้น ผมขอยกตัวอย่าง กรณีศึกษาจากเว็บไซต์ เราชนะ
เมื่อเรากรอกข้อมูลส่วนตัวลงไป และกดปุ่มตรวจสอบสถานะ จะมีสิ่งที่เรียกว่า Request เกิดขึ้น ซึ่ง Request ดังกล่าวจะวิ่งผ่านเครือข่ายอินเทอร์เน็ต (Network) ไปยัง API ปลายทาง พร้อมด้วยข้อมูลส่วนตัวของเราที่แนบไปกับ Request ดังภาพประกอบด้านล่าง
จากตัวอย่างที่ผมยกมาข้างต้น จะเห็นว่าข้อมูลส่วนตัวของเราถูกแนบไปกับ Request ซึ่งเราเรียกว่า Payload
ข้อมูลบางส่วนจะถูกเข้ารหัสไว้ เพื่อความปลอดภัยของเจ้าของข้อมูล หากเกิดกรณีผู้ไม่หวังดีแอบดักข้อมูล จะไม่สามารถนำข้อมูลดังกล่าวไปใช้ประโยชน์ได้ เนื่องจากไม่มีกุญแจส่วนตัว (Private Key) สำหรับถอดรหัสข้อมูล
ดังนั้นการเลือกใช้อัลกอริทึมแบบอสมมาตร เพื่อเข้ารหัสและถอดรหัสข้อมูล จึงมีความปลอดภัยมากกว่าการเข้ารหัสและถอดรหัสที่ใช้กุญแจดอกเดียวกัน (อัลกอริทึมแบบสมมาตร)
ลองจินตนาการง่าย ๆ ว่าคุณพัฒนาเว็บไซต์ขึ้นมา 1 เว็บไซต์ และจัดเก็บกุญแจ (Key) เอาไว้ที่ Javascript และคุณจะหยิบมาใช้ตอนเข้ารหัสข้อมูลก่อนส่งไปให้ API
คุณอาจพบความจริงอันโหดร้ายที่ว่า ผู้ไม่หวังดี สามารถถอดรหัสข้อมูลออกมาได้โดยง่าย ด้วยกุญแจ (Key) ที่ฝังไว้ใน Javascript ซึ่งเป็นดอกเดียวกันกับที่คุณใช้เข้ารหัสข้อมูลไปหยก ๆ
นั่นจึงเป็นที่มาว่าเราจะต้องมีกุญแจคนละดอกนั่นเอง และกุญแจนั้นจะต้องมีความแข็งแกร่งมากพอต่อการคาดเดาด้วย
สมมุติฐาน
ถ้าเรามีคู่กุญแจ 1 คู่ เราจะต้องเข้ารหัสด้วย Public key และถอดรหัสด้วย Private key ได้อย่างถูกต้อง
มาเริ่มลง Technical กันดีกว่า
บทความนี้ ผมจะใช้ Angular 11 เรียกใช้งาน Library JSEncrypt ตรง ๆ ผ่านวิธีการง่าย ๆ ดังนี้
1) ดาวน์โหลด Library ที่ชื่อว่า JSEncrypt จาก https://travistidwell.com/jsencrypt/
2) แตกไฟล์ที่ดาวน์โหลดมา จากนั้นเข้าไปที่ Folder ชื่อ bin ให้ทำการคัดลอก (Copy) ไฟล์ที่ชื่อว่า jsencrypt.min.js และนำไปวางไว้ที่ Folder src/assets/js ของ Project Angular ดังภาพ
3) แก้ไขไฟล์ angular.json ให้ทำการ Include Library ตัวนี้เข้ามาด้วยทุกครั้ง เวลาที่สั่ง Build Project
4) สร้าง Public key และ Private key ขึ้นมา 1 คู่
สำหรับบทความนี้ ผมแนะนำให้ไปสร้างคู่กุญแจ 1 คู่ โดยกำหนดขนาดกุญแจ (Key Size) เท่ากับ 2,048 bit จากเว็บนี้ครับ https://travistidwell.com/jsencrypt/demo/
5) คัดลอก (Copy) Public key ที่สร้างมาแล้ว ไปไว้ในไฟล์ environment.ts ตาม Code ตัวอย่างด้านล่างนี้ครับ
6) ลองเขียน ฟังก์ชันง่าย ๆ ที่ app.component.ts เพื่อทำการเข้ารหัสข้อมูลด้วย Public key ดังตัวอย่างด้านล่างนี้ครับ ผมจะทำการเข้ารหัสคำว่า “SURASAK”
7) ลอง Run project ขึ้นมาด้วยคำสั่ง ng serve จะเห็นผลลัพธ์ที่ Console ดังภาพ
ลำดับต่อไป จะเป็นส่วน Backend
เราจะสร้าง API กาก ๆ ขึ้นมา 1 เส้น ที่มี Logic ทุกอย่างอยู่ในที่เดียวกัน โดยมีวัตถุประสงค์เพื่อรับค่าที่ถูกเข้ารหัสไว้จาก Frontend จากนั้นก็ถอดรหัสด้วย กุญแจส่วนตัว (Private key) เพื่อดูข้อมูลต้นฉบับ
8) สร้าง API Controller ใหม่ ภายใต้ Folder Controllers ชื่อ SampleController.cs ตาม Code ตัวอย่างด้านล่างนี้ครับ
9) เปลี่ยนค่าในตัวแปร privateKey ในบรรทัดที่ 29 เป็น Private key ที่คุณสร้างไว้ในข้อ 4) จากนั้นทดลอง Run Project ด้วยคำสั่ง dotnet run
10) คัดลอก ข้อมูลที่ถูกเข้ารหัสไว้ ดังที่แสดงอยู่ใน Console ข้อ 7) มาทดลองยิง API โดยใช้ Swagger ที่ติดตั้งมาพร้อมกับ Project ดังภาพ
11) สังเกตที่ Response ของ Swagger จะเห็น Response body ดังภาพ ซึ่งเป็นประโยคว่า “Original data is SURASAK” แสดงว่า การถอดรหัสด้วย Private key ทำงานได้อย่างถูกต้อง
คำแนะนำเพิ่มเติม
- การกำหนดขนาดกุญแจ มีผลต่อความเร็วและความปลอดภัย ในการเข้ารหัส/ถอดรหัสข้อมูล อ่านเพิ่มเติมได้ที่ https://csrc.nist.gov/Projects/Key-Management/publications
- เพื่อความปลอดภัยของระบบ ผู้พัฒนาโปรแกรม ควรจัดเก็บ Private key แยกจาก Source code เพื่อป้องกันกรณี Repository ถูกโจมตีโดยผู้ไม่หวังดี และเปิดเผย Source code ต่อสาธารณะ
ดาวน์โหลด Source code มาลองเล่นได้ จากลิงค์นี้เลยครับ
ขอบคุณที่ติดตามอ่านจนจบครับ แล้วพบกันใหม่ครั้งหน้าครับ