← 所有工具
我們的筆記

CyberChef 手動驗證 X-Device-Signature

webhook 簽章對不上時,第一個要判斷的是哪一邊錯了——你的還是我們的。CyberChef 能讓你在瀏覽器裡跑 UnifyPort 完全一樣的簽章演算法,用 handler 看到的同一組輸入,三十秒內出結果。

UnifyPort 到底簽什麼

每次投遞只要設定了簽章密鑰,就會帶三個 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 ) )

偵錯前貼幾條在螢幕邊:

  • timestamp 和 body 中間的那個字元是 ASCII 點號(.),不是換行。
  • raw_body 指我們送過去的原始位元組——在你這邊做任何 JSON 解析、去空白、unicode 正規化之前
  • hex 輸出是小寫。如果跟大寫 digest 比對,會假陰性。

CyberChef recipe

在 CyberChef 裡按順序把兩個操作丟進 recipe 面板:

  1. 1. HMAC——把 Hashing function 設成 SHA256。把你的簽章密鑰貼進 KeyTypeUTF8
  2. 2. To Hex——Delimiter 留空,Bytes per line0。這樣能得到沒有空白的小寫 hex 字串,跟 header 對得上。

Input 面板貼上的內容必須正好是 <timestamp>.<raw_body>——例如:

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

Output 面板出來的應該跟那條投遞裡的 X-Device-Signature 一致。如果不一致,bug 鎖定在三處之一:用了不同的 secret、body 在途中被改過、或者你讀的是錯的 timestamp header。

這種手動驗證真正派上用場的時刻

  • 輪換簽章密鑰之後。在你怪 DNS 或部署沒重新整理之前,先確認新密鑰真的到了 handler。
  • 升級 JSON 函式庫之後。有些解析器在交給驗證邏輯前重新輸出過 body——這種事很容易漏看,直到簽章突然對不上。
  • 隊友說「我這邊跑得起來」的時候。兩個人各跑同一個 recipe、同一組輸入;digest 不一樣的那個就是拿了錯的 secret。

把密鑰貼進網頁這件事

CyberChef 是純靜態的客戶端 bundle——完全在你瀏覽器裡跑,官方代管版本裡 secret 不會離開你的機器。話雖如此,如果你擔心瀏覽器擴充功能或共用工作階段,可以在本地跑 CyberChef(clone 倉庫後開啟 index.html)或者用 DevToys——完全離線的桌面端等價物。正式環境的簽章密鑰輪換,要走程式碼做 constant-time 比對,而不是用肉眼看 CyberChef 輸出。

手動驗過之後

把等價邏輯搬進你的 handler。大多數語言的標準函式庫就有原語:Node 的 crypto.createHmac、Python 的 hmac.new、Go 的 hmac.New。比對一定要用 constant-time 函式(timingSafeEqualhmac.compare_digesthmac.Equal)——絕對不要用 ==