複数TLSコネクションの署名処理をまとめて行うBatch Signing

GoogleのDavid Benjaminさんにより「Batch Signing for TLS」という仕様が提出されています。

TLSではハンドシェイク中に証明書を持っていることを証明するために、対応する秘密鍵を用いて署名を行います。この署名処理(特にRSA署名)はCPUをたくさん消費するほか、秘密鍵をハードウェアモジュールに格納している場合はオーバーヘッドが高くなります。

この署名処理を、複数コネクション分をまとめて1回で行ってしまうのが「Batch Signing for TLS」です。

Acknowledgmentsに書かれているとおり、Roughtimeプロトコルに同じような機能があります

概要

複数のハンドシェイク中のコネクションから、署名を行うメッセージを集め、Merkleツリーを構成します。

葉を署名対象のメッセージのハッシュ値として、ルートにのみ署名を行います。そのため、複数のメッセージに対して1回の署名で済ませることができます。

メッセージ1, 2, 3をBatch Signingする場合
f:id:ASnoKaze:20190730180837p:plain

  • 葉の初期化: 各メッセージ1, 2, 3 のハッシュ値を偶数番号の葉とします。奇数番号の葉は乱数です。
  • ノードの計算: 各レベルごとに、左右の子を連結したハッシュをノードの値とします
  • ルートの計算: ルートまでノードの値を計算します。

ノードに署名をします。

署名を検証する場合、ルートを計算するのに必要なノードのみが与えられます。メッセージ2を検証する場合、必要なノードはt03, t10, t21です。このノードを順々に連結しハッシュを求めることでルートの値を計算でき、署名値を検証できます。

もちろん、検証する際に他のコネクション用のメッセージを取得できると問題です。そのため、署名するメッセージは偶数番号の葉で、奇数番号は乱数であり結合しハッシュを取ったもののみが他の人にも共有されるため、メッセージ自体がなんだったかそのハッシュ値さえわかりません。

SignatureScheme

Batch Signing用のSignatureSchemeも追加で定義します

       enum {
           ecdsa_secp256r1_sha256_batch(TBD1),
           ecdsa_secp384r1_sha384_batch(TBD2),
           ecdsa_secp521r1_sha512_batch(TBD3),
           ed25519_batch(TBD4),
           ed448_batch(TBD5),
           rsa_pss_pss_sha256_batch(TBD6),
           rsa_pss_rsae_sha256_batch(TBD7),
           rsa_pkcs1_sha256_legacy_batch(TBD8),
           (65536)
       } SignatureScheme