具代表性的面試主題

程式設計面試:實作 HMAC Webhook 簽名驗證

程式題中等
Offer.cc 編輯團隊發佈 更新

題幹

實作一個函式,接收原始請求本文、簽名標頭、共享密鑰和目前時間,安全地接受或拒絕 Webhook。

題目與情境

供應方會對時間戳和原始請求本文簽名。請求可能延遲、重複、格式錯誤或在 JSON 解析時改變。實作必須防竄改、防重放且不洩漏比較時序。

面試官在考察什麼

  • 保留精確位元組並安全解析結構化簽名標頭。
  • 按指定演算法計算 HMAC 並使用恆定時間比較。
  • 執行時間戳容差並保持清晰的失敗行為。

作答前的釐清問題

  • 供應方規定的簽名字串、摘要演算法、編碼和標頭格式是什麼?
  • JSON 解析前能否取得原始請求位元組?
  • 需要多大的時鐘偏差容忍和重放識別碼?
  • 格式錯誤是否統一返回拒絕,避免暴露具體失敗檢查?

30 秒回答框架

我會讀取原始位元組,安全解析時間戳與簽名,拒絕超出窗口的時間,再按供應方定義的規範字串計算 HMAC。把簽名解碼成位元組後使用恆定時間原語比較,最後在入隊前去重事件 ID。錯誤對外統一拒絕,內部指標區分失敗類別。

分步深挖

1. 保留原始請求本文

不要把解析後的 JSON 重新序列化來驗簽。空白、鍵順序和 Unicode 轉義都會改變位元組。請求本文只讀取一次,先限制大小,再把同一位元組傳給驗簽和後續解析。

2. 解析並校驗簽名標頭

拆出時間戳和帶版本的簽名,拒絕重複欄位或無效編碼,並限制時間戳長度。轉換為整數後,先拒絕超出配置容差的值,再進行昂貴計算。

3. 計算並比較

構造精確簽名訊息,按配置摘要演算法計算 HMAC,解碼外部簽名,並用恆定時間函式比較等長位元組陣列。攻擊者可測量響應時,不要用普通字串相等比較十六進制值。

4. 防止重放

驗簽通過後要求穩定事件 ID,以覆蓋時間窗口的保留期原子記錄它。合法重複請求可以返回成功,但不能重複業務副作用。

5. 測試邊界

覆蓋修改位元組、錯誤密鑰、錯誤演算法、格式錯誤標頭、過期與未來時間戳、重複簽名、空請求本文、過大請求本文和重複事件 ID。日誌不能包含密鑰與完整負載。

高品質示範回答

「我會保留原始請求本文,解析並限制時間戳,拒絕超出重放窗口的值,再構造供應方規定的精確簽名字串。使用指定摘要演算法計算 HMAC,把簽名解碼為位元組後恆定時間比較。驗簽後在入隊前原子去重事件 ID。對外統一拒絕格式錯誤,內部計數區分解析、時間、MAC 與重放失敗。」

常見失誤

  • 驗證解析後的 JSON → 序列化可能改變簽名字節 → 驗證原始請求本文。
  • 使用普通字串相等 → 時序可能洩漏部分匹配 → 使用恆定時間位元組比較。
  • 跳過時間戳檢查 → 合法簽名可以被重放 → 執行有界窗口與事件去重。
  • 記錄請求標頭和負載 → 密鑰或個人資料可能洩漏 → 只記錄安全 ID 和失敗類別。

追問與回答

為什麼要先驗簽再解析?

先解析可能規範化位元組,也可能耗用只能讀取一次的請求流。驗簽必須覆蓋供應方簽名的原始內容,接受後再解析。

輪換期間可以接受兩個簽名嗎?

如果供應方規定重疊期,可以在有界窗口內嘗試目前與退役版本,記錄成功版本並讓舊密鑰過期。

只校驗時間戳足夠防重放嗎?

不夠。窗口內仍可反覆重放合法請求。應原子保存穩定事件 ID 或摘要,並讓業務操作具備冪等性。

公開來源

同類題目

相關面試工具

用 Screenshot 處理演算法題

截圖題目後,依序看約束、解法、程式碼、邊界條件和複雜度。

查看工具