代表的な面接トピック

バックエンド面接:メッセージの完全性を確保するために HTTP Digest Fields をどのように活用しますか?

バックエンド難しい
Offer.cc 編集チーム公開日 更新日

質問

ファイルアップロード API は、クライアントがゲートウェイやキャッシュによって HTTP コンテンツが書き換えられていないことを検証できるようにする必要があります。RFC 9530 に基づき、Content-Digest、Repr-Digest、Want-Repr-Digest の活用方法を設計し、TLS、署名、リトライとの境界を説明してください。

プロンプトとスコープ

ファイルアップロード API は、クライアントがゲートウェイやキャッシュによって HTTP コンテンツが書き換えられていないことを検証できるようにする必要があります。RFC 9530 に基づき、Content-Digest、Repr-Digest、Want-Repr-Digest の活用方法を設計し、TLS、署名、リトライとの境界を説明してください。

この質問では、ダイジェストを適切な HTTP レイヤーにバインドできるかが問われます。Content-Digest は実際のメッセージコンテンツをカバーし、Repr-Digest は選択された表現(representation)を記述し、Want-Repr-Digest は表現ダイジェストに対する受信側の好みを伝えます。ダイジェストはコンテンツの完全性を検証しますが、それ単体では誰がメッセージを送信したかを証明しません。

面接官がテストしていること

メッセージコンテンツと表現の区別、安全なアルゴリズムの選択、リクエストとレスポンスのネゴシエーション、プロキシと圧縮の境界、ストリーミング計算、ダイジェスト失敗時のステートマシン、ならびにダイジェストと認証、TLS、リトライ、冪等性との適切な組み合わせを網羅してください。

30秒での回答

「まず、検証対象となるオブジェクトとバイト境界を定義します。アップロードクライアントは Content-Digest を計算し、サーバーは受信したメッセージをストリーミング処理しながらそれを検証します。サーバーは Repr-Digest を返すことができ、クライアントはそれを最終的な表現に対して検証します。Want-Repr-Digest はアルゴリズムの選好を伝達し、サーバーは許可された強力なアルゴリズムのみを選択して結果を記録します。不一致が発生した場合は配信や永続化を停止します。送信者認証は引き続き TLS、HTTP Message Signatures、またはアクセストークンによって担保されます。」

ステップバイステップの解決策

ステップ 1: 保護対象のオブジェクトを定義する

目的が転送されたメッセージコンテンツなのか、コンテンツネゴシエーション後の表現なのかを明示します。Content-Digest は実際のメッセージコンテンツに適用され、Repr-Digest は選択された表現を記述します。表現ダイジェストは、トランスコーディング後の異なるバイトシーケンスを検証することはできません。

ステップ 2: ダイジェストアルゴリズムを選択する

SHA-256 や SHA-512 など、現在承認されているアルゴリズムを含む許可リストを使用し、MD5 や SHA-1 などのレガシーな選択肢は拒否します。構造化フィールドをパースする際は、異なるライブラリが同一の値を誤って解釈しないよう、重複するアルゴリズム、未知のパラメータ、不正な形式のエンコーディングを拒否します。

ステップ 3: リクエストを検証する

アップロードクライアントは、最終的なメッセージバイト列に対して Content-Digest を計算します。サーバーは読み取り中にそれを計算し、メッセージが終了した後にのみ比較します。不一致がある場合はオブジェクトのコミットやイベントの発行を阻止し、部分的な出力を成功として扱うことは決してありません。大きなアップロードはメモリにバッファリングするのではなく、ストリーミング処理する必要があります。

ステップ 4: レスポンスを検証する

サーバーはレスポンスで Repr-Digest を送信できます。クライアントは、ネゴシエートされたルールに従って、デコードされた選択済みの表現に対してダイジェストを計算します。圧縮が含まれる場合、ダイジェストが圧縮されたメッセージをカバーするのか、それとも非圧縮の表現をカバーするのかをプロトコルで規定する必要があり、クライアントはこれらのレイヤーを混同してはなりません。

ステップ 5: Want-Repr-Digest を使用する

クライアントは、アルゴリズムの選好と重み付けを指定した Want-Repr-Digest を送信できます。サーバーはそれに応じるか、許可された別のアルゴリズムを選択するか、レスポンスフィールドを省略することができます。クライアントは「ダイジェストが提供されなかった」ことと「ダイジェストの不一致」を区別しなければならず、フィールドの欠落は検証の成功を意味しません。

ステップ 6: プロキシとキャッシュを処理する

キャッシュヒットの場合でも、現在の表現に一致するダイジェストが必要です。ゲートウェイがコンテンツの再圧縮、トランスコード、または結合を行う場合は、関連するダイジェストを再計算しなければなりません。アップストリームのフィールドをそのままコピーすると誤った結果が生じます。ダイジェストの対象バイト範囲外のフィールドを書き換えてもダイジェスト自体は自動的には壊れませんが、署名や認可のセマンティクスが変更される可能性があります。

