WebAuthn Data Decoder: ถอดรหัส Payload ของ Passkey ได้ในเบราว์เซอร์
ถอดรหัส WebAuthn passkey registration และ authentication payload: clientDataJSON, attestationObject CBOR, authenticator flags, AAGUID, credential ID และ COSE public key — ทำงานในเบราว์เซอร์ 100%
Table of Contents
WebAuthn Data Decoder: ถอดรหัส Payload ของ Passkey ได้ในเบราว์เซอร์
ตอนนี้ passkey อยู่ทุกที่แล้ว ทั้งบัญชี Google, Apple และ Microsoft ใช้มันปกป้องผู้ใช้ เว็บและแอปสาย enterprise ก็เริ่มใช้เป็นวิธีล็อกอินหลัก และทุกเบราว์เซอร์หลักกับมือถือทุกระบบล้วนมี WebAuthn API รองรับ ถ้าคุณเขียนโปรแกรมอยู่ ปีนี้คุณอาจต้อง implement หรือ debug passkey สักครั้งเป็นแน่
แต่มีปัญหาอยู่อย่างหนึ่ง เมื่อ ceremony จบขึ้น เบราว์เซอร์จะส่ง payload กลับมาเป็น base64 ที่ห่อข้อมูล binary แบบ CBOR เอาไว้ ข้างในมีทั้งค่า hash, bit flags และ public key ที่เข้ารหัส base64 อีกชั้น สายตามนุษย์อ่านไม่รู้เรื่องเลย และบทเรียนส่วนใหญ่ก็มักจบแค่ "ไปเรียก verification library ก็จบ" พอเจอปัญหาจริงเมื่อไหร่ คุณจะเหลือแค่ string ลึกลับก้อนหนึ่งให้ถอดรหัสเอง
นี่คือช่องว่างที่ WebAuthn Data Decoder เข้ามาแก้ แค่วาง JSON object ของ registration หรือ authentication ทั้งก้อน — ที่มี clientDataJSON และ attestationObject หรือ authenticatorData — เครื่องมือจะถอดรหัส clientDataJSON, parse CBOR attestation, แจกแจง authenticator flags อย่าง UP และ UV และดึง AAGUID, credential ID และ COSE public key ออกมาให้เป็นฟิลด์ที่อ่านได้ ทำงานในเบราว์เซอร์ของคุณ 100% ข้อมูลอะไรก็ไม่ออกจากเครื่อง
ทำไมต้องใช้ WebAuthn Data Decoder?
- Debug passkey registration ที่ล้มเหลวได้เร็วขึ้น — เมื่อเซิร์ฟเวอร์ปฏิเสธ registration ด้วย error กำกวม ถอดรหัสดูเลย จะเจอทันทีว่า relying party ID ผิด, format แปลก หรือ flag ขาดหาย
- ตรวจ flags ฝั่งเซิร์ฟเวอร์ได้มั่นใจขึ้น — bit UP, UV, BE และ BS คือพื้นฐานของนโยบายจริง การเห็นว่าอุปกรณ์เซ็ต flag ไหนไว้ ช่วยยืนยันว่าเช็กฝั่งเซิร์ฟเวอร์ของคุณตรงกับความจริง
- เข้าใจว่า verification library ทำอะไร — library จะเป็นกล่องดำจนกว่าคุณจะเห็นโครงสร้างที่มันกินเข้าไป payload ที่ถอดรหัสแล้วบอกคุณว่าแต่ละฟิลด์คืออะไร
- ระบุ authenticator ด้วย AAGUID — AAGUID คือตัวระบุรุ่น authenticator ที่ฝังมากับทุก registration ช่วยให้แยก platform authenticator, hardware key และ password manager ออกจากกันได้
- ส่อง payload โดยไม่ต้องส่งข้อมูลออกนอกเครื่อง — challenge และ credential material อยู่กับที่ เพราะทุกการ parse เกิดขึ้นในเบราว์เซอร์ของคุณเอง
- สอนและเรียน WebAuthn แบบจับต้องได้ — spec ที่เป็นนามธรรมจะเข้าใจง่ายขึ้นทันทีเมื่อมีตัวอย่างจริงที่ถอดรหัสแล้วอยู่บนหน้าจอ
ฟีเจอร์หลัก
| ฟีเจอร์ | สิ่งที่ได้ |
|---|---|
| ถอดรหัส clientDataJSON | ค่า type, challenge และ origin ที่เบราว์เซอร์สร้างขึ้น |
| Parse attestationObject แบบ CBOR | format, authenticator data และ attestation statement |
| แจกแจง authenticator flags | bit UP, UV, BE, BS, AT และ ED ทีละตัว |
| ดึง AAGUID | ตัวระบุรุ่น authenticator ขนาด 16 ไบต์ พร้อมดูง่าย |
| แสดง credential ID | ไบต์ของ credential identifier สำหรับเทียบข้อมูล |
| แสดง COSE public key | algorithm และพารามิเตอร์ เช่น ES256 บนเส้นโค้ง P-256 |
| ประมวลผลในเบราว์เซอร์ 100% | ไม่อัปโหลด ไม่เก็บ log ถอดรหัสบนเครื่องคุณเอง |
- วาง JSON object ทั้งก้อนที่ได้จาก navigator.credentials ได้เลย ไม่ต้อง base64 decode เองทีละฟิลด์
- รองรับทั้ง registration และ authentication และทุกขั้นตอน parse ทำงานใน JavaScript ฝั่งเครื่องคุณ
วิธีใช้งาน
- เก็บ WebAuthn response มาก่อน — log credential object ที่ได้จาก navigator.credentials ใน frontend หรือหยิบ payload ที่ client ส่งเข้าเซิร์ฟเวอร์
- วางลงในตัวถอดรหัส — เปิด WebAuthn Data Decoder แล้ววาง JSON object ทั้งก้อนลงในช่อง input
- ดู clientDataJSON ที่ถอดแล้ว — เช็ก type, challenge และ origin แค่นี้ก็แก้ปัญหา challenge ไม่ตรงและ origin mismatch ได้หลายเคส
- ไล่ดู CBOR และ authenticator data — ตรวจ flags, sign counter, AAGUID, credential ID และ COSE public key ว่าตรงกับที่คาดไว้
- เทียบกับสิ่งที่เซิร์ฟเวอร์คาดหวัง — ดูว่า relying party ID, allowed algorithms และนโยบาย flags ของคุณตรงกับที่ authenticator ส่งมาจริง
ข้างใน Registration Payload มีอะไร
response ของ registration เป็นซองซ้อนซอง และแต่ละชั้นอธิบายความล้มเหลวส่วนใหญ่ได้
ซองชั้นนอก: clientDataJSON
ส่วนนี้คือ JSON ที่เบราว์เซอร์สร้างและเข้ารหัส base64 ไว้ มีสามฟิลด์ที่สำคัญที่สุด:
- type — webauthn.create สำหรับ registration, webauthn.get สำหรับ authentication ถ้าไม่ตรงแปลว่า ceremony ไปกันคนละทาง
- challenge — challenge ที่เซิร์ฟเวอร์ของคุณออกให้กับ ceremony นี้ ต้องเท่ากับค่าที่เก็บไว้ ไม่งั้นอาจเป็นการ replay
- origin — origin ของหน้าเว็บที่ทำ ceremony ความไม่ตรงกันตรงนี้เป็นสาเหตุยอดฮิต โดยเฉพาะข้าม subdomain
แกน CBOR: attestationObject
attestationObject คือ CBOR ที่เข้ารหัส base64 — ฟอร์แมต binary ที่กระชับ — ข้างในเป็น map สามคีย์:
- fmt — attestation format เช่น packed, fido-u2f หรือ none ซึ่งกำหนดวิธีตรวจ statement
- attStmt — attestation statement: ลายเซ็นและ certificate ที่รับรองรุ่น authenticator ถ้าเป็น none จะว่างเปล่า
- authData — authenticator data ที่ไบต์น่าสนใจทั้งหมดอยู่ตรงนี้
เลย์เอาต์ของ Authenticator Data
byte string ของ authData อัดแน่นมาก และตัวถอดรหัสจะไล่ให้ทีละส่วน:
- rpIdHash — 32 ไบต์แรก: SHA-256 hash ของ relying party ID ต้องตรงกับโดเมนของคุณ
- flags — หนึ่งไบต์ของ bit: UP (user present), UV (user verified), BE (backup eligibility), BS (backup state) บวก AT และ ED
- signCount — ตัวนับสี่ไบต์ที่ใช้จับ authenticator ที่ถูกโคลน
- AAGUID — สิบหกไบต์ที่ระบุรุ่นของ authenticator
- credential ID — ตัวระบุ credential ใหม่ที่มีความยาวนำหน้า
- COSE public key — public key ของ credential มักเป็น ES256 บน P-256 เซิร์ฟเวอร์จะเก็บไว้ใช้ตรวจลายเซ็นภายหลัง
เซิร์ฟเวอร์ต้องเช็กอะไรบ้าง
การถอดรหัสในเครื่องเป็นเครื่องมือช่วยเรียนรู้ แต่การตัดสินด้านความปลอดภัยต้องอยู่บนเซิร์ฟเวอร์ ให้ตรวจว่า origin ตรง, challenge เป็นค่าที่คุณออกและใช้ครั้งเดียว, type ถูก, rpIdHash ตรงกับ relying party ID, เซ็ต UP (และ UV ถ้านโยบายกำหนด), attestation statement ผ่านการตรวจ และ sign counter เพิ่มขึ้นเรื่อย ๆ ตัวถอดรหัสทำให้ค่าเหล่านี้มองเห็น แต่เซิร์ฟเวอร์ต้องบังคับใช้เอง
กรณีใช้งานจริง
Debug ปัญหา passkey registration
ผู้ใช้แจ้งว่าลงทะเบียนไม่ได้บน Safari แต่ Chrome ผ่าน ถอดรหัส response ที่พังแล้วเทียบ origin, format และ flags — สาเหตุมักมองเห็นทันที เช่น origin ต่างกันใน redirect flow, format แปลก หรือ flag ที่นโยบายปฏิเสธ
พัฒนา verification ฝั่งเซิร์ฟเวอร์
กำลังทำ verification endpoint อยู่? ลอง registration บน staging แล้วถอดรหัสดู เทียบกับค่าที่เซิร์ฟเวอร์ parse ได้ นี่คือวิธีเร็วสุดที่ทำให้ client กับ backend เห็นตรงกัน
ตรวจสอบความปลอดภัยของ authenticator
ทีม security ถอดรหัส registration จริงเพื่อทำ inventory ว่ามี AAGUID อะไรใช้งานอยู่, attestation statement มาครบไหม และ flag BE กับ BS ชี้ว่า credential ถูก sync เข้า cloud password manager หรือเปล่า
สอน WebAuthn
workshop จะดีขึ้นทันทีเมื่อให้ผู้เรียนถอดรหัส registration ของตัวเองสด ๆ เห็น challenge ที่เพิ่งสร้างและ flags ที่เครื่องตัวเองเซ็ต กลายเป็น protocol ที่จับต้องได้
แนวปฏิบัติที่ดี
- ตรวจ origin และ challenge ที่เซิร์ฟเวอร์เสมอ — ตัวถอดรหัสช่วยให้คุณส่องดู แต่มีแค่ backend ที่ผูก response เข้ากับ session ได้
- เก็บ log AAGUID เพื่อทำ inventory — พอมีช่องโหว่กระทบรุ่นใดรุ่นหนึ่ง คุณจะรู้ทันทีว่าต้องแจ้งผู้ใช้กลุ่มไหน
- ถอดรหัสได้ไม่ได้แปลว่าเชื่อได้ — payload ที่ถอดได้สวยงามไม่ได้แปลว่าผ่านการ verify ลายเซ็น, attestation chain และ counter ยังต้องเช็กฝั่งเซิร์ฟเวอร์
- ถือว่า payload เป็นข้อมูลอ่อนไหว — อย่าวาง production payload ลงเครื่องมือที่ไม่น่าเชื่อถือ
- ทดสอบหลายประเภท authenticator — platform authenticator, hardware key และ password manager เซ็ต flags กับ format ไม่เหมือนกัน ลองถอดรหัสอย่างละแบบก่อนตัดสินนโยบาย
- กำหนดนโยบาย flags ให้ชัด — ตัดสินล่วงหน้าว่าจะบังคับ UV หรือรับ synced passkey หรือไม่ แล้วบังคับใช้ให้คงที่
เริ่มถอดรหัส passkey แรกของคุณวันนี้
เคยเขียง base64 ก้อนใหญ่แล้วสงสัยว่า authenticator พูดอะไรไหม? คำตอบอยู่ห่างแค่การวาง paste ครั้งเดียว เปิด WebAuthn Data Decoder วาง registration หรือ authentication response ลงไป แล้วอ่านทุกฟิลด์ได้ชัดเจน — เป็นส่วนตัวและทำงานในเบราว์เซอร์ของคุณทั้งหมด
เครื่องมือที่เกี่ยวข้องที่คุณอาจสนใจ:
- VAPID Key Generator — สร้างคู่กุญแจ VAPID สำหรับ Web Push ที่ยืนยันตัวตนได้
- PEM Certificate Decoder — ส่องรายละเอียด certificate แบบ PEM รวมถึง certificate ใน attestation
- UUID Decoder — แยกโครงสร้างและเวอร์ชันของ UUID ใช้ได้ดีกับ identifier อย่าง AAGUID
ขอให้ challenge ตรงทุกครั้ง และ flags ถูกเซ็ตทุก login
คำถามที่พบบ่อย
ถ: ใช้ WebAuthn Data Decoder กับ payload จริงได้ปลอดภัยไหม?
ตอบ: ปลอดภัยครับ การถอดรหัสทั้งหมดเกิดขึ้นในเบราว์เซอร์ของคุณด้วย JavaScript ไม่มีการอัปโหลด เก็บ หรือ log ข้อมูล ผลคือ production payload ไม่หลุดออกจากเครื่อง
ถ: รองรับทั้ง registration และ authentication response ไหม?
ตอบ: รองรับครับ registration response มี clientDataJSON กับ attestationObject ส่วน authentication response มี clientDataJSON กับ authenticatorData เครื่องมือจะจำแนกเองว่าคุณวางแบบไหน
ถ: AAGUID คืออะไร และสำคัญอย่างไร?
ตอบ: AAGUID คือ identifier ขนาด 16 ไบต์ที่บอกชื่อรุ่น authenticator ที่สร้าง credential นั้น ช่วยให้คุณทำ inventory ว่าผู้ใช้ลงทะเบียนด้วยอุปกรณ์อะไร และบังคับ allow list รายรุ่นได้
ถ: เครื่องมือนี้แทนการ verify ฝั่งเซิร์ฟเวอร์ได้ไหม?
ตอบ: ไม่ได้ครับ การถอดรหัสทำให้ฟิลด์อ่านออกเท่านั้น การตรวจลายเซ็น, attestation, การผูก challenge และการติดตาม counter ต้องทำบนเซิร์ฟเวอร์ของคุณเสมอ