題目與情境
供應方會對時間戳和原始請求本文簽名。請求可能延遲、重複、格式錯誤或在 JSON 解析時改變。實作必須防竄改、防重放且不洩漏比較時序。
面試官在考察什麼
- 保留精確位元組並安全解析結構化簽名標頭。
- 按指定演算法計算 HMAC 並使用恆定時間比較。
- 執行時間戳容差並保持清晰的失敗行為。
作答前的釐清問題
- 供應方規定的簽名字串、摘要演算法、編碼和標頭格式是什麼?
- JSON 解析前能否取得原始請求位元組?
- 需要多大的時鐘偏差容忍和重放識別碼?
- 格式錯誤是否統一返回拒絕,避免暴露具體失敗檢查?
30 秒回答框架
我會讀取原始位元組,安全解析時間戳與簽名,拒絕超出窗口的時間,再按供應方定義的規範字串計算 HMAC。把簽名解碼成位元組後使用恆定時間原語比較,最後在入隊前去重事件 ID。錯誤對外統一拒絕,內部指標區分失敗類別。
分步深挖
1. 保留原始請求本文
不要把解析後的 JSON 重新序列化來驗簽。空白、鍵順序和 Unicode 轉義都會改變位元組。請求本文只讀取一次,先限制大小,再把同一位元組傳給驗簽和後續解析。
2. 解析並校驗簽名標頭
拆出時間戳和帶版本的簽名,拒絕重複欄位或無效編碼,並限制時間戳長度。轉換為整數後,先拒絕超出配置容差的值,再進行昂貴計算。
3. 計算並比較
構造精確簽名訊息,按配置摘要演算法計算 HMAC,解碼外部簽名,並用恆定時間函式比較等長位元組陣列。攻擊者可測量響應時,不要用普通字串相等比較十六進制值。
4. 防止重放
驗簽通過後要求穩定事件 ID,以覆蓋時間窗口的保留期原子記錄它。合法重複請求可以返回成功,但不能重複業務副作用。
5. 測試邊界
覆蓋修改位元組、錯誤密鑰、錯誤演算法、格式錯誤標頭、過期與未來時間戳、重複簽名、空請求本文、過大請求本文和重複事件 ID。日誌不能包含密鑰與完整負載。
高品質示範回答
「我會保留原始請求本文,解析並限制時間戳,拒絕超出重放窗口的值,再構造供應方規定的精確簽名字串。使用指定摘要演算法計算 HMAC,把簽名解碼為位元組後恆定時間比較。驗簽後在入隊前原子去重事件 ID。對外統一拒絕格式錯誤,內部計數區分解析、時間、MAC 與重放失敗。」
常見失誤
- 驗證解析後的 JSON → 序列化可能改變簽名字節 → 驗證原始請求本文。
- 使用普通字串相等 → 時序可能洩漏部分匹配 → 使用恆定時間位元組比較。
- 跳過時間戳檢查 → 合法簽名可以被重放 → 執行有界窗口與事件去重。
- 記錄請求標頭和負載 → 密鑰或個人資料可能洩漏 → 只記錄安全 ID 和失敗類別。
追問與回答
為什麼要先驗簽再解析?
先解析可能規範化位元組,也可能耗用只能讀取一次的請求流。驗簽必須覆蓋供應方簽名的原始內容,接受後再解析。
輪換期間可以接受兩個簽名嗎?
如果供應方規定重疊期,可以在有界窗口內嘗試目前與退役版本,記錄成功版本並讓舊密鑰過期。
只校驗時間戳足夠防重放嗎?
不夠。窗口內仍可反覆重放合法請求。應原子保存穩定事件 ID 或摘要,並讓業務操作具備幂等性。