用 CyberChef 手動驗 X-Device-Signature
webhook 簽章對唔到嗰陣,第一件事係要判斷邊一邊錯——你嗰邊定我哋呢邊。CyberChef 可以畀你喺 browser 度跑 UnifyPort 完全一樣嘅簽章算法,用 handler 收到嘅同一組 input,三十秒出結果。
UnifyPort 究竟簽乜嘢
每次投遞只要配咗 signing secret,就會帶三個 header:
簽章係咁計嘅:
Debug 前貼幾條喺 mon 邊:
- timestamp 同 body 中間嗰隻 byte 係 ASCII 點(
.),唔係換行。 raw_body係指我哋發出嘅原始 byte——喺你嗰邊做任何 JSON parse、去空白、unicode 正規化之前。- hex output 係細階。如果同大階 digest 比,會 false-negative。
CyberChef recipe
喺 CyberChef 度按順序將兩個 operation 拖入 recipe pane:
- 1. HMAC——將 Hashing function 設成
SHA256。把 signing secret paste 落 Key,Type 揀UTF8。 - 2. To Hex——Delimiter 留空,Bytes per line 設
0。咁可以出到無 space 嘅細階 hex string,啱晒 header。
喺 Input pane 度 paste 嘅嘢必須係 <timestamp>.<raw_body>——例如:
Output pane 出嘅嘢應該同嗰次投遞嘅 X-Device-Signature 一樣。如果唔一樣,bug 就鎖喺三個位之一:用咗唔同 secret、body 喺途中被改過、或者你讀錯 timestamp header。
呢種手動驗真係派上用場嘅時候
- 輪換 signing secret 之後。喺你怪 DNS 或者 deploy 未 refresh 之前,先確認新 secret 真係到咗 handler。
- Upgrade JSON 庫之後。有啲 parser 會喺交畀驗證邏輯之前重新 emit 一次 body——呢啲嘢好易走漏眼,直到簽章突然對唔到。
- 隊友話「我呢度跑得到」嗰陣。兩個人都跑同一個 recipe、同一組 input;digest 唔同嗰個就係攞錯 secret。
將密鑰 paste 入網頁呢件事
CyberChef 係純靜態嘅 client-side bundle——完全喺你 browser 度跑,官方 host 嘅版本裡面 secret 唔會離開你部機。話雖如此,如果你怕 browser extension 或者 shared session,可以本地跑 CyberChef(clone 個 repo 之後開 index.html)或者用 DevToys——完全 offline 嘅 desktop equivalent。Production 嘅 signing secret 輪換,要用 code 做 constant-time 比對,唔好用對眼睇 CyberChef 嘅 output。
手動驗完之後
將等效邏輯搬入 handler。大多數語言嘅 standard library 都有 primitive:Node 嘅 crypto.createHmac、Python 嘅 hmac.new、Go 嘅 hmac.New。比對一定要用 constant-time function(timingSafeEqual、hmac.compare_digest、hmac.Equal)——絕對唔好用 ==。