プロンプトと設定
プロバイダーはタイムスタンプと生ボディに署名します。リクエストは遅延、重複、不正な形式、または JSON パースによる変更が発生する可能性があります。実装では、比較タイミングの漏洩を起こさずに、改ざんとリプレイを拒否する必要があります。
面接官がテストするポイント
- 正確なバイト列の保持と、構造化された署名ヘッダーの安全なパース。
- 指定されたアルゴリズムによる HMAC の計算と定数時間での比較。
- タイムスタンプの許容範囲の適用と明確な失敗時の挙動。
回答前の確認質問
- プロバイダーが指定する正確な署名対象文字列、ダイジェストアルゴリズム、エンコーディング、ヘッダー形式はどのようなものですか?
- ボディは JSON パース前の生のバイト列として利用可能ですか?
- クロックスキューの許容範囲とリプレイ識別子には何が必要ですか?
- 不正な形式の入力に対しては、どのチェックが失敗したかを開示せずに汎用的な拒否を返すべきですか?
30秒の回答フレームワーク
生のバイト列を読み取り、型を信用せずにタイムスタンプと署名をパースし、許可されたウィンドウ外のタイムスタンプを拒否した上で、プロバイダー定義のカノニカル文字列に対して HMAC を計算します。デコードされた MAC バイトを定数時間プリミティブで比較し、エンキューする前にイベント ID を重複排除します。エラー時は単一の汎用的な拒否を返し、内部メトリクスで失敗の分類を行います。
ステップごとの詳細解説
1. 生ボディの保持
検証のためにパースされた JSON を文字列化しないでください。空白、キーの順序、Unicode エスケープによってバイト列が変化する可能性があります。ボディは一度だけ読み取り、サイズ制限を適用し、同じバイト列を検証およびその後のパースに渡します。
2. ヘッダーのパースとバリデーション
ヘッダーをタイムスタンプとバージョン管理された署名に分割し、重複や無効なエンコーディングを拒否し、タイムスタンプの長さを制限します。タイムスタンプを整数に変換し、コストのかかる処理を行う前に設定されたスキューウィンドウ外の値を拒否します。
3. 計算と比較
正確な署名対象メッセージを構築し、設定されたダイジェストで HMAC を計算し、提供された署名をデコードして、等しい長さのバイト配列を定数時間関数で比較します。攻撃者が応答時間を計測できる可能性がある場合、16進数文字列を通常の等価比較で比較してはいけません。
4. リプレイの防止
署名検証の後、不変のイベント ID を要求し、受け入れられるタイムスタンプウィンドウと少なくとも同じ長さの保持期間でアトミックに記録します。重複した有効なリクエストには、ビジネス上の効果を繰り返すことなく成功を返すことができます。
5. 境界値のテスト
改ざんされたバイト列、誤ったシークレット、誤ったアルゴリズム、不正なヘッダー、過去および未来のタイムスタンプ、重複した署名、空のボディ、サイズ超過のボディ、重複したイベント ID をテストします。ログにはシークレットや完全なペイロードを含めないようにします。
質の高い模範解答
「私なら生のボディを保持し、タイムスタンプをパースして制限をかけ、リプレイウィンドウ外のものを拒否し、プロバイダーの正確な署名対象文字列を構築します。必要なダイジェストで HMAC を計算し、署名をデコードして、定数時間のバイト比較を使用します。検証後、エンキューする前にイベント ID をアトミックに重複排除します。不正な入力には単一の汎用的な拒否を返し、内部カウンターでパース、時間、MAC、リプレイの失敗を区別します。」
よくある間違い
- パースされた JSON を検証する → シリアライズによって署名されたバイト列が変化する可能性がある → 生のボディを検証する。
- 通常の文字列等価比較を使用する → タイミングによって部分一致が漏洩する可能性がある → 定数時間のバイト比較を使用する。
- タイムスタンプチェックをスキップする → 有効な署名がリプレイされる可能性がある → 制限されたウィンドウとイベントの重複排除を強制する。
- ヘッダーとペイロードをログに出力する → シークレットや個人データが漏洩する → 安全な ID と失敗クラスのみをログに出力する。
フォローアップの質問と回答
なぜパース前に検証するのですか?
最初にパースするとバイト列が正規化される可能性があり、また一度しか読み取れないリクエストストリームを消費してしまう恐れがあります。検証はプロバイダーが署名したものと完全に一致する対象をカバーしなければならないため、受け入れ後にのみパースを行います。
ローテーション中に2つの署名を受け入れることはできますか?
はい、プロバイダーがオーバーラップ期間を規定している場合は可能です。制限されたウィンドウ内でアクティブなバージョンと廃止予定のバージョンのみを試し、どのバージョンがパスしたかを記録し、古いシークレットを失効させます。
タイムスタンプのバリデーションだけでリプレイ保護には十分ですか?
いいえ。有効なリクエストはウィンドウ内で繰り返しリプレイされる可能性があります。不変のイベント ID またはダイジェストをアトミックに保存し、ビジネス操作を冪等(べきとう)にしてください。