Content-Encoding: aes128gcm とは (RFC8188)

20170624追記
RFC8188 として標準化されました


HTTPリクエスト・レスポンスのボディを暗号化する、「Content-Encoding: aes128gcm」を新しく標準化する「Encrypted Content-Encoding for HTTP」という仕様が議論されております。


提案自体は数年前に行われており、すでにWGドラフトになっています。

Encrypted Content-Encoding for HTTP

この仕様では、HTTPのボディをAEAD_AES_128_GCMで暗号化します。HTTPSと違って通信路だけでなく、アップロードファイル・ダウンロードファイル自体が暗号化されているため、ファイルが保存される場合も鍵を知っている人(ソフトウェア)のみがその内容を読むことができます。


仕様上では上記のような例があげられておりますが、IETFで同様に議論されているPush通知の標準プロトコル Web Push でこの仕様を使用します。「Message Encryption for Web Push」という仕様で、Content-Encoding: aes128gcmを使ってPush通知の暗号化プロトコルが実現されています。

暗号化概要

この仕様では、暗号化されたデータの他にも幾つかのパラメータをHTTPボディに含めて送信します。


具体的には下記のパラメータが暗号データ以外に送信されます

+-----------+--------+-----------+---------------+
| salt (16) | rs (4) | idlen (1) | keyid (idlen) |
+-----------+--------+-----------+---------------+
  • salt: ソルト
  • rs: レコードサイズ
  • idlen: keyidの長さ
  • keyid: keying materialの識別子


特徴として鍵交換の具体的方法は定義されておりません、別途別の手段で交換する必要があります。この仕様ではお互いにどのkeying materialを使用しているか識別するためのkeyidを通知するだけになります。


実際に暗号化に使用する鍵は、keying materialより導出されます。

鍵の導出

送信したパラメータと、keying materialより暗号化に用いる鍵を導出します
input keying material (IKM), pseudorandom key (PRK), content encryption key (CEK)

   PRK = HMAC-SHA-256(salt, IKM)
   cek_info = "Content-Encoding: aes128gcm" || 0x00
   CEK = HMAC-SHA-256(PRK, cek_info || 0x01)

( || は結合)

ノンスの導出

同様にノンスも導出します
The record sequence number (SEQ)

   nonce_info = "Content-Encoding: nonce" || 0x00
   NONCE = HMAC-SHA-256(PRK, nonce_info || 0x01) XOR SEQ

レコードのシーケンス番号がつくことで、順番の入れ替えや欠落を検出できるようになっております。

パディングの順番が変更になりそうですので、その例でどのように暗号化されるか見ていきます。
( https://github.com/httpwg/http-extensions/blob/0f3ff05b3679f9ead35c1be800723e73915b6aaf/draft-ietf-httpbis-encryption-encoding.md )


この例では、暗号化するデータは「I am the walrus」(UTF-8)、keying materialは「B33e_VeFrOyIHwFTIfmesA」(base64)、keyidは空文字列

HTTP/1.1 200 OK
Content-Type: application/octet-stream
Content-Length: 54
Content-Encoding: aes128gcm

I1BsxtFttlv3u_Oo94xnmwAAEAAA-NAVub2qFgBEuQKRapoZu-IxkIva3MEB1PD-
ly8Thjg
  • salt (from header) = I1BsxtFttlv3u_Oo94xnmw
  • PRK = zyeH5phsIsgUyd4oiSEIy35x-gIi4aM7y0hCF8mwn9g
  • CEK = _wniytB-ofscZDh4tbSjHw
  • NONCE = Bcs8gkIRKLI8GeI8
  • plaintext = SSBhbSB0aGUgd2FscnVzAg