HTTP/2 クロスオリジン サーバプッシュを可能にする提案仕様

ちょっと不明瞭な部分が修正できてません。すみません。

20180824追記
Loading Signed Exchangesについて記事を書きました
Loading Signed Exchangesの仕様 (WebPackaging) - ASnoKaze blog

20180213補足
「Origin-signed HTTP Responses」は「Signed HTTP Exchanges」に改称されました。

この仕様では、HTTP Exchange(リクエストとレスポンス)両方を署名対象にし、それらの署名値であるSignatureヘッダをレスポンスヘッダに追加して返します。署名値を計算するために一旦リクエストレスポンスをCBOR形式にシリアライズします。

ただHTTP Exchangeに署名をする仕様という点に注意が必要です

20180208追記
Bundled HTTP Exchangesについて記事を書きました
Bundled HTTP Exchanges とは (WebPackagingの議論より) - ASnoKaze blog


20180121追記
Intent to Implement: Origin-Signed HTTP Exchanges (Part of Web Packaging)
https://groups.google.com/a/chromium.org/forum/#!topic/blink-dev/n7cZXSTwBTY
Chromeでは導入検討中



現状HTTP/2では、クロスオリジンでのサーバプッシュは出来い。

a.comからb.comのコンテンツを、b.comのコンテンツだとしてプッシュされてもクライアントは信頼することが出来ない。

f:id:ASnoKaze:20180211101317p:plain

それを可能にする「Origin-signed HTTP Responses」という仕様がGoogleのJeffrey Yasskin氏から提案されている。

Origin-signed HTTP Responses」では、コンテンツを署名する仕組みを定義している。b.comの署名があれば、b.comのコンテンツを別の所から配布しても信頼できるという感じである。

自分も正しく理解できてるかわからないが、簡単に読んでみた。

Origin-signed HTTP Responses

Origin-signed HTTP Responses」は、以前書いたWebPackagingの議論からでてきた仕様である。
asnokaze.hatenablog.com

Webページを1つにまとめる仕組みとそれに署名する仕組みは分離され、後者が「Origin-signed HTTP Responses」である。

コンテンツをCBOR形式で表現する

再配布するコンテンツは、HTTPリクエストヘッダ・HTTPレスポンスヘッダ含めてCBOR形式でシリアライズしてから署名が行われる

例えば、以下のようなやりとりは

GET https://example.com/ HTTP/1.1
Accept: */*
HTTP/1.1 200
Content-Type: text/html
Signed-Headers: "content-type"

<!doctype html>
<html>
...

CBOR形式で以下のようにシリアライズされます(分かりやすいように書き下されている)

[
  "request",
  [
    ':method', 'GET',
    ':url', 'https://example.com/'
  ],
  "response",
  [
    ':status', '200',
    'content-type', 'text/html'
  ],
  "payload",
  '<!doctype html>\n<html>...'
]

この時、Signed-Headersレスポンスヘッダで指定された領域が署名の対象に含まれる。

Signatureヘッダ

この仕様では、Signatureレスポンスヘッダを新しく定義している。

Signature: sig1;
  sig=*MEUCIQDXlI2gN3RNBlgFiuRNFpZXcDIaUpX6HIEwcZEc0cZYLAIga9DsVOMM+g5YpwEBdGW3sS+bvnmAJJiSMwhuBdqp5UY;
  validityUrl="https://example.com/resource.validity";
  certUrl="https://example.com/certs";
  certSha256=*W7uB969dFW3Mb5ZefPS9Tq5ZbH5iSmOILpjv2qEArmI;
  date=1511128380; expires=1511560380
  • sig: 署名 (リクエストメソッド, リクエスURI, Signed-Headersで指定されたレスポンスヘッダ, ペイロードの署名)
  • validityUrl: 署名が更新(expire)された場合、validityUrlで指定された場所に新しい署名が格納されている
  • certUrl: 証明書のURL。TLS1.3のCertificate message形式のデータが得られる
  • certSha256: 証明書のハッシュ
  • date: 現在のUnix Time
  • expires: 失効 Unix Time (現在時間より7日以内である必要がある)

元コンテンツがレスポンスする際にSignatureヘッダを付けてくるので、再配布者はこれをそのまま再配布すれば良い

クライアントはそのコンテンツの署名を確認し、有効であれば受け入れる。

HTTP/2 extension for cross-origin Server Push

HTTP/2でクロスオリジン サーバプッシュを可能にするため、幾つかの拡張を定義している。

まだ、IETFに提出されている提案仕様では含まれていないが、Github上ではmasterにコミットされている(コミットURL)

  • ENABLE_CROSS_ORIGIN_PUSH SETTINGSパラメータ: クロスオリジン サーバプッシュに使うことをネゴシエーションするためのSETTINGSパラメータ
  • NO_TRUSTED_EXCHANGE_SIGNATURE error code: プッシュされたコンテンツが署名検証できなかったときなど、信頼できなかったときのエラー

雑感

なんでサーバ証明書そのものを、ヘッダに入れないんだろうか、キャッシュできるようにかな

preloadを使うのがシンプルで強力だが、クロスオリジン サーバプッシュも面白いなと思いました。