Encryption Field 101 + ทำหน้าบ้านให้ปลอดภัยขึ้น
อธิบายแบบง่ายที่สุด: มี HTTPS แล้วทำไมต้องเข้ารหัสอีก, browser ไม่มี secret แล้วล็อกข้อมูลยังไง, ทำงานคู่กับลายเซ็นยังไง และวิธีอุดจุดอ่อนร่วมของทั้งระบบ (XSS) — พร้อม sequence diagram
อัปเดต: 2026-08-04
Encryption Field 101 + ทำหน้าบ้านให้ปลอดภัยขึ้น
เล่มคู่ของ Body Signature 101 — เล่มนั้นตอบเรื่อง “ลายเซ็น” (กันปลอม) เล่มนี้ตอบเรื่อง “การเข้ารหัส” (กันอ่าน) และปิดท้ายด้วยวิธีทำให้หน้าบ้านแข็งแรงขึ้นทั้งระบบ
⚠️ สถานะ: encryption field (ชั้น 3) ยังเป็นร่าง design ยังไม่ freeze — หลักการในเล่มนี้คือทิศทางที่ตกลงกันแล้ว แต่รายละเอียด (สูตร, รูปแบบ envelope) ยังเปิดอยู่ 6 ประเด็น ดูภาพระบบข้อ 5.4
คำถามที่ 1: เว็บเราเป็น HTTPS อยู่แล้ว ทำไมต้องเข้ารหัสซ้ำอีก
HTTPS (TLS) เข้ารหัสแบบ “ท่อต่อท่อ” ไม่ใช่ “ต้นทางถึงปลายทาง” — ระหว่างทางข้อมูลของเราวิ่งผ่านตัวกลางหลายตัว และทุกข้อต่อ ข้อมูลถูกแกะออกมาเป็นตัวหนังสือโล้นๆ ชั่วคราว:
sequenceDiagram
participant B as Browser
participant CF as Cloudflare (WAF)
participant GW as App GW (L7)
participant BE as Backend
Note over B,BE: HTTPS จริงๆ คือท่อเข้ารหัส "หลายท่อนต่อกัน" ไม่ใช่ท่อเดียวยาวถึงปลายทาง
B->>CF: 🔒 ท่อนที่ 1 (เข้ารหัส)
Note over CF: แกะออกอ่านได้เต็มๆ ตรงนี้<br/>(WAF ต้องอ่านเพื่อตรวจ traffic)
CF->>GW: 🔒 ท่อนที่ 2 (เข้ารหัสใหม่)
Note over GW: แกะออกอ่านได้อีกที่
GW->>BE: 🔒 ท่อนที่ 3
Note over BE: ปลายทางตัวจริง
แปลว่า เลขบัญชี เลขบัตร ข้อมูลส่วนตัว — ตัวกลางทุกตัวที่ยืนอยู่ตรงข้อต่อเห็นหมด ไม่ใช่เพราะใครทำผิด แต่เพราะหน้าที่ของมัน (WAF ต้องอ่าน traffic ถึงจะกรองได้)
Encryption field แก้ตรงนี้: ล็อกเฉพาะ field ที่อ่อนไหวตั้งแต่ในเครื่องผู้ใช้ แล้วไปเปิดได้ที่ backend ปลายทางเท่านั้น — ตัวกลางยังทำงานของมันได้ตามปกติ (เห็น request, เห็น header, กรอง traffic ได้) แต่ field ที่ล็อกไว้กลายเป็นก้อนขยะอ่านไม่ออกสำหรับมัน
คำถามที่ 2: browser ห้ามถือ secret แล้วจะเข้ารหัสได้ยังไง
ใช้กุญแจคู่อีกชุดหนึ่ง — แต่คราวนี้กลับด้านกับลายเซ็น: เจ้าของกุญแจคือ backend ไม่ใช่ browser
นึกภาพแม่กุญแจกับลูกกุญแจ:
| อยู่ที่ไหน | ทำอะไรได้ | ถ้าคนอื่นได้ไป | |
|---|---|---|---|
| public key (แม่กุญแจ) | แจกให้ browser ทุกเครื่อง — แจกฟรี ใครเห็นก็ได้ | ล็อกได้อย่างเดียว | ไม่เป็นไรเลย — ได้แม่กุญแจไปก็ทำได้แค่ล็อก เปิดไม่ได้ |
| private key (ลูกกุญแจ) | ใน Key Vault ของ backend ไม่เคยออกไปไหน | เปิดล็อก | เป็นไปไม่ได้ — ไม่เคยเดินทางออกจาก server |
browser จึงไม่ต้องถือความลับอะไรเลย — มันถือแค่ “แม่กุญแจ” ซึ่งเป็นของสาธารณะ · เหมือนกับที่ฝั่งลายเซ็น browser ถือแค่ตราประทับที่ล้วงออกมาไม่ได้ — ทั้งสองชั้นยึดหลักเดียวกัน: ไม่มีของลับในหน้าบ้าน
มีรายละเอียดทางเทคนิคอีกชั้น: ของจริงไม่ได้เอาแม่กุญแจล็อกข้อมูลตรงๆ (มันช้ากับข้อมูลก้อนใหญ่) — browser จะสุ่มกุญแจชั่วคราวขึ้นมาใหม่ทุก request ใช้ล็อกข้อมูลจริง แล้วเอาแม่กุญแจล็อก “ตัวกุญแจชั่วคราว” นั้นอีกที ส่งไปด้วยกัน (เรียกว่า hybrid encryption):
sequenceDiagram
participant B as Browser
participant BE as Backend
Note over B: ครั้งแรก (หรือตาม cache)
B->>BE: ขอ public key (แม่กุญแจ) — เป็นของแจกฟรี
BE-->>B: ส่งให้ ไม่มีอะไรต้องปกปิด
Note over B: ทุก request ที่มี field อ่อนไหว
B->>B: ① สุ่มกุญแจชั่วคราว (ใช้ครั้งเดียวทิ้ง)
B->>B: ② ล็อก field อ่อนไหวด้วยกุญแจชั่วคราว
B->>B: ③ เอาแม่กุญแจล็อก "ตัวกุญแจชั่วคราว" อีกชั้น
B->>BE: ④ ส่ง: { กุญแจชั่วคราวที่ถูกล็อก + ข้อมูลที่ถูกล็อก }
Note over B,BE: ตัวกลางทุกตัวระหว่างทางเห็นแค่ก้อนขยะ 2 ก้อน
BE->>BE: ⑤ ใช้ลูกกุญแจ (จาก Key Vault) เปิดเอากุญแจชั่วคราวออกมา
BE->>BE: ⑥ ใช้กุญแจชั่วคราวเปิดข้อมูล → ได้ field ตัวจริง
ทำไมต้องสุ่มใหม่ทุกครั้ง? — เพราะกุญแจชั่วคราวใช้แล้วทิ้ง ต่อให้ใครเจาะได้สัก request (ซึ่งยากมากอยู่แล้ว) ก็เปิดได้แค่ request เดียว ไม่มี “กุญแจสะสม” ให้ขโมย
คำถามที่ 3: แล้วทำงานร่วมกับลายเซ็น (body signature) ยังไง
กติกาตายตัว: ล็อกก่อน แล้วค่อยประทับตรา (encrypt → sign) และฝั่งรับก็กลับลำดับ: ตรวจตราก่อน แล้วค่อยเปิดล็อก (verify → decrypt)
ฝั่ง browser: payload → เข้ารหัส field → ได้ body สุดท้าย → เซ็นทับ body สุดท้ายนั้น
ฝั่ง backend: ตรวจลายเซ็นจาก body ตามที่ได้รับ (ยังล็อกอยู่) → ผ่านแล้วค่อยเปิดล็อก
เหตุผล 2 ข้อ:
- ตรวจของถูกก่อนเสียแรงเปิด — request ปลอม/ถูกแก้ ตายตั้งแต่ด่านลายเซ็น (401) โดย backend ไม่ต้องเสียแรงถอดรหัสเลย
- ตราครอบทั้งกล่อง — ลายเซ็นทับก้อนที่ล็อกแล้วทั้งก้อน ใครสลับ/ตัดต่อชิ้นส่วนของกล่องระหว่างทาง ลายเซ็นพังทันที
จุดที่คนมักงง (มาจากคำถามจริงตอนคุยเรื่องลายเซ็น): “server ตรวจลายเซ็นได้ยังไงในเมื่อ body ถูกเข้ารหัส?” — ได้สบายมาก เพราะลายเซ็นถูกประทับทับก้อนที่ล็อกแล้ว server แค่เอาก้อนที่อยู่ในมือ (ยังล็อกอยู่) ไปเช็คสมการตามปกติ ไม่ต้องเปิดล็อกก่อนตรวจ — รายละเอียดเรื่องเช็คสมการอ่านที่ Body Signature 101 คำถามที่ 3
คำถามที่ 4: ขากลับ (backend ตอบมา) เข้ารหัสไหม
มติ Owner 04/08/2026: ต้องทำด้วย — ขากลับไม่ใช่ของแถม เหตุผลตรงไปตรงมา: response มักถือข้อมูลอ่อนไหวหนักกว่าขาไปด้วยซ้ำ — เรียกดูโปรไฟล์ครั้งเดียว เลขบัตรประจำตัวประชาชน เลขบัญชี ที่อยู่ ไหลกลับมาทั้งชุด และจุดเปิดเผยคือจุดเดียวกับขาไปเป๊ะ: ข้อต่อที่แกะ TLS อ่านได้หมด
(เกร็ดความแม่นยำ: response ไม่ได้ “โล้นๆ บน network” — ในสายมันอยู่ใต้ TLS เสมอ คนดักสายมองไม่เห็น · จุดที่เห็นคือข้อต่อที่แกะท่อ ซึ่งเพียงพอแล้วที่จะต้องปิดด้วยหลัก end-to-end เดียวกับขาไป)
วิธีทำ — สมมาตรกับขาไป แค่สลับบทบาท: คราวนี้ browser ต้องมี “แม่กุญแจ” ของตัวเองบ้าง — สร้างกุญแจคู่ชุดที่ 2 ในตู้เซฟเดียวกัน (คนละชุดกับลายเซ็น เพราะกุญแจลายเซ็นเซ็นได้อย่างเดียว ล็อก/เปิดไม่ได้) แล้วฝาก public key ขึ้นไปพร้อม flow ลงทะเบียนเดิม
sequenceDiagram
participant B as Browser
participant BE as Backend
Note over B: ตอนลงทะเบียน (ครั้งเดียวต่อเครื่อง)
B->>B: สร้างกุญแจคู่ชุดที่ 2 — สำหรับ "รับของ"
B->>BE: ฝากแม่กุญแจของ browser (public key ชุดที่ 2)
Note over BE: ทุก response ที่มี field อ่อนไหว
BE->>BE: ① สุ่มกุญแจชั่วคราว → ล็อก field
BE->>BE: ② เอาแม่กุญแจของ browser ล็อกตัวกุญแจชั่วคราว
BE-->>B: ③ ส่ง envelope กลับ — ข้อต่อกลางทางเห็นแต่ก้อนขยะ
B->>B: ④ เปิดด้วยลูกกุญแจในตู้เซฟ (ชุดที่ 2) → ได้ข้อมูลจริง
ลำดับการสร้าง: ขาไปก่อน → ขากลับตามทันที — เหตุผลเชิง engineering ล้วนๆ (ขาไปพิสูจน์กลไก envelope + การแจก key ให้จบก่อน ขากลับ reuse ของเดิมเกือบทั้งหมด) — ไม่ใช่ optional และไม่ใช่ “ค่อยว่ากัน”
กติการะหว่างที่ยังไม่มา (บังคับ — ไม่งั้นช่องเปิดค้าง): field อ่อนไหวใน response ให้ backend mask เสมอ เมื่อหน้าจอไม่จำเป็นต้องใช้ค่าเต็ม — เช่น เลขบัตรประชาชนส่ง x-xxxx-xxx45-67-8 แทนเลขเต็ม · หน้าจอส่วนใหญ่ต้องการแค่ให้ผู้ใช้ยืนยันว่า “ใช่เลขนี้” ไม่ได้ต้องการเลขเต็ม — ลดของอ่อนไหวบน wire ได้ทันทีโดยไม่ต้องรอ crypto
ข่าวดี: วิธีเข้ารหัสที่ใช้ (AES-GCM) ตรวจจับการแก้ไขได้ในตัวมันเอง — response ถูกแก้ = เปิดล็อกไม่ออก — จึงไม่ต้องเพิ่มลายเซ็นขากลับอีกชั้นให้ซ้ำซ้อน
คำถามที่ 5: จุดอ่อนร่วมของทุกชั้นคืออะไร — และทำหน้าบ้านให้ปลอดภัยขึ้นยังไง
หัวข้อนี้มีเล่มเต็มแยกแล้ว: Frontend Hardening 101 — เจาะลึกว่า XSS เข้าทางไหน, CSP/Trusted Types/WebAuthn ทำงานยังไงทีละ diagram, และถ้าเกิดจริงอะไรเสียหาย-อะไรรอด · ข้างล่างนี้คือฉบับย่อ
ทั้งลายเซ็นและการเข้ารหัส มีศัตรูร่วมตัวเดียวกัน: XSS — สคริปต์แปลกปลอมที่หลุดเข้ามารันในหน้าเว็บเรา
ทำไมสองชั้นนี้ช่วยไม่ได้: สคริปต์ที่รันในหน้าเดียวกัน มีสิทธิ์เท่ากับโค้ดของเราเป๊ะ — มันขโมยตราประทับไม่ได้ (non-extractable) แต่สั่งประทับได้ · มันขโมยกุญแจไม่ได้ แต่อ่านข้อมูลบนหน้าจอก่อนถูกล็อกได้ · browser แยกไม่ออกว่าใครเป็นคนเรียก
วิธีทำให้หน้าบ้านแข็งแรงขึ้น เรียงตามลำดับความสำคัญ:
| # | มาตรการ | กันอะไร | สถานะของเรา |
|---|---|---|---|
| 1 | CSP แบบเข้มงวด (nonce-based) — browser จะรันเฉพาะสคริปต์ที่มี “รหัสผ่านประจำรอบ” ที่ server แจกเท่านั้น | ตัดทางสคริปต์แปลกปลอมตั้งแต่ก่อนมันได้รัน — แก้ที่ต้นเหตุของ XSS | track แยกใน security uplift (IMPL_PLAN_10) — ยังไม่เริ่ม |
| 2 | Trusted Types — ห้ามยัด string ดิบเข้า DOM ตรงๆ (จุดเกิด DOM-XSS) | XSS สายที่เกิดจากโค้ดเราเองเผลอประกอบ HTML จาก input | ไปด้วยกันกับข้อ 1 |
| 3 | Supply-chain scan — ตรวจ dependency ที่ใช้ว่ามีตัวไหนโดนฝังของ | XSS ที่มากับ library ที่เรา import เอง | ✅ มีแล้ว — SBOM + Dependency-Track ใน CI ของ FE |
| 4 | WebAuthn step-up สำหรับ operation มูลค่าสูง — ลายเซ็นที่ต้องมีการกดของมนุษย์จริง (แตะ fingerprint / security key) | เป็น primitive เดียวที่ XSS สั่งเงียบๆ ไม่ได้ — ต่อให้สคริปต์ร้ายรันอยู่ ก็บังคับนิ้วผู้ใช้ไม่ได้ | อนาคต — สำหรับ operation ระดับโอนเงิน/เปลี่ยนข้อมูลสำคัญ |
| 5 | หลักการที่ถืออยู่แล้ว: ไม่มี secret ใดๆ ใน bundle/config ของ FE · cookie เป็นแค่ตัวชี้ session (token จริงอยู่ server) | จำกัดความเสียหาย — ต่อให้ XSS เกิด ก็ไม่มีของลับให้ขโมยออกไปใช้ที่เครื่องอื่น | ✅ เป็นหลักของ architecture ทั้งระบบอยู่แล้ว |
มองรวมกันเป็นภาพเดียว: ชั้น 1-3 กันภัยจากนอกเครื่อง (ขโมย cookie, แก้ข้อมูลกลางทาง, ดักอ่าน) ส่วนมาตรการในตารางนี้กันภัยจากในหน้าเว็บเอง (สคริปต์แปลกปลอม) — ต้องมีทั้งสองด้านถึงเรียกว่าหน้าบ้านปลอดภัยจริง
ศัพท์ที่เจอบ่อย
| ศัพท์ | แปลว่า |
|---|---|
| TLS / HTTPS | ท่อเข้ารหัสระหว่างจุดต่อจุด — ปลอดภัยในท่อ แต่ถูกแกะที่ข้อต่อ |
| terminate TLS | จุดที่ท่อเข้ารหัสสิ้นสุดและข้อมูลถูกแกะออกอ่าน (Cloudflare, App GW, APIM) |
| end-to-end (E2E) | ล็อกจากต้นทางจริง เปิดที่ปลายทางจริง — ตัวกลางอ่านไม่ได้เลย |
| hybrid encryption | สุ่มกุญแจชั่วคราวล็อกข้อมูล แล้วเอาแม่กุญแจ (public key) ล็อกตัวกุญแจชั่วคราวอีกชั้น |
| ephemeral key | กุญแจชั่วคราวที่สุ่มใหม่ทุก request ใช้แล้วทิ้ง |
| AES-GCM | สูตรล็อกข้อมูลที่ตรวจจับการแก้ไขได้ในตัว (เปิดไม่ออกถ้าถูกแก้) |
| envelope | ก้อนที่ส่งจริง = กุญแจชั่วคราวที่ถูกล็อก + ข้อมูลที่ถูกล็อก |
| encrypt-then-sign | กติกาลำดับ: ล็อกก่อน → เซ็นทับก้อนที่ล็อกแล้ว |
| XSS | สคริปต์แปลกปลอมที่หลุดมารันในหน้าเว็บเรา — จุดอ่อนร่วมที่ crypto ช่วยไม่ได้ |
| CSP (nonce-based) | กฎบอก browser ว่ารันได้เฉพาะสคริปต์ที่มีรหัสประจำรอบจาก server |
| Trusted Types | กฎห้ามยัด string ดิบเข้า DOM — กัน DOM-XSS |
| WebAuthn | ลายเซ็นที่ต้องมีการกดของมนุษย์จริง — XSS สั่งแทนไม่ได้ |
อ่านต่อ
- Frontend Hardening 101 — เล่มเต็มของคำถามที่ 5: ปิดจุดอ่อนร่วม (XSS) ทีละมาตรการ
- Body Signature 101 — เล่มคู่กัน: ลายเซ็นทำงานยังไง ทำไมปลอมไม่ได้
- ภาพระบบ 3 ชั้น (Target Architecture) — encryption field อยู่ตรงไหนของระบบใหญ่ + 6 ประเด็นที่ยังต้องตัดสินก่อน implement (ข้อ 5.4)
- แผน Implement รอบ POC — งานรอบปัจจุบัน (ลายเซ็นฝั่ง backend)