コンパクトTLS (cTLS) 

## 1. はじめに

TLS(Transport Layer Security)のセキュリティプロトコルの仕様としての課題はTLS1.3でかなりのところ整理されました。それでもいくつかの点ではさらに検討が進められています。コンパクトTLS(cTLS)もその一つです。cTLSはTLS1.3[RFC8446]プロトコルの軽量化を目指すプロトコル仕様で、2019年から検討が進められています。RFCとなるにはまだ時間がかかると思われるものの、2022年3月現在[ドラフト5](https://datatracker.ietf.org/doc/draft-ietf-tls-ctls/05/)が公開されていて、その骨格を知ることができます。以下、その内容について紹介します。

## 2. コンパクト化の方針、目標
cTLSはTLSに残されている後方互換性のためのフィールドなどを排除し、楕円曲線の点圧縮などのコンパクトエンコーディング以上の軽量化を目指します。テンプレートベースの特殊化(後述)を利用することで、ネゴシエーションによらずに通信の両者で必要な情報を共有させます。また、準静的ディフィーヘルマンのような新しい暗号技術を取り入れます。

これらによって、使用する証明書が事前に確定している場合(EC)DHEハンドシェークで原理的に必要な最小限の暗号情報サイズに対して45バイトのオーバーヘッド、PSKハンドシェークの場合、21バイトのオーバヘッドでハンドシェークを完了します。

## 3. テンプレートベースの特殊化

TLSは、証明書ベースの認証、生の公開鍵ベースの認証、また事前共有鍵（PSK）ベースの認証などさまざまなスキームを通信相手とのネゴシエーションで決定することができるようになっています。この完全に汎用的なものから、ある自由度を削除してみます。例えば、TLSの１つのバージョンのみをサポートする場合には、バージョンネゴシエーションは不要となり、supported_version拡張を省略することができます。この特殊化されたハンドシェークはワイヤーエンコーディング(ネットワークの物理層に送信される情報)のみに適用されるもので、その内容は同じ機能が使用されたTLS1.3のハンドシェークの内容と等価になります。

特殊化は、ハンドシェイクとレコードレイヤーの間のステートフルな圧縮レイヤーとして見ることができます(下図)。

![cTLS.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/263939/bdea32ee-9d16-085b-295a-61954d49730b.png)

JSON記述された圧縮プロファイルでテンプレートの仕様を規定します。プロファイルでは、アルゴリズム、アルゴリズムパラメータ、また拡張機能の仕様などを定義します。クライアントは使用したいプロファイルをClientHelloのプロファイルフィールドでサーバに通知します。

例えば、固定バージョン（TLS 1.3）と固定暗号スイート（TLS_AES_128_GCM_SHA256）を使用するプロトコルについて説明します。回線上では、ClientHello.cipher_suites、ServerHello.cipher_suitesとClientHelloとServerHelloのsupported_versions拡張機能は省略されます。


```
   {
      "version" : 772,
      "cipherSuite" : "TLS_AES_128_GCM_SHA256"
   }
```

これにより次の要素が定義されます。
- プロファイル（整数）：プロファイルのID。 
- version（integer）：この場合、TLS1.3を示す772 == 0x0304
- cipherSuite（文字列）：[RFC8446]のセクション8.4で定義されている「TLS_AEAD_HASH」構文を使用。
- dhGroup（文字列）：鍵の確立に使用するDHグループを指定。[RFC8446]のセクション4.2.7mpコードポイント名。 （例：x25519）。
- signatureAlgorithm（文字列）：認証に使用する署名スキーム。[RFC8446]のセクション4.2.7にコードポイント名 （例：ed25519）。
- random（integer）：乱数長は32バイト以下
. 相互認証（ブール値）：trueに設定されている場合、クライアントが証明書とCertificateVerifyメッセージを送信して証明書で認証する。 


## 4. 圧縮効果の例

圧縮効果の例として、証明書を使用した相互認証をサポートする完全なcTLSベースの交換を示します。 SHA256およびNISTP256r1でECDSA、Diffie-HellmanはFX25519曲線、スイートはTLS-AES-128-CCM8-SHA256です。 証明書は、既知の証明書のIDを使用して交換されます。

この例での圧縮効果を下のグラフに示します。

![Compression.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/263939/46e8d627-da87-de87-2871-b611d3a727f0.png)


この例には次のプロファイルが使用されています。

```
   {
     "profile": 1,
     "version": 772,
     "cipherSuite": "TLS_AES_128_CCM_8_SHA256",
     "dhGroup": "X25519",
     "signatureAlgorithm": "ECDSA_P256_SHA256",
     "finishedSize": 8,
     "clientHelloExtensions": {
       "server_name": "000e00000b6578616d706c652e636f6d",
     },
     "certificateRequestExtensions": {
       "certificate_request_context": 0,
       "signature_algorithms": "00020403"
     },
     "mutualAuth": true,
     "extension-order": {
          "clientHelloExtensions": {
             Key_share
          },
          "ServerHelloExtensions": {
             Key_share
          },
     },

     "knownCertificates": {
       "61": "3082...",
       "62": "3082...",
       "63": "...",
       "64": "...",
       ...
     }
   }
```

```
   ClientHello: 36 bytes = DH(32) + Overhead(4)

   01                    // ClientHello
   01                    // Profile ID
   0020 a690...af948     // KeyShareEntry.key_exchange
   ServerHello: 36 = DH(32) + Overhead(4)

   02                 // ServerHello
   26                 // Extensions.length
   0020 9fbc...0f49   // KeyShareEntry.key_exchange
   Server Flight: 80 = SIG(64) + MAC(8) + CERTID(1) + Overhead(7)
```

EncryptedExtensions、およびCertificateRequestメッセージは空なので省略します。

```
   0b                 // Certificate
     03               //   CertificateList
       01             //     CertData.length
         61           //       CertData = 'a'
```

```
   0f                 // CertificateVerify
     4064             //   Signature.length
          3045...10ce //   Signature
```

```
   14                 // Finished
     bfc9d66715bb2b04 //   VerifyData
   Client Flight: 80 bytes = SIG(64) + MAC(8) + CERTID(1) + Overhead(7)
```

```
   0b                 // Certificate
     03               //   CertificateList
       01             //     CertData.length
         62           //       CertData = 'b'
```

```
   0f                 // CertificateVerify
     4064             //   Signature.length
          3045...f60e //   Signature
```

```
   14                 // Finished
     35e9c34eec2c5dc1 //   VerifyData
```