Edited at
http2Day 9

HPACK の never indexed はいつ使う?

More than 3 years have passed since last update.


"I thought Falkor appeared in Never ending Story was a dog".


HPACK は HTTP/2 のヘッダーフィールドエンコーディングアルゴリズムです. だいたい 30% 程度の大きさになります. この圧縮率を実現するためいろいろなことをやっているのですが, 基本的なところは一度送ったヘッダーフィールドは大きさ制限の着いた FIFO キューに入れておいて (このキューは送信側, 受信側で同期して共有する), 次に送信する場合はキューの中のインデックスだけ送信すればよい, という部分になります. このキューにいれることをインデックス化 (Indexed, Indexing) と RFC 7541 では述べています. エンコーダーは必ずもインデックス化しなければならないわけではなく, インデックスする / しないという選択をヘッダーフィールド単位で制御できます. インデックス化しない場合は, Literal Header Field without Indexing (以降, Without Indexing) というエンコードを使います.

さて, RFC 7541, Section 6.2.3 に Literal Header Field Never Indexed (以降, Never Indexed) というのがあります. これは Without Indexing と同じでインデックス化しない, というエンコードです. 2 つを比べてみると 4 ビット目が違うだけで後は同じです. Never Indexed はどのようなときに使うのでしょうか.

Never Indexed はセキュリティ対策として導入されたエンコード方法です. 当初 HPACK ドラフトにはありませんでしたが, セキュリティレビューの時に CRIME 攻撃のように一文字ずつの解読というのはできないが, 辞書による完全一致攻撃に対して脆弱性があるという指摘が上げられました. 短い cookie や authorization ヘッダーフィールドはインデックス化していると, 完全一致の場合インデックスを使うので出力が短くなる = 推測が当たっている, と攻撃者に情報を与えてしまうというものです. そういう重要なヘッダーには Without Indexing を使えばいい, という単純な話にはなりませんでした. というのはプロキシーがフォワードするときにインデックス化してしまう可能性があります. そこで全てのフォーワードされるパスにおいてインデックス化してはいけない, ということを要求するために追加されたのが Never Indexed なのです.

実際に Never Indexed は使われているのでしょうか. 実は Firefox ではかなり前から実装されています. Firefox は authorization ヘッダーフィールドや, 短い cookie ヘッダーフィールドは Never Indexed を適用するようになっています. nghttp2 でも同様の手法を取りいれています.