オニオンルーティング
この章では、ライトニング・ネットワークのオニオン・ルーティング・メカニズムについて説明します。オニオンルーティングの発明は、ライトニングネットワークより25年も前なのです!オニオンルーティングは、米国海軍の研究者によって通信セキュリティプロトコルとして発明されました。オニオンルーティングは、米国海軍の研究者によって通信セキュリティプロトコルとして発明されました。オニオンルーティングは、研究者、活動家、諜報員、その他すべての人が個人的かつ匿名でインターネットを利用できるオニオンルーティングのインターネットオーバーレイであるTorで最も有名に使用されています。
この章では、Lightning プロトコルアーキテクチャの「ソースベースオニオンルーティング(SPHINX)」の部分に焦点を当て、Lightning プロトコルスイートにおけるオニオンルーティングの中央(ルーティング層)にあるアウトラインで強調しています。
https://scrapbox.io/files/6329957a1c23220022da09de.png
図1. Lightningプロトコルスイートにおけるオニオンルーティング
オニオンルーティングとは、暗号化通信の手法の1つで、メッセージ送信者が暗号化のネストされた層を次々と構築し、各中間ノードによって「剥がされ」、最も内側の層が目的の受信者に配信されるというものです。オニオンルーティング」という名称は、タマネギの皮のように一度に1層ずつ剥がされる層状の暗号化の使い方を表している。
各中間ノードが「剥がす」ことができるのは1層だけで、次に通信路を通るのは誰かを確認することができます。オニオンルーティングでは、送信者以外の誰も通信経路の宛先や長さを知らないようにする。各中間ノードが知っているのは、前のホップと次のホップだけである。
ライトニング・ネットワークは、George DanezisとIan Goldbergが2009年に開発したSphinx1をベースにしたオニオン・ルーティング・プロトコルの実装を使用している。 ライトニング・ネットワークにおけるオニオンルーティングの実装は、BOLT #4: Onion Routing Protocolで定義されている。 オニオンルーティングを説明する物理的な例
オニオンルーティングを説明する方法はたくさんあるが、最も簡単な方法の1つは、封をした封筒に相当する物理的なものを使うことである。封筒は暗号化のレイヤーを表し、指定された受信者だけが封筒を開けて中身を読むことができる。
例えば、アリスがディナに秘密の手紙を、いくつかの仲介者を介して間接的に送りたいとしましょう。
経路の選択
ライトニング・ネットワークはソース・ルーティングを採用しています。つまり、支払い経路は送信者によって選択・指定され、送信者のみが選択することができます。この例では、アリスからディナへの秘密の手紙が支払いに相当することになります。手紙がディナに届くように、アリスはボブとチャンを仲介して、アリスからディナへの経路を作ります。
ヒント
アリスがディナに到達するための経路はたくさんあるかもしれません。最適な経路を選択する過程は path_finding で説明します。ここでは、アリスが選択した経路が、ボブとチャンを仲介してディナに到達するものと仮定します。 念のため、アリスが選択した経路をPathに示す。アリス→ボブ→チャン→ディナ。
https://scrapbox.io/files/62d689b03c70bb001dfa27e4.png
図2. パス アリス→ボブ→チャン→ディナ
アリスが仲介者のボブとチャンに情報を明かさずにこの経路を使う方法を見てみましょう。
ソースベースルーティング
ソースベースのルーティングは、初期には可能でしたが、今日インターネット上でパケットが典型的にルーティングされる方法ではありません。インターネットルーティングは、各中間ルーティングノードでのパケットスイッチングに基づいている。例えば、IPv4パケットには送信者と受信者のIPアドレスが含まれており、他のすべてのIPルーティングノードが各パケットを宛先に向けてどのように転送するかを決定する。しかし、このようなルーティングメカニズムでは、すべての中間ノードが送信者と受信者を見ることができるため、プライバシーが確保できず、決済ネットワークでの使用には適していない。
https://scrapbox.io/files/63299607822f0b001dcf0b28.png
図3. 封筒に封印されたディナの密書
ディナの手紙は、"道 "でディナのすぐ前にいるチャンがディナに届けることになる。そこで、アリスはディナの封筒をチャン宛の封筒の中に入れる(ディナの封書が入ったチャンの封筒参照)。チャンが読めるのは宛先(経路指示)の部分だけである。"ディナへ" これをChan宛の封筒に封入することは、Chanの公開鍵で暗号化し、Chanだけが封筒の宛先を読めるようにすることを意味します。しかし、ChanはDinaの封筒を開けることができません。彼が見ることができるのは、外側に書かれた指示(住所)だけだ。
https://scrapbox.io/files/6329968502a9d3002350e58f.png
図4. Dinaの封書が入ったChanの封筒
さて、この手紙はボブによってChanに届けられる。そこで、アリスはそれをボブ宛の封筒に入れます (Chanの封書を入れたボブの封筒を参照)。前と同じく、封筒はボブだけが読める、ボブへの暗号化されたメッセージを表しています。ボブはChanの封筒の外側(住所)しか読めないので、 Chanに送ることがわかります。
https://scrapbox.io/files/632996a4e25bf9001d2ff8f4.png
図5.ボブの封筒、チャンの封書が入った封筒
さて、もし封筒の中を見ることができたら(X線で!)、「入れ子の封筒」のように、封筒が1つずつ入れ子になっているのが見えるでしょう。
https://scrapbox.io/files/632996c416eaa20021a6fd52.png
図6. ネストされたエンベロープ
レイヤーをはがす
アリスは今、外側に "To Bob" と書かれた封筒を持っています。これはボブだけが開ける(復号する)ことのできる暗号化されたメッセージを表しています。アリスはこれをボブに送ることから始めます。全体のプロセスはSending the envelopeに示されています。
https://scrapbox.io/files/632996e6c78a8a001d7bf3d0.png
図7. 封筒を送る
見てわかるように、ボブはアリスから封筒を受け取っています。彼はそれがアリスから来たことは知っていますが、 アリスが最初の送り主なのか、それとも封筒を転送しているだけの人なのかはわかりません。彼はそれを開けて、中に "To Chan" と書かれた封筒を見つける。これはチャンに宛てたものなので、ボブはそれを開けることができない。彼はその中身を知らないし、Chanが手紙を受け取っているのか、それとも別の封筒を転送しているのかも知らない。ボブは、Chanが最終的な受取人であるかどうか分からない。ボブは封筒をChanに転送する。
Chanはボブから封筒を受け取る。彼はそれがアリスから来たものであることを知らない。彼はボブが仲介者なのか手紙の差出人なのか知らない。Chanが封筒を開けると、中には「To Dina」と書かれた別の封筒が入っていた。ChanはそれをDinaに転送するが、Dinaが最終的な受取人であるかどうかは分からない。
DinaはChanから封筒を受け取る。開けてみると、手紙が入っており、このメッセージの受取人が自分であることがわかる。彼女はその手紙を読み、仲介者の誰もそれがどこから来たのか知らないし、他の誰も彼女の秘密の手紙を読んでいないことを知る!これがオニオンルーティングの本質である。
これがオニオンルーティングの真骨頂である。送信者はメッセージを何重にも包み、それがどのようにルーティングされるかを正確に指定し、仲介者が経路やペイロードに関する情報を得るのを防ぐ。各中間送信者は1つのレイヤーを剥がし、転送先アドレスのみを確認し、パスの前と次のホップ以外は何も知らない。
では、ライトニング・ネットワークにおけるオニオンルーティングの実装の詳細を見ていこう。
HTLCのオニオンルーティングの紹介
ライトニングネットワークのオニオンルーティングは一見複雑に見えますが、基本的な考え方を理解すれば、実にシンプルなものです。
実用的な観点では、アリスはすべての仲介ノードに、経路上の次のノードと設定するHTLCを伝えています。
最初のノード(この例では支払送信者またはアリス)は、オリジンノードと呼ばれます。最後のノード(この例ではDina)は、最終ノードと呼ばれる。
各中間ノード(この例ではBobとChan)はホップと呼ばれる。各ホップは次のホップへの発信 HTLC をセットアップしなければならない。アリスが各ホップに伝える情報は、ホップペイロードまたはホップデータと 呼ばれます。アリスからディナに送られるメッセージはオニオンと呼ばれ、各ホップに暗号化されたホップペイロードまたはホップデータメッセージで構成されています。
ライトニングオニオンルーチングで使われる用語がわかったところで、アリスのタスクを再表現しましょう。アリスはホップデータでオニオンを構築し、最終ノード(Dina)に支払いを送るための送信HTLCを構築する方法を各ホップに伝えなければなりません。
アリスはパスを選択する
ルーティング]から、アリスは5万サトシの支払いをボブとチャン経由でDinaに送ることが分かっている。この支払いは、AliceからDinaへのHTLCによる支払い経路に示されるように、一連のHTLCを介して送信される。
https://scrapbox.io/files/6329973f046cd6001f98cd85.png
図8. アリスからディナへのHTLCを用いた支払い経路
gossip]で説明するように、LightningノードがLightning Gossip Protocolを使用してLightningネットワーク全体にチャンネルを発表するため、アリスはDinaへのこのパスを構築することができます。最初のチャンネル発表の後、ボブとチャンはそれぞれ、支払いルーティングのためのルーティング料とタイムロックの予想を含む追加のchannel_updateメッセージを送りました。
発表と更新から、アリスはボブ、チャン、ディナ間のチャネルについて以下の情報を知っている。
各チャネルの short_channel_id (短いチャネル ID) (アリスが経路を構築する際にチャネルを参照するために使用する)
Cltv_expiry_delta(タイムロックの差分):アリスが各HTLCの有効期限に追加できる。
fee_base_msatとfee_proportional_millionths。これは、アリスがそのチャネルでのリレーに対してそのノードが期待するルーティングフィーの合計を計算するために使用できる。
実際には、チャネルが伝送する最大の (htlc_maximum_msat) および最小の (htlc_minimum_msat) HTLC など、他の情報も交換されますが、これらは前述のフィールドほど直接オニオンルート構築中に使用されません。
この情報は、Alice が次の詳細経路のノード、チャネル、料金、タイムロックを特定するために使用されます (A detailed path constructed from gossiped channel and node information)。
https://scrapbox.io/files/632997d9856372001d82e697.png
図9. ゴシップされたチャネルとノード情報から構築された詳細なパス
アリスはすでにボブへの自分のチャネルを知っているので、パスを構築するためにこの情報を必要としません。また、アリスはディナからのチャネル更新を必要としません。なぜなら、パスの最後のチャネルについて、チャンからの更新があるからです。
アリスがペイロードを構築する
アリスが各ホップに伝える情報には 2 つの形式があります: ホップデータと呼ばれる固定長の形式と、 ホップペイロードと呼ばれるより柔軟な Type-Length-Value (TLV) ベースの形式です。TLVメッセージフォーマットはtlvでより詳細に説明されています。これは、プロトコルにフィールドを自由に追加することができる柔軟性を提供します。 備考
どちらの形式も、BOLT #4: Onion Routing Protocol, Packet Structureで規定されています。 アリスは経路の終端から逆算してホップデータの構築を開始する。Dina、Chan、Bobの順にホップデータを構築する。
Dinaの最終ノードペイロード
アリスはまず、Dinaに配送するペイロードを構築します。Dinaは最終ノードであり支払いの受取人なので、Dinaは "送信 HTLC "を構築しない。このため、Dinaのペイロードは他のすべてのペイロードと異なる(short_channel_idにすべてゼロを使用)が、オニオンの最も内側の層で暗号化されるのでDinaだけがこれを知ることができる。基本的に、これは物理的な封筒の例で見た「Dinaへの秘密の手紙」のようなものです。
Dinaのホップペイロードは、DinaがAliceのために生成した請求書の情報と一致しなければならず、TLV形式で以下のフィールドが含まれます(最低でも)。
amt_to_forward
amt_to_forward この支払いの金額(ミリサトシ)。amt_to_forward この支払いの金額(ミリサトシ)。これがマルチパートの支払いの一部である場合、金額は合計より少なくなる。そうでなければ、これは単一の完全な支払いであり、請求書の金額とtotal_msatの値に等しくなる。
アウトゴーイング_cltv_value
請求書のmin_final_cltv_expiryの値に設定された支払い期限タイムロックです。
支払秘密
Dinaがこの受信支払いを認識することを可能にする、請求書からの特別な256ビットの秘密値。これは、これまでゼロバリューの請求書を安全でなくしていたプロービングの一種を防ぐことにもなります。この値は受信者だけに暗号化されるため、中間ノードによるプロービングは軽減されます。つまり、中間ノードは「正規に見える」最終パケットを再構築することができないのです。
total_msat
請求書と一致する合計金額。1つしかない場合は省略可能で、その場合はamt_to_forwardと一致し、請求書の金額と等しくなければならないと仮定される。
アリスがディナから受け取った請求書の金額は50,000 satoshisと指定されていた。Dinaは支払いの最小有効期限min_final_cltv_expiryを18ブロック(平均10分のビットコインブロックで考えると3時間)と指定した。アリスが支払いを行おうとした時点で、ビットコインのブロックチェーンは70万ブロックを記録しているとします。したがって、アリスはoutgoing_cltv_valueを最小ブロック高700,018に設定しなければならない。
アリスはディナに対するホップペイロードを以下のように構築する。
code:payload
amt_to_forward : 50,000,000
outgoing_cltv_value: 700,018
payment_secret: fb53d94b7b65580f75b98f10...03521bdab6d519143cd521d1b3826
total_msat: 50,000,000
アリスはそれをTLV形式でシリアライズします。(簡略化)ディナのペイロードはアリスによって構築されます。
https://scrapbox.io/files/632998cdc78a8a001d7c0821.png
図10. DinaのペイロードはAliceによって構築される
Chanのホップペイロード
次に、アリスは Chan のためにホップペイロードを構築します。これは Chan に Dina への発信 HTLC をどのようにセットアップするかを伝える。
Chanのホップペイロードはshort_channel_id、amt_to_forward、outgoing_cltv_valueの3つのフィールドを含む。
code:payload
short_channel_id: 010002010a42be
amt_to_forward: 50,000,000
outgoing_cltv_value: 700,018
アリスはこのペイロードをTLV形式でシリアライズします。(簡略化)Chanのペイロードはアリスによって構築されます。
https://scrapbox.io/files/632999240ce465001d6065bf.png
図11. ChanのペイロードはAliceによって構築される
Bobのホップペイロード
最後に、アリスはボブ用のホップペイロードを構築します。このペイロードには、チャン用のホップペイロードと同じ3つのフィールドが含まれますが、値は異なります。
code:payload
short_channel_id: 000004040a61f0
amt_to_forward: 50,100,000
outgoing_cltv_value: 700,038
ご覧のように、amt_to_forwardフィールドは50,100,000ミリサトシ、つまり50,100サトシとなっています。これは、ChanがDinaへの支払いをルーティングするために100サトシの手数料を期待しているからです。チャンがその送金手数料を「稼ぐ」ためには,チャンの受信側HTLCは,チャンの送信側HTLCより100サトシ多くなければならない。Chanの受信HTCはBobの送信HTCであるから、Bobへの指示はChanが獲得した手数料を反映する。簡単に言えば、BobはChanに5万サトシを送り、Chanが100サトシをキープできるように、5万100サトシを送るよう指示する必要がある。
同様に、Chanは20ブロックのタイムロック・デルタを期待する。従って、Chanの受信するHTLCはChanの送信するHTLCより20ブロック後に期限切れとならなければならない。これを達成するために、アリスはボブに、チャンからディナへの HTLCより20ブロック遅いブロック高700,038でチャンへの送信 HTLCの有効期限が切れるように伝える。
ヒント
チャネルの料金およびタイムロックデルタの期待値は、受信 HTLC と送信 HTLC の差によって設定されます。受信 HTLC は先行ノードによって作成されるので、その先行ノードへのオニオンペイロードに 料金とタイムロックの差分が設定される。Bob は Chan の料金とタイムロックの期待値に見合う HTLC を作る方法を教えられる。
アリスは、ボブのペイロードはアリスによって構築されるに示すように、このペイロードをTLV形式でシリアライズする(簡略化)。
https://scrapbox.io/files/63299999dd6859002087883c.png
図12. ボブのペイロードはアリスによって構築される
完成したホップペイロード
アリスはこれで、オニオンに包まれる3つのホップのペイロードを構築しました。ペイロードの簡略図は、すべてのホップのペイロードに示されている。
https://scrapbox.io/files/632999b16d3c8300219786fb.png
図 13. 全ホップのペイロード
鍵の生成
アリスは次に、タマネギの様々な層を暗号化するのに使われるいくつかの鍵を 生成しなければなりません。
これらの鍵で、アリスは高度なプライバシーと完全性を達成することができます。
アリスはオニオンの各層を暗号化し、意図した受信者だけがそれを読むことができるようにすることができます。
すべての仲介者はメッセージが変更されていないことを確認できます。
経路上の誰も、誰がこのオニオンを送ったのか、 どこに向かっているのかを知ることはできません。アリスは送信者である自分の身元や、支払いの受取人であるディナの身元を明かさない。
各ホップは前のホップと次のホップについてだけ知ることができる。
誰も経路がどのくらい長いか、経路のどこにいるか知ることはできません。
警告
刻んだタマネギのように、以下の技術的な詳細は、あなたの目に涙をもたらすかもしれません。混乱した場合は、遠慮なく次のセクションに飛んでください。もっと学びたい場合は、BOLT #4: Onion Routing, Packet Construction を読んで戻って来てください。 オニオンで使われるすべての鍵の基本は、アリスとボブが楕円曲線ディフィー・ヘルマン(ECDH)アルゴリズムを使って別々に生成できる共有秘密(shared secret)である。共有秘密(ss)から、彼らは独立してrho, mu, um, padという名前の4つの追加の鍵を生成することができます。
rho
ストリーム暗号(CSPRNGとして使用)からランダムなバイトのストリームを生成するために使用します。これらのバイトは、Sphinxのパケット処理中に、メッセージボディの暗号化/復号化、およびフィラーゼロバイトとして使用されます。
mu
ハッシュベースのメッセージ認証コード(HMAC)で、整合性/認証性の検証のために使われます。
um
エラー報告で使用されます。
pad
オニオンを一定の長さにパディングするためのフィラーバイトを生成するために使用される。
各種鍵の関係と生成方法は、Onion key generationに図解されている。
https://scrapbox.io/files/63299a3b7bc87b00200ffaa3.png
図 14. オニオンキーの生成
アリスのセッション鍵
自分の身元を明らかにしないように、アリスは自分のノードの公開鍵を オニオンを作るのに使いません。その代わりに、アリスはセッション秘密鍵と対応するセッション公開鍵と呼ばれる、 32バイト(256ビット)の一時的な鍵を作成します。これはこのオニオンだけの一時的な「アイデンティティ」と鍵の 役割を果たします。このセッション鍵から、アリスはこのオニオンで使われる他のすべての鍵を 作成します。
鍵生成の詳細
鍵の生成、ランダムバイトの生成、エフェメラルキー、そしてそれらがどのようにパケット構築に使われるかは、 BOLT #4 の3つのセクションで指定されています。 鍵の生成
ランダムバイトストリーム
パケット構築
簡略化のため、また技術的に難しくなりすぎないようにするため、これらの詳細については本書には記載していません。内部構造をご覧になりたい方は、先のリンクをご参照ください。
共有秘密の生成
ほとんど魔法のように思える重要な点は、アリスが他のノードの公開鍵を知っているだけで、他のノードと共有の秘密を作ることができる点です。これは、暗号技術に革命をもたらした1970年代のDiffie-Hellman鍵交換(DH)の発明が元になっています。Lightningオニオンルーティングは、Bitcoinのsecp256k1曲線上の楕円曲線Diffie-Hellman(ECDH)を使用しています。これはとてもクールなトリックなので、Elliptic Curve Diffie-Hellman Explainedでわかりやすく説明するようにしています。
楕円曲線Diffie-Hellmanの説明
楕円曲線を使って、アリスとボブはそれぞれ自分の秘密鍵に生成点Gを掛けて、公開鍵A、Bを生成します。
A = aG
B = bG
ここで、アリスとボブは楕円曲線Diffie-Hellman鍵交換を使って共有秘密ssを作ることができます。この値は、情報を交換することなく二人が独立して計算できる値です
共有秘密ssは、それぞれが自分の秘密鍵と相手の公開鍵を掛け合わせることで、以下のように計算されます。
ss = aB = bA
しかし、なぜこの2つの掛け算は同じ値ssになるのでしょうか?それが可能であることを証明する計算をお見せします。
ss
= aB
a(自分の秘密鍵)とB(ボブの公開鍵)の両方を知っているアリスが計算したものです。
= a(bG)
となり、B = bGであることがわかるので、次のように代入します。
= (ab)G
とすれば、連想性から、括弧を動かして
= (ba)G
xy = yx なので (曲線は abelian 群)
= b(aG)
となり、連想性から、括弧を動かすと
= bA
となり、aGをAに置き換えることができる。
この結果bAは、b(自分の秘密鍵)とA(アリスの公開鍵)を知っているボブが独自に計算することができる。
したがって、次のことを示した。
ss = aB (アリスはこれを計算することができる)
ss = bA (ボブはこれを計算できる)
このように、2人はそれぞれ独立してssを計算することができ、これを共有鍵として、共有秘密を伝えることなく2人の間で秘密を対称に暗号化することができます。
Sphinxのユニークな特徴は、Mix-netのパケット形式として、ルートの各ホップに個別のセッションキーを含めるのではなく、Mix-netパケットのサイズを劇的に増加させる、巧妙なブラインドスキームを使用して、各ホップのセッションキーを決定論的にランダム化するということです。
実際には、この小さなトリックによって、望ましいセキュリティ特性を維持しながら、オニオンパケットをできるだけコンパクトに保つことができる。
ホップiのセッションキーは、ノードの公開キーとホップi - 1の共有秘密を使って導出される。
session_key_i = session_key_{i-1} * SHA-256(node_pubkey_{i-1} || shared_secret_{i-1})
つまり、前のホップのセッションキーに、そのホップの公開キーと共有シークレットから導き出された値を乗算するのである。
楕円曲線乗算は秘密鍵を知らなくても公開鍵に対して実行できるので、各ホップは次のホップのセッション鍵を決定論的な方法で再ランダム化することが可能である。
オニオンパケットの作成者は、(パケットを各ホップごとに一意に暗号化したため)すべての共有秘密を知っており、したがって、すべての盲点要因を導き出すことができる。
この知識によって、パケット生成時に前もって使用されるすべてのセッションキーを導き出すことができる。
最初のホップは生成されたオリジナルのセッションキーを使用することに注意。 なぜなら、このキーは後続の各ホップによるセッションキーの隠蔽を開始するために使用されるからである。
オニオン層のラッピング
Onion を包むプロセスは、BOLT #4: Onion Routing, Packet Construction で詳しく説明されている。 このセクションでは、このプロセスを高水準でやや簡略化して説明し、特定の詳細を省略する。
固定長のタマネギ
ホップ」ノードのいずれも、経路の長さや経路上の位置を知らないという事実を述べました。なぜ、このようなことが可能なのでしょうか。
もし、暗号化された道順があったとしても、道順のリストのどこにいるかを見るだけで、始点や終点からどのくらい離れているかを知ることはできないだろうか?
オニオンルーティングでは、どのノードでも常に同じ長さのパス(道順リスト)を作るというトリックが使われている。これは、オニオンパケットの長さを各ステップで同じにすることで実現されている。
各ホップでは、オニオンペイロードの最初にホップペイロードが現れ、その後にさらに19個のホップペイロードがあるように見える。すべてのホップは、自分自身を20のホップのうちの最初のホップと見なす。
ヒント
オニオンのペイロードは 1,300 バイトである。各ホップのペイロードは65バイト以下である(65バイト以下の場合は65バイトにパディングされる)。したがって、オニオンの総ペイロードは 20 ホップのペイロードに収まる (1300 = 20 × 65) 。したがって、オニオンの最大経路は20ホップである。
各レイヤーが「剥がされる」ごとに、オニオンペイロードの最後にさらにフィラーデータ(基本的にジャンク)が追加される。そのため、次のホップは同じサイズのオニオンを取得し、再びオニオン内の「最初のホップ」となる。
オニオンのサイズは1,366バイトであり、The onion packetに示すような構造になっている。
1バイト
バージョン バイト
33バイト
圧縮された公開セッション鍵 (アリスのセッション鍵) ここから、アリスの身元を明かすことなくホップごとの共有秘密 (Shared secret generation) を生成することができる。
1,300バイト
各ホップに対する指示を含む実際のオニオンペイロード
32バイト
HMAC完全性チェックサム
https://scrapbox.io/files/63299c543847c0001d6cec4a.png
図15. オニオンパケット
Sphinxのユニークな特徴として、Mix-netのパケットフォーマットは、ルートの各ホップに個別のセッションキーを含めるのではなく、その代わりに巧妙なブラインドスキームを使って、各ホップのセッションキーを決定論的にランダム化することで、劇的にサイズを大きくしています。
実際には、この小さなトリックによって、望ましいセキュリティ特性を保ちつつ、オニオンパケットを可能な限りコンパクトにすることができる。
オニオンを包む(概要)
次に、オニオンを包むプロセスの概要を説明する。このリストは、実世界の例で各ステップを調べるときに、また戻ってくる。
各ホップについて、送信者(アリス)は同じ処理を繰り返します。
1. アリスはホップごとの共有秘密と、rho、mu、padのキーを生成します。
2. アリスは1,300バイトのフィラーを生成し、このフィラーで1,300バイトのオニオンペイロードフィールドを埋める。
3. アリスはホップペイロードのHMACを計算する(最終ホップにはゼロを使用)。
4. アリスはホップペイロードの長さ + HMAC + 長さそのものを格納するためのスペース を計算する。
5. アリスはオニオンペイロードを、ホップペイロードを収めるために必要な計算されたスペース分だけ右シフトする。右端の「詰め物」データは破棄され、ペイロードのために十分な左側のスペースが作られる。
6. アリスは、ペイロードフィールドの先頭に、length + hop payload + HMACを、fillerをシフトしてできたスペースに挿入する。
7. アリスはrhoキーを使って1300バイトのワンタイムパッドを生成する。
8. アリスはrhoから生成されたバイトとXORすることで、onionペイロード全体を難読化する。
9. アリスはmu鍵を使って、onionのペイロードのHMACを計算する。
10. アリスはセッションの公開鍵を追加する(ホップが共有秘密を計算できるように)。
11. アリスはバージョン番号を追加する。
12. アリスは、共有秘密と前のホップの公開鍵をハッシュすることによって 得られる値を使用して、セッション鍵を決定論的に再ブラインドする。
次に、アリスはこのプロセスを繰り返す。新しい鍵が計算され、オニオンペイロードがシフトされ (ジャンクをさらに落とす)、新しいホップのペイロードが先頭に追加され、 オニオンペイロード全体が次のホップのためにrhoバイトストリームで 暗号化される。
最後のホップでは、ステップ#3で平文命令に含まれるHMACが実際にはすべてゼロである。最終ホップは、この信号を使用して、それが本当に経路の最終ホップであることを判断する。あるいは、「次のホップ」を示すためにペイロードに含まれるshort_chan_idがすべてゼロであるという事実も同様に使用することができる。
各フェーズで、暗号化された(ペイロードを処理するノードの観点から)オニオンパケットのHMACと、暗号化の1層を取り除いたパケットのコンテンツのHMACを生成するために、mu鍵が使用されることに注意すること。この外側のHMACによって、パケットを処理するノードはオニオンパケットの完全性(変更されたバイトがない)を確認することができる。内部HMACはその後、前述した「シフトと暗号化」の逆ルーチンの間に明らかにされ、次のホップの外部HMACとして機能する。
Dinaのホップペイロードのラッピング
注意点として、オニオンは最終ノードまたは受信者であるDinaからのパスの終端から始めてラップされる。次に、送信者であるアリスに戻るまで、パスを逆向きに構築します。
アリスは、固定長のオニオンペイロードである1,300バイトの空のフィールドから始めます。次に、彼女はオニオンペイロードを、パッドキーから生成される擬似ランダムバイトストリーム「フィラー」で埋める。
これは、Filling the onion payload with a random byte streamに示されている。
注
ランダムバイトストリームの生成には、CSPRNG(cryptographic secure pseudorandom number generator)としてChaCha20アルゴリズムが使用される。このようなアルゴリズムは、最初のシードから、一見ランダムに見えるバイトの、決定論的で、長く、非繰り返しのストリームを生成する。詳細はBOLT #4: Onion Routing, Pseudo Random Byte Streamに規定されている。