ステップ 7: 認証とリプレイ保護を組み合わせる

ダイジェストはバイトの対応関係を証明するものであり、送信者の同一性を証明するものではなく、有効なメッセージが再送されるのを防ぐこともできません。送信者認証には TLS、HTTP Message Signatures、またはトークンを使用します。二重請求などを防ぐには、nonce、時間枠、およびビジネス上の冪等性キーを使用します。ダイジェスト値自体は認可クレデンシャルではありません。

ステップ 8: 障害と可観測性を定義する

不一致、不許可のアルゴリズム、不正な形式のフィールド、欠落したフィールドに対して、個別のメトリクスとエラークラスを公開します。アップロードの検証に失敗した後は一時オブジェクトをクリーンアップします。未検証のキャッシュレスポンスは破棄し、リトライポリシーをトリガーします。機密コンテンツや完全なペイロードは絶対に記録せず、アルゴリズム、リクエスト ID、サイズ、および障害クラスのみをログに記録します。

トレードオフと境界

Content-Digest または Repr-Digest

Content-Digest は、この HTTP メッセージが実際に転送した内容を検証するのに適しています。Repr-Digest は、キャッシュ、コンテンツネゴシエーション、およびリソース表現の検証に適しています。これらは共存可能ですが、プロトコルでバイト境界とデコード順序を文書化する必要があります。

ダイジェストまたはデジタル署名

ダイジェストは計算コストが低く、転送中または保存中の変更を検出します。デジタル署名はさらに鍵の保持者を認証し、システム間の検証をサポートします。署名でダイジェストフィールドをカバーしてコンテンツの完全性をメソッドやターゲットにバインドできますが、ダイジェスト自体には識別特性がありません。

フェイルクローズまたは縮退運転

決済、ソフトウェアパッケージ、および規制対象のアーカイブでは、欠落または不一致のダイジェストを拒否する必要があります。オプションのダイジェストを持つ通常の静的リソースは、アラートを記録した上で処理を続行しても構いませんが、呼び出し元は完全性が検証されていないことを認識している必要があり、暗黙のうちに信頼済みとしてマークしてはなりません。

障害訓練とシステム進化

ゲートウェイがレスポンスを再圧縮する

ゲートウェイに圧縮形式を変更させ、クライアントがプロトコルで定義された表現レイヤーのハッシュを依然として計算していることを検証します。ゲートウェイが対象レイヤーを変更した場合、新しいフィールドを生成する必要があります。

アップロード中に1バイトが変化する

プロキシで1バイトを書き換え、サーバーがオブジェクトをコミットする前に Content-Digest の不一致を報告し、一時データとダウンストリームイベントを削除することを確認します。

アルゴリズムのダウングレードまたはフィールドの欠落

レガシーアルゴリズムを含む選好を送信し、サーバーが許可されていない選択肢を拒否することを確認します。Repr-Digest を削除し、クライアントが成功ブランチではなく「未検証」ブランチに入ることを確認します。

よくある間違いとフォローアップ

間違い 1: ダイジェストを認証として扱う

フォローアップ: 攻撃者は自身のコンテンツに対してダイジェストを再計算できますか? はい、可能です。送信者を認証するには、依然として TLS、署名、またはトークンが必要です。

間違い 2: 圧縮と表現レイヤーを無視する

フォローアップ: アップストリームのダイジェストを再圧縮されたレスポンスにコピーできますか? カバーされているバイトレイヤーが変更されていない場合に限られます。それ以外の場合は再計算が必要です。

間違い 3: フィールドの欠落を検証済みとして扱う

フォローアップ: サーバーが要求されたダイジェストを省略した場合はどうなりますか? 結果を未検証としてマークするか、ポリシーに従って拒否します。省略は一致を意味しません。

より深いフォローアップと模範解答

なぜアップロードリクエストで Content-Digest を使用できるのですか?

送信者は転送前またはストリームの完了時にダイジェストを提供できるため、受信者は永続化の前にバイト列を検証できます。大きなオブジェクトはバッファリングするのではなく、増分(インクリメンタル)でハッシュ化する必要があります。

ダイジェストフィールドはリプレイ保護になりますか?

いいえ、なりません。同一の有効なメッセージが再送される可能性があります。リプレイ保護には、時間枠、nonce、署名の適用範囲、およびビジネス上の冪等性ステータスが必要です。

プロキシはアップストリームのダイジェストを削除すべきですか?

対象バイトを変更し、フィールドを再計算できない場合にのみ、削除するか使用不可としてマークする必要があります。再計算できる場合は、最終的なメッセージまたは表現の値を作成し、責任の境界を文書化する必要があります。

公開情報ソース

関連する質問