Double Ratchet

概要

The Double Ratchet Algorithm

Double Ratchet は X3DH でセッション確立後に双方でメッセージを送信する場合に、 Forward security と Post-Compromise Security を実現するための仕組みです。

簡単に言えばどこかのタイミングで秘密鍵が危殆化した場合に、過去も未来も見れない事を実現します。

Double Ratchet という名の通り、相対鍵ラチェットとディフィー・ヘルマンラチェットの2つの組み合わせを利用します。 ラチェットというのは歯止めという意味で逆回転しないという意味だそうです。自分はこれで初めて知りました。

解説

Alice と Bob で説明していきます。ただしメッセージスキップやヘッダーの暗号化については割愛します。

Alice と Bob は X3DH によってセッションがはられている状態になっています。そこで双方でメッセージを送ろうとします。今回も Alice からメッセージを送ります。

Alice はメッセージを送りたいのですが、まずはラチェット鍵ペアを生成します。 これは x25519 の鍵ペアです。ラチェット鍵の秘密鍵と、Bob の中期的公開鍵の DH を行います。

得られた値からルート鍵とチェイン鍵を取得します。このチェイン鍵を利用して AES-GCM 用の共通鍵を生成します。そうしたらチェイン鍵を HKDF-SHA256 に入れて、新しいチェイン鍵を生成します。このチェイン鍵は相手からメッセージが送られてこない状態で、次のメッセージを送る際に利用します。

ここで X3DH で得ている SK を利用します。

A = DH(AliceRatchetPrivateKey, BobPrePublicKey)
RootKey[32], ChainKey[32] = HKDF-SHA256(A, SK, "Ratchet")
Seed = HMAC-SHA256(ChainKey, 0x01)
MessageKey[32], Nonce[12] = HMAC-SHA256(Seed, "MessageKeys")

AD = AliceIdenityPublicKey + BobIdentityPublicKey

Ciphertext = AES-GCM(MessageKey, Nonce, Plaintext, AD)

あとは得られた共通鍵でメッセージを暗号化します。

メッセージ送信時にラチェット公開鍵などをヘッダーに追加して暗号化されたメッセージを Bob に送ります。

そしてここまでは Bob がオフラインでも実現できます。つまりメッセージを送るだけであれば Bob がオンラインである必要はないのが特徴です。

追加でメッセージを送る場合はさきほど新しく生成したチェイン鍵を利用し新しく共通鍵を生成します。 その後、新しくチェインキーを HMAC-SHA256 で生成します。

NewChainKey = HMAC-SHA256(PreviousChainKey, 0x02)

1 メッセージごとに共通鍵が変わります。

Bob がオンラインになり、Alice からのメッセージを受信し、その後 Bob も新しくラチェット鍵ペアを生成し、 送られてきた Alice のラチェット公開鍵を利用して DH で得られた値からルート鍵、チェイン鍵を生成し、チェイン鍵から共通鍵を利用します。

Alice はこれを受け取ったあとにメッセージを送る場合、 Bob から送られてきたラチェット公開鍵と新しくラチェット鍵ペアを生成してそのラチェット秘密鍵で DH を行います。

このときにルート鍵を利用して KDF を行い新たにルート鍵とチェイン鍵を生成します。1 メッセージごとにチェイン鍵が更新され、 さらに相手からメッセージを受信するたびにそもそものルート鍵とチェイン鍵が更新されるというのが Double Ratchet の仕組みになります。

Sora での利用

Sora では Double Ratchet を用いて暗号化したメッセージを Sora 経由で配信します。 用途としては主に音声や映像ストリームを複合するのに必要な鍵の配布です。