Skip to content

QUIC・TLS 1.3 超入門

QUIC や TLS 1.3 を初めて触れる人向けに、Nocturne プロトコルで使う用語をさらっと解説します。

UDP とは?

UDP は「投げっぱなし」の通信方式です。手紙をポストに投函するように、データ(パケット)を相手に送るだけで、届いたかどうかの確認を基本しません。速いですが、届かない・順番が変わる・内容が壊れるリスクがあります。

TCP は「確実な通信」です。データが届いたか毎回確認し、順番を保証します。ウェブサイトやメールなど長年使われてきましたが、モバイルで Wi-Fi と 4G を切り替えたときに「接続が切れてまた最初から」という弱点があります。

QUIC とは?

QUIC は「UDP の速さを活かしつつ、TCP の安心感を取り戻す」技術です。Google が開発し、今は IETF 標準(RFC 9000)になっています。

  • UDP の上で動く: インターネットのどんな回線でも通ります。
  • TCP の役割を内包: パケットの順序保証や再送は QUIC 自身がやります。
  • 多重ストリーム: 1 本の接続の中で複数の「線路」を同時に走らせられます。A の線路でボイスチャット、B の線路で位置情報、C の線路でオブジェクト情報……といった具合です。ある線路が詰まっても別の線路には影響しません(TCP だと全部止まりがち)。
  • 暗号化が標準: TCP の時代は「まず接続して、後から暗号化(TLS)」が一般的でした。QUIC は最初から暗号化が組み込まれています。

TLS 1.3 とは?

TLS(Transport Layer Security)は「通信相手が本物かどうか確認し、データを暗号化する」ための仕組みです。ブラウザで https:// を開くときに裏で動いています。TLS 1.3 はその最新版で、以前のバージョンより handshake が速く、セキュリティも高くなっています。

QUIC の中では TLS 1.3 が使われています。つまり Nocturne を使うと、最初のパケットから暗号化されています。

ALPN(Application-Layer Protocol Negotiation)

ALPN は「この店で何を注文しますか?」と伝える仕組みです。同じ UDP ポート(例: 443)で複数のプロトコルを運用しているとき、クライアントが「僕は Nocturne で来ました」と宣言し、サーバーが「了解、Nocturne で受け付けます」と応答することで、お互いの言葉が通じることを確認します。

例えば同じポートで HTTP/3 と Nocturne の両方を動かしているサーバーもありえます。このとき ALPN が一致しないと、サーバーは別のプロトコルとして扱うか、接続を断ります。

0-RTT と Early Data

RTT(Round-Trip Time)は「手紙を送って返事が返ってくるまでの時間」です。

通常の TLS 接続では「こんにちは→こんにちは→暗号化の準備しましょう→了解」と何度も往復してからようやくデータを送れます。これを 1-RTT と呼びます。

0-RTT は「前回来た常連」を覚えておく仕組みです。前回の接続情報(鍵の材料)を覚えておくことで、「いきなり暗号化したデータを送る」ことができます。店の常連証を見せると、待たずに入場できるイメージです。

ただし 0-RTT には「リプレイ攻撃」のリスクがあります。 悪意のある人が同じデータを何度もコピーして送りつけると、サーバーが「また常連が来た」と思ってしまう可能性があります。Nocturne では「プレイヤー認証(ログイン)に 0-RTT は使わない」というルールを設けているのは、このためです。認証済みの後のゲームデータなど、安全な用途にだけ使います。

接続移行(Connection Migration)

TCP は IP アドレスとポート番号の組み合わせを「接続の身分証明書」として扱います。そのため、Wi-Fi から 4G に切り替えて IP アドレスが変わると、今までの接続は「別人扱い」になって切れてしまいます。

QUIC は接続自体に固有の ID を持っています。IP アドレスが変わっても「この ID の人だ」と認識できるため、回線を切り替えても通信が継続します。Nocturne のような VR やモバイル環境では、Wi-Fi とモバイル回線を行き来しても drop しにくくなる大きな利点です。

前方秘匿性(Forward Secrecy)

「今使っている鍵が後から盗まれても、過去の通信を復号できない」性質です。TLS 1.3 は毎回異なる一時鍵を使って通信を暗号化するため、将来サーバー証明書の秘密鍵が漏洩しても、過去のセッションの内容は読まれません。

CBOR(Concise Binary Object Representation)

Nocturne は QUIC ストリーム上のデータを CBOR(RFC 8949)というバイナリ形式でやり取りします。

JSON との違い

JSON はテキスト形式です。人間が読める反面、バイト列や数値をそのまま埋め込めず、base64 変換などのオーバーヘッドが発生します。

CBOR は同じデータモデルをバイナリで表現します。JSON の {"nonce": "abc123..."} が 50 バイトかかるところ、CBOR なら 35 バイト程度で済みます。nonce や署名のようなバイト列を文字列変換せずそのまま埋め込めるのも大きな利点です。

キーに文字列も整数も使える

CBOR の map(連想配列)の key は、JSON のような文字列("type")も、整数(1)も使えます。Nocturne ではコアフィールド(よく使うもの)を整数 key で 1 バイトに節約し、拡張フィールドは文字列 key で自由に追加できる混在方式を採用しています。

text
// コアフィールドは整数 key
{1: "auth", 5: "medi:player:ed25519:...", 2: h'...'}

// 拡張フィールドは文字列 key
{1: "auth", "customExtension": "value"}

バイト列はそのまま

nonce(32 バイト)や署名(64 バイト)は文字列に変換せず、生のバイト列として格納します。パース時の base64 デコードバグやエラー処理が不要になります。署名検証用の Canonical JSON を作るときだけ、一時的に base64url 文字列に変換します。