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

ตรวจ 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.

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

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