「Rougtime」という時刻同期プロトコルの標準化が進められている。
すでに、GoogleやCloudflareがRoughtimeサーバを公開している
- roughtime.cloudflare.com
- roughtime.sandbox.google.com
もともとは、2016年頃にGoogleのAdam Langley氏が原案を公開しており、サーバの実装が進められた。その後、時刻同期プロトコルを扱うIETFのNTP WGに仕様が提出されました。そして2020年1月に、「Rougtime」としてWG Draftになり標準化が進められています。
Roughtimeプロトコルの特徴
Roughtimeは以下の特徴を持つ
- クライアントからリクエストを送信し、サーバから署名を付けてレスポンス(時刻+証明書+署名)を返す
- 複数サーバを利用することで、暗号的に不正なサーバを暗号的に検知できる
- UDPとTCPに対応。UDPでは、アンプ攻撃対策が入ってる。
- サーバにおける署名処理は、複数クライアントからのリクエストを一気に署名できるようになっている
- バッチ的に処理を行うため、高精度の時刻同期ではない
(図はリクエスト/レスポンス内に含まれるタグを一部咲楽しています)
Rougtimeでは、クライアントからリクエストを送り、サーバから署名のついたレスポンスが返されます。サーバの署名がついてますので、クライアントはサーバを認証できます。
クライアントはリクエストにノンス(NONC)をつけて送ります。これに対してサーバ側はレスポンス(時刻+証明書+ノンスに対する署名 SIG)を返します。これにより、クライアントからのリクエストを受信したあとに、レスポンスが生成されたことを暗号的に保証することができます。
クライアントはサーバAからのレスポンスを、乱数と結合しハッシュを撮った値を付きのサーバBへのノンスとして送ります。こうすることで、「サーバAからの時刻 < サーバBからの時刻」ということことが暗号的に保証されます。こうすることで、暗号的に不正な値を返すサーバを見つけることができます。
各サーバは事前に長期鍵として公開鍵を公開している。その鍵で一時鍵を署名して、その一時鍵を用いてクライアントからのリクエストに対して署名処理をする。
例えば、Cloudflareでは長期鍵はこのように公開されています。
address: roughtime.cloudflare.com port: 2002 long-term key: gD63hSj3ScS+wuOeGrubXlq35N1c5Lby/S+T7MNTjxo=
メッセージ
リクエストおよび、レスポンスのメッセージは下記の構造を持ちます。タグというキー・バリューのペアが複数含まれます。
最初にタグの数と、メッセージの中で1~N番目のタグがどこから始まるか示すオフセット、32bitのタグ(ASCIIでNONCやVERのように表現されます)およびタグの値が繰り返されます。
レスポンス
レスポンスには、時刻を示すMIDP、証明書を示すCERT、署名値SIGとマークルツリー(後述) ROOT INDEX PATHなどである。
署名対象はSREPであり、ここに時刻やマークルツリーのROOTの値の値が含まれている。複数のリクエストを一度に処理する場合、このPREPが同じ値になる。
Response
署名のバッチ処理
Routhtimeでは、サーバは複数のリクエストのノンスに対して一度に署名処理を行います。これは、先述のマークルツリーを利用します。
ツリーの各リーフには、複数のクライアントから送られてきたノンス(NONC)が含まれます。各リーフは左から順にindexを持ちます。
親は、左のノードと右のノードを結合しハッシュを取った値が含まれています。
順々にハッシュを取ってルートが計算されると、ルートの値と時刻情報を合わせて署名を行います。その署名結果を複数のリクエストに対するレスポンスに含めます。
クライアントは署名値を検証するのにマークルツリー全体の情報は必要なく、自身の送ったノンス(NONC)のindex, ROOT, およびPATH(ROOTまでハッシュを計算するのに必要なノードの値)のみが必要です。
例えば、index3のPATHは赤く囲ったノードになります。