inthisfucking.world

💩🌎

Signalシリーズ: Signal Protocolを実装する - 1

この記事は下書きです
続きを希望される場合は、コメントを残してください。著者のやる気が出ます。

End-to-end encryption (E2EE) として広く採用されているSignal Procotolを、実際に実装していくシリーズです。第一弾として、私が現段階でSignal Procotolに関して分かっていること、なぜSignal Procotolを実装したいのかを書きます。

なぜSignal Procotolを実装したいのか

前提

Signal Procotolの背景

Signal Procotolの概要

XEdDSAとVXEdDSA

XEdDSAは、X25519及びX448を用いた楕円曲線ディフィー・ヘルマン鍵共有を使用したデジタル署名のスキーマです。ここで言うスキーマは、英語のschemaで、このコンテキストにおいては、データベースにおけるテーブルのスキーマの様な、仕様とか定義みたいな意味です。

セキュリティの専門家でもない限り、この一文でもう何がなんだか分からないと思います。私も今でもそうなので、自分に対するメモの意味と、普段英語で読み書きしているセキュリティの専門用語の正しい日本語訳を知るためにも少し掘り下げて解説します。

注意
間違えているところが沢山あると思うので、コメントで指摘を頂けると嬉しいです。

まず、デジタル署名が何なのかから解説します。デジタル署名は、署名されたデータを受け取った人が、そのデータが本当に期待した人が作成したものなのかどうかを判断するために使用します。対となった公開鍵と秘密鍵を必要とし、秘密鍵を使って署名し、公開鍵を使って署名を確認します。

例えば、Aliceがデジタル署名したとされるデータをサーバから受け取ったとします。それは本当にAliceが署名したものなのか、はたまたサーバがAliceが署名したと言っているだけで本当は違うのか、受け取った側はそれを確かめる必要がある場合があります。AliceがAliceの秘密鍵でデジタル署名をするため、対となった公開鍵を用いてデジタル署名が正しいとされた場合は、そのデータは本当にAliceが署名したのだと強く確信することができます (勿論、Aliceではない者がAliceの秘密鍵を保持しており、Aliceではない者が署名した可能性は残ります)。

デジタル署名の生成には秘密鍵を、確認には対となる公会鍵を使用しますが、デジタル署名はデータを暗号化するものではありません。

つまり、XEdDSAは公開鍵と秘密鍵を用いたデジタル署名のスキーマです。楕円曲線ディフィー・ヘルマン鍵共有 (楕円曲線を用いるディフィー・ヘルマン鍵共有) は、なんらかしらの楕円曲線を用いた方法で生成された公開鍵と秘密鍵を使用して、両者間で共有した秘密の値を確立する方法です。X25519及びX448は、楕円曲線を用いた公開鍵と秘密鍵を生成する方法の種類です (楕円曲線ではない方法で公開鍵と秘密鍵を作成する方法としてはRSAが有名です)。

とても重要なのが、ディフィー・ヘルマン鍵共有の特徴です。両者間で共有した秘密の値を確立する際、その一連のやり取りが盗聴されていてもその秘密の値が安全であることが担保されています。

VXEdDSAは、XEdDSAを拡張したもので、XEdDSAと同じ入力を期待するデジタル署名のアルゴリズムです。XEdDSAの出力を検証できるようにしたものがVXEdDSAです (先頭のVはverifiableのvだと思います)。暗号理論 (cryptography) においては、この様な性質を持つ関数をverifiable random function (VRF) と呼ぶそうです。

VXEdDSAを使用したデジタル署名を検証する際には、XEdDSAの場合と同じ入力、ただしXEdDSAの署名ではなくVXEdDSAの署名が必要になります (当然ですが)。

X3DH

Double Ratchet

Double Ratchetは、両者間において共有された秘密を元に、暗号化されたメッセージをやり取りするために使用されるアルゴリズムの仕様です。

Double Ratchetに従ってメッセージをやり取りする両者は、メッセージごとに新しい鍵を生成します。これによって、過去に使用された鍵がその後に生成された鍵から計算できないようにしています。両者は更に、メッセージにDiffie-Hellman public value [TODO] を含ませます。Diffie-Hellmanの計算 [TODO] の結果は、鍵を生成する際の入力の一部として使用するので、過去の鍵からその後に生成される鍵を計算できないようにしています。

Double Ratchetのアルゴリズムの中核となるのが、KDF chainという概念です。KDFはcryptographic functionであり、ある秘密とランダムなKDF key、そしてなんらかしらの入力データをその入力とし、出力データを返します。このKDFの出力データの一部をoutput keyとして使用し、更に一部をKDF keyとして置き換える場合、これをKDF chainと呼びます。

Double Ratchetのセッションにおいて、AliceとBobはKDF keyをroot chain、sending chain、receiving chainの三つのchainで保存します。

AliceとBobは、新しいメッセージをやり取りする度にDiffie-Hellman public keysもやり取りし、Diffie-Hellmanの出力として得られる秘密はroot chainの入力となります。root chainの出力は、sending chainとreceiving chainに対する新しいKDF keyとなります。これを、Diffie-Hellman ratchetと呼びます。

sending chainとreceiving chainは、メッセージがやり取りされる度に進んでいきます。これらのchainからのoutput keyは、メッセージを暗号化及び復号するために使用されます。これを、 symmetric-key ratchetと呼びます。

Double Ratchet with header encryption

With header encryption each party stores a symmetric header key and next header key for both the sending and receiving directions.

ヘッダーを特定のdouble ratchetのセッションと関連付けなければならないが、その方法はsignalプロトコルでは定義されていない。

Successful decryption with the next header key indicates the recipient must perform a DH ratchet step. During a DH ratchet step the next header keys replace the current header keys, and new next header keys are taken as additional output from the root KDF.

参考文献

次回