Oblivious HTTP draft-06 メモ
現在(2023/02/25)最新のdraft-06をベースに要点をメモっていく。
1. Introduction
やりたいのは、匿名性の高い Privacy-preservingなHTTPアクセス。
これは、ClientのIPアドレスは分かるがリクエストの内容が分からないOblivious Relay Resource (relay)と、ClientのIPアドレスはわからないがリクエストの内容は分かるOblivious Gateway Resource (gateway)をclientとTarget Resource (target)間に配することで達成する。
client = relay = gateway = target
clientからtargetに渡すHTTPリクエストの内容は、Binary HTTPにエンコードしたものをHPKEで暗号化する。レスポンスも同様に暗号化。relayは覗けない。
プライバシー強化を目的とするならば、Tor のような Client-configured HTTPプロキシをつかうソリューションも解決策になるが、TLSコネクションを都度つくらなければならないコストは大きく、これを削減したい。OHTTPなら、client-relay間、 relay-gateway間でコネクションの再利用が可能。
2. Overview
以下の通り。見たまんま。
2.1. Applicability
適用範囲は狭い。結局、CookieやAuthenticationヘッダによるステート管理のメリットや以下のOHTTPのコストより、プライバシー保護のメリットが大きいと判断できる場合にのみ使えるもの。
- リクエストが2倍になる。遅延が増える。
- メッセージサイズも肥大する。追加のヘッダフィールド、暗号関連のメタデータやAEAD expansion.
- clientとgatewayの暗号・復号に要する計算コスト
適用例として挙がっているのは以下。
- DNSクエリ。
- テレメトリの登録。ユーザによるアプリの利用状況を開発者向けに送信する等。
- その他
- 匿名調査の登録
- クエリ検索
- 特定の場所に関係するコンテンツの取得(地図のタイル取得)
3. Key Configuration
client はEncapsulated Requestを送信するためにgatewayの公開鍵情報(key configuration)を予め取得する必要がある。
この文書では、key configurationのフォーマットを規定するが、gatewayによる公開方法(clientによる取得方法)については規定しない。clientは複数のkey configurationを用いてもよい。
3.1. Key Configuration Encoding
単一のkey configurationのフォーマットは以下の通り。
HPKE Symmetric Algorithms {
HPKE KDF ID (16),
HPKE AEAD ID (16),
}
Key Config {
Key Identifier (8),
HPKE KEM ID (16),
HPKE Public Key (Npk * 8),
HPKE Symmetric Algorithms Length (16),
HPKE Symmetric Algorithms (32..262140),
}
3.2. Key Configuration Media Type
複数のkey configurationをシリアライズしたデータを表現するために、"application/ohttp-keys" というMIMEタイプを新たに定義する。フォーマット拡張は、新しいメディアタイプを定義することによって行うとしている。
4. HPKE Encapsulation
Binary HTTPメッセージリクエスト、レスポンスそれぞれに新しいメディアタイプを割り当てている。
- ”message/ohttp-req”
- "message/ohttp-res"
4.1. Rquest format
リクエストフォーマットは以下の通り。
Request {
Binary HTTP Message (..),
}
Encapsulated Request {
Key Identifier (8),
KEM Identifier (16),
KDF Identifier (16),
AEAD Identifier (16),
Encapsulated KEM Shared Secret (8 * Nenc),
HPKE-Protected Request (..),
}
4.2. Response format
レスポンスフォーマットは以下の通り。
Response {
Binary HTTP Message (..),
}
Encapsulated Response {
Nonce (8 * max(Nn, Nk)),
AEAD-Protected Response (..),
}
4.3. Encapsulation of Requests
clientでのEncapsulated Requestのエンコード・暗号手順は、以下の通り。
hdr = concat(encode(1, key_id),
encode(2, kem_id),
encode(2, kdf_id),
encode(2, aead_id))
info = concat(encode_str("message/bhttp request"),
encode(1, 0),
hdr)
enc, sctxt = SetupBaseS(pkR, info)
ct = sctxt.Seal("", request)
enc_request = concat(hdr, enc, ct)
gatewayでのEncapsulated Requestのデコード・復号手順は以下の通り。
key_id, kem_id, kdf_id, aead_id, enc, ct = parse(enc_request)
info = concat(encode_str("message/bhttp request"),
encode(1, 0),
encode(1, key_id),
encode(2, kem_id),
encode(2, kdf_id),
encode(2, aead_id))
rctxt = SetupBaseR(enc, skR, info)
request, error = rctxt.Open("", ct)
4.4. Encapsulation of Responses
gatewayでのEncapsulated Responseのエンコード・暗号手順は以下の通り。
secret = context.Export("message/bhttp response", Nk)
response_nonce = random(max(Nn, Nk))
salt = concat(enc, response_nonce)
prk = Extract(salt, secret)
aead_key = Expand(prk, "key", Nk)
aead_nonce = Expand(prk, "nonce", Nn)
ct = Seal(aead_key, aead_nonce, "", response)
enc_response = concat(response_nonce, ct)
clientでのEncapsulated Responseのデコード・復号手順は以下の通り。
reponse, error = Open(aead_key, aead_nonce, "", ct)
4.5. Request and Response Media Types
key configurationと同様、フォーマット拡張は、新しいメディアタイプを定義することによって行うとしている。
4.6. Repurposing the Encapsulation Format
このカプセル化メカニズムを利用する場合には、新たにメディアタイプを利用して、infoやexporterコンテキストへのインプットにしている上記の”message/bhttp”を置き換えるべし。
例としては、”application/dns-message”を挙げている。
5. HTTP Usage
client, relay, gatewayのHTTPプロトコル処理に関して。
clientは、Encapsulated Requestをボディに設定したPOSTメッセージを relayに投げる。gatewayによって処理されるリクエストヘッダは、Content-Type1つのみ。他のヘッダを指定しても良いが、それはrelayによって消費されるもので、その先には行かない。
relayは、target URIを gatewayに差し替えて送付。RequestBodyはそのままgateway向けにコピる。RequestBodyが空など、OHTTP的にinvalidであれば、エラーを返せる。gatewayからの応答がタイムアウトするなどプロキシ的エラーが発生したら、当然それも返せる。
gatewayは、targetのリバースプロキシとしてふるまう。応答をカプセル化することを除き。当然、504等のプロキシ的エラーも返せる。
5.1. Informational Responses
OHTTPのカプセル化は、応答のプログレッシブな処理を認めない。1xx応答は禁止ということ。Binary HTTP的にはOKだが、AEAD処理は、応答を全て受信して行うので。
したがって、clientは、Exceptヘッダで100-continueを入れてはいけない。gatewayはこれを受診したらエラー応答がMUST。
5.2. Errors
復号できたら、エラー応答は、Encapsulated Responseで。できなければ通常エラーで。clientはエラー応答がカプセル化されていなければ、key configurationが間違っているか期限切れと判断できる。
5.3. Signaling Key Configuration Problems
"https://iana.org/assignments/http-problem-types#ohttp-key" というProblem typeを定義する。key configurationが間違っていた場合には、これが使える。ただし、これはカプセル化されていない応答として返される(relayによって応答されない可能性もある)点に注意。以下は例。
HTTP/1.1 400 Bad Request
Date: Mon, 07 Feb 2022 00:28:05 GMT
Content-Type: application/problem+json
Content-Length: 106
{"type":"https://iana.org/assignments/http-problem-types#ohttp-key",
"title": "key identifier unknown"}
6. Security Consideration
前提として、oblivious gateway resource と taget resource は同一のオペレータ (serverとよぶ)が運用する前提のもとでのセキュリティ考察。
6.1. Client Responsibilities
あまり特筆すべきことは無い。HPKEに使う鍵(enc)の再利用は止めましょう等。
6.2. Relay Responsibilities
relayは一般的なHTTPメッセージのルーティングルール(RFC9110 HTTP Semantics, Section 7.6 Message Forwarding)に従わなければならない(MUST)が、例外として:
- relayは未知のメッセージを転送すべきではない(SHOULD NOT)。
- 送信元を識別し得るヘッダを追加してはならない(MUST NOT)。
6.2.1. Differential Treatment
大量のリクエストを送ってくるような不正なクライアントの扱いについて。relayはブロックするような対応をしても良いが、これは匿名ユーザ集合を小さくする副作用があることを認識しましょう的な。
カプセル化をほどいて初めてわかる不正なメッセージは、serverでしか処理できない。serverは、特定のクライアントがもんだいであることをrelayにフィードバックしてもよい(MAY)、としている(なんとなく問題がある気がする)。
6.2.2. Denial of Service
relayが多数のクライアントを収容することはプライバシー保護の観点で望ましいが、一方でserverからDoS判定をくらうかもしれない。予め何らかの取り決めが必要かも。
この際、serverは、relayがクライアントが不正なレベルのリクエスト量を許可していないことを信頼する必要があるかもしれない。
高いリクエストレートを可能にするrelayは、gateway上で何らか認証されるかもしれない。
6.2.3. Traffic Analysis
relayは、アクセスタイミングによって匿名性が棄損されることを防ぐために、遅延を入れてもいいかも。clientが許容できる範囲で。
clientは、Binary HTTPメッセージに含めることができるパディングを利用して、トラフィック解析の効果を下げることができる。
6.3. Server Responsibilities
あまり特筆すべきことは無い。
6.4. Key Management
鍵のローテーションをしましょう。
期限切れの鍵や、認識できない鍵IDが使われた場合には、422応答を返すことができる、としている。
6.5. Replay Attacks
serverはリプレイを拒否することとリプレイがclientやresourceに悪影響を与えないことに責任を持たなければいけない。
clientやrelayは、再送に対するポジティブなレスポンス(REFUSED_STREAM, H3_REQUEST_REJECTED, GOAWAYフレーム)を受け取らないうちは再送してはならない(MUST NOT)。
6.5.1. Use of Date for Anti-Replay
serverがDateヘッダを無視しないなら、clientは、Dateヘッダを使うべき(SHOULD)。
6.5.2. Correcting Clock Differences
serverは、Dateヘッダが許容期間外だったら400エラー返しましょう。
clientは、serverから提供される日付情報をいかなる目的にも使ってはならない(MUST NOT)。sercerがclient特定に使うかもしれないので。
6.6. Forward Secrecy
この文書では、key configurationの生存期間は、forward secrecyは提供しない。key configurationのローテーションによってforward secrecyは提供される。
6.7. Post-Compromise Security
この設計では、レスポンスに対する危殆化後のセキュリティは提供しない。クライアントのリスクはわずか。サーバの鍵が漏洩した場合のリスクは、TLSによる保護である程度緩和されるし、影響範囲は、鍵のローテーション期間で調整できる。
6.8. Client Clock Exposure
Dateヘッダを入れるとclient同定、紐づけのリスクがあるので値を散らしましょうという話。
7. Privacy Considerations
ポイントは、key configurationの選択によって匿名clientのグルーピングが可能だということ。選択肢が多いほど細分化できる。
8. Operational and Deployment Considerations
8.1. Performance Overhead
OHTTPの利用は、暗号処理によるオーバーヘッドとリクエストの遅延を引き起こす。relayにより追加遅延を緩和することが出来る。ODoHベースでの評価では、serverの近くにrelayを配置するとコスト低減に効果があるとのこと。
8.2. Resource Mappings
このプロトコルは、relay と gateway の間に固定的な一対一の対応関係を仮定している。つまり、relayに送られた暗号化されたリクエストは、常にgatewayに転送される。この制約は、relayの設定を簡略化するためと、relayが未知のgatewayの汎用relayとして使用されることを防ぐために課されたもの。relayは,明示的に設定され許可された gatewayに対してのみ転送を行う。
1 つのサーバーに複数のrelayを設定し、必要に応じてそれぞれを異なるgateway用に設定することが可能。多数のgatewayをサポートすることを目的とする場合、クライアントには URI テンプレートを提供し、そこから複数のrelayを構築することができるかもしれない。
8.3. Network Management
Oblivious HTTP は、clientをトラストアンカーで設定し TLS 接続を傍受することに依存するようなネットワーク傍受体制と相容れない云々。
フィードバック
個人的に改善したほうが良いと思う点を本家にフィードバックした。