← เครื่องมือทั้งหมด
บันทึกของเรา

ตรวจ X-Device-Signature ด้วยมือผ่าน CyberChef

เมื่อลายเซ็น webhook ไม่ตรง สิ่งแรกที่ต้องแยกคือ ฝั่งไหน ของการเปรียบเทียบที่ผิด — ของคุณหรือของเรา. CyberChef ช่วยให้คุณรันอัลกอริทึมเซ็นแบบเดียวกับ UnifyPort เป๊ะ ๆ ใน browser ด้วย input ชุดเดียวกับที่ handler เห็น ภายในประมาณ 30 วินาที.

UnifyPort เซ็นอะไรกันแน่

ทุก delivery ที่มีการตั้ง signing secret จะมาพร้อม header สามตัว:

X-Device-Delivery-Id: d_01J2K…
X-Device-Timestamp: 1716800000
X-Device-Signature: 9f8c…

ลายเซ็นคำนวณตามนี้:

X-Device-Signature = hex( HMAC-SHA256( secret, timestamp + "." + raw_body ) )

ติดไว้ข้างจอก่อน debug:

  • ไบต์ที่อยู่ระหว่าง timestamp กับ body คือจุด ASCII (.) ไม่ใช่ขึ้นบรรทัดใหม่.
  • raw_body หมายถึงไบต์ที่เราส่งไป ก่อน ที่ฝั่งคุณจะ parse JSON, ตัดช่องว่าง, หรือทำ unicode normalization.
  • Output hex เป็นตัวพิมพ์เล็ก. ถ้าเทียบกับ digest ตัวพิมพ์ใหญ่ จะได้ false-negative.

Recipe ของ CyberChef

ใน CyberChef ลาก operation สองตัวต่อไปนี้ลงใน pane recipe ตามลำดับ:

  1. 1. HMAC — ตั้ง Hashing function เป็น SHA256. แปะ signing secret ลงในช่อง Key, Type เลือก UTF8.
  2. 2. To Hex — เว้น Delimiter ว่าง, Bytes per line ตั้งเป็น 0. จะได้สตริง hex ตัวพิมพ์เล็กไม่มีช่องว่าง ตรงกับ header.

ใน pane Input แปะให้ตรงคือ <timestamp>.<raw_body> — เช่น:

1716800000.{"id":"evt_demo","type":"message.received",...}

Output ที่ออกมาควรตรงกับ X-Device-Signature ของ delivery. ถ้าไม่ตรง บัก ถูกล็อกอยู่หนึ่งในสามจุด: ใช้ secret คนละตัว, body ถูกแก้ระหว่างทาง, หรือคุณอ่าน timestamp จาก header ที่ผิด.

เมื่อการเช็กด้วยมือนี้คุ้มจริง ๆ

  • หลังหมุน signing secret. ยืนยันว่า secret ใหม่ถึง handler แล้ว ก่อนจะไปโทษ DNS หรือ deploy ค้าง.
  • หลัง upgrade ไลบรารี JSON. บาง parser ส่ง body กลับออกอีกครั้งก่อนให้ตัว verify — พลาดได้ง่ายจนกว่าลายเซ็นจะไม่ตรง.
  • เมื่อเพื่อนร่วมทีมบอกว่า "เครื่องผมรันได้". ทั้งสองรัน recipe เดียวกันด้วย input เดียวกัน; ใครได้ digest ต่าง คนนั้นถือ secret ผิด.

เรื่องการแปะ secret ลงในหน้าเว็บ

CyberChef เป็น bundle ฝั่ง client แบบสแตติก — รันใน browser ของคุณทั้งหมด, ในเวอร์ชันที่ host อย่างเป็นทางการ secret ไม่ออกจากเครื่อง. ถึงอย่างนั้นถ้ายังไม่สบายใจกับ extension หรือ session ที่ใช้ร่วมกัน ให้รัน CyberChef แบบ local (clone repo แล้วเปิด index.html) หรือใช้ DevToys — เดสก์ท็อปออฟไลน์เทียบเท่า. การหมุน signing secret ใน production ต้องเปรียบเทียบด้วยโค้ดที่ใช้ constant-time function ไม่ใช่จ้อง output ของ CyberChef.

คำถามที่พบบ่อย

จะยืนยันลายเซ็น webhook ของ UnifyPort ด้วยมือได้อย่างไร?
ใน CyberChef ให้เพิ่ม HMAC (Hashing function SHA256, signing secret ของคุณเป็น Key แบบ encoding UTF8) ตามด้วย To Hex (delimiter ว่าง, bytes per line 0). แปะ <timestamp>.<raw_body> ลงใน pane Input ให้ตรงเป๊ะ. Output ควรตรงกับ header X-Device-Signature ทุกไบต์.
ทำไมลายเซ็นของผมไม่ตรงกับที่ UnifyPort ส่งมา?
สาเหตุที่พบบ่อยสามอย่าง: (1) คุณใช้ signing secret ผิดตัว — ยืนยันว่าค่าตรงกับที่เห็นใน dashboard; (2) body ถูกแก้ก่อนการยืนยัน — JSON ที่ส่งออกใหม่, การตัดช่องว่าง, หรือ unicode normalization ล้วนทำให้ digest พัง; (3) timestamp ถูกอ่านจาก header ที่ผิด — เซ็นเฉพาะ X-Device-Timestamp เท่านั้น ไม่ใช่ Date header ของ framework.
แปะ signing secret ลงใน CyberChef ปลอดภัยไหม?
CyberChef ที่ host อย่างเป็นทางการเป็น bundle ฝั่ง client แบบสแตติก — secret ไม่ออกจาก browser ของคุณ และไม่มีการ logging ฝั่งเซิร์ฟเวอร์. ถ้ายังต้องการ exposure เป็นศูนย์ ให้ clone repository แล้วเปิด index.html แบบ local, หรือใช้ DevToys — เดสก์ท็อปออฟไลน์เทียบเท่าแบบสมบูรณ์.

หลังตรวจด้วยมือเสร็จ

ย้าย logic แบบเดียวกันเข้าไปใน handler. ภาษาส่วนใหญ่มี primitive อยู่ใน standard library: crypto.createHmac ของ Node, hmac.new ของ Python, hmac.New ของ Go. เปรียบเทียบต้องใช้ฟังก์ชัน constant-time (timingSafeEqual, hmac.compare_digest, hmac.Equal) — ห้ามใช้ == เด็ดขาด.