SphinxプロトコルにHMACを追加する理由はリプレイ攻撃対策

ライトニングネットワーク上の送金はプライバシー向上のためにオニオンルーティングが使われている。そのプロトコルとしてSphinxプロトコルをベースとしているが、そこにHMACがなぜ追加されているのか、以下のLNメーリスに回答があったので、その備忘録。

[Lightning-dev] Reason for having HMACs in Sphinx (linuxfoundation.org)

オニオンルーティングのペイロードのラップ、アウンラップについては以下のサイトが参考になるので、それをもとに以下、詳細を割愛しながら説明する。

lnbook/10_onion_routing.asciidoc at develop · lnbook/lnbook (github.com)

オニオンペイロードのラップ・アンラップ

オニオンペイロードは送信者によって構成される。このペイロードは1300バイトの固定長である。例えば、A→B→C→Dという経路で送信する場合、AはまずDへの情報をセットし、残りのスペースを1300バイトになるまでフィラーで埋め、Dとの共有鍵から生成したrho鍵でXORしてペイロードを暗号化(難読化)する(1)。次にCへの情報をセットし、暗号化したデータ(1)を追加する。この時、1300バイトを超過したデータは切り捨て、Cとの共有鍵から生成したrho鍵で全体を暗号化する(2)。次にBへの情報をセットし、暗号化したデータ(2)を追加する。この時も1300バイトを超過したデータは切り捨てて全体を暗号化する(3)。こうして入れ子になったデータをオニオンペイロードと呼ぶ。

Aはこのオニオンペイロードの先頭にBとのセッションキー(※1)をセットしてBへ送信する。Bはオニオンペイロードに1300バイトのゼロ埋めされたフィラーを追加して、共有鍵を使い2600バイトのペイロードを復号して(先頭1300バイトが復号され、残りの1300バイトは難読化される)、自身のペイロードを切り取る。残ったペイロードを左へシフトして、1300バイトを超過するデータを切り捨てる。Bはこのオニオンペイロードの先頭にCのためのセッションキーをセットしてCへ送信する。Cも同様にペイメントの先頭に1300バイトのフィラーを追加してから共有鍵を使いペイロードを復号して自身のペイロードを切り取る。残ったペイロードを左へシフトして、1300バイトを超過するデータを切り捨てる。Cはこのオニオンペイロードの先頭にDのためのセッションキーをセットしてDへ送信する。Dも同様な処理を行い、自身のペイロードからこの送金は自身のものだと分かる。

※1 セッションキーを使うことで、送信者の公開鍵を公開することなく中継者とECDHによる鍵共有が可能となる。各ホップごとのセッションキーは以下のように生成できる。送信者はオニオンペイロードを作る際、すべての鍵を事前に計算できる。また、中継者は次の中継者のための鍵生成を行う。

session_key_i = session_key_{i-1} * SHA-256(node_pubkey_{i-1} || shared_secret_{i-1})

リプレイ攻撃

送金の中継者が悪意ある行動をとるとする。まずn=1をセットして(n+1)番目のペイロードをビット反転して送信する。次のノードが最終受信者だとすればエラーは返ってこない。なぜなら、ビット反転した箇所はフィラーで埋めされた箇所だから。もしエラーが返ってきたら、nを1増加させて(n+1)番目のペイロードをビット反転して送信する。これをエラーが返ってこないところまで繰り返すことで、自分が最終受信者から何番目に位置するのかを知ることができる。

Bが悪意ある行動をとるとする。Aから受け取ったオニオンペイロードを復号してCへ送信するペイロードを作る。この時、2番目のペイロード、すなわちDへのペイロードをビット反転しておく。Cは自身のペイロードは復元できるので、そのままDへのペイロードを作り送信する。Dはそのペイロードを復元するがビット反転されているので不正なデータだと分かり、Cへエラーを返す。CはそれをBへ返す。これでBはCが最終受信者ではないと分かる。次に、nを1増加させて3番目のペイロード、すなわちフィラーで埋められている箇所をビット反転する。このペイロードはCもDも読み取らない箇所なのでDまで問題なく送信される。よってBは最終受信者から2番目に位置すると知ることができる。

リプレイ攻撃対策1: HMAC

オニオンペイロードの改ざんを防ぐために、各ペイロードを暗号化したあとにHMACを付与する。上記の例だと、Bから受け取ったペイロードが改ざんされていることをCが検知できる。

リプレイ攻撃対策2: セッションキー

SphinxプロトコルにはHMACの規定はないが、リプレイ攻撃への対策が備わっている。オニオンペイロードを受け取ったら、その先頭に付加されているセッションキーをログとして保存しておく。もし同じセッションキーが再送されてもログを探索することでリプレイ攻撃を検知できる。上記の例だと、Bから再送されたペイロードをCが受け取った際に検知できる。

リプレイ攻撃対策3: ペイメントハッシュ

オニオンペイロードを送信する際、チャネルIDや金額、ペイメントハッシュなども一緒に送信される(具体的にはupdate_add_htlcを参照)。ライトニングネットワークでは1つのHTLCに含まれるペイメントハッシュが安全に使用できるのは1度限り。すでに使用されたペイメントハッシュを使った送金の場合、相手がそれを中継せずに資金を中抜きできてしまう。しかし、攻撃者はそのハッシュ値を適当な値に改ざんして送信することができる。そこで、HMACするデータにペイメントハッシュを含めることで(ペイメントハッシュは平文としてHMACする)、送信者にペイメントハッシュをコミットさせることができる。よって攻撃者がリプレイ攻撃をする場合、同じペイメントハッシュが含まれたペイロードを使う必要があり、資金を失う可能性がある。よってリプレイ攻撃をするインセンティブを減らすことができる。

特記事項

当初のオニオンペイロードは65バイトの固定長だったが、TLVの採用によって可変長となった。そのため、上記で紹介したn番目のペイロードをビット反転して経路の位置を特定するような手法はできないような気がする。

Remaining : 0 characters / 0 images
100

Sign up / Continue after login

Related stories

Writer

ちょビットコイナー nostr id: npub1l83ycz54gng3nd8suvww43fardjsca37x7z5rcwlmeqzudg027fqe9hwaa

Share

Popular stories

LNノードの運用益はどれぐらい?パート1

1819

【Muun】ちょっと変わったライトニング搭載ノンカストディアルウォレット

1703

LNノードの運用益はどれぐらい?パート3

1092