高級
Sphinx 洋蔥封包
深入了解閃電網路使用的 Sphinx 洋蔥路由封包格式,如何實現支付路徑的隱私保護。
12 分鐘
什麼是 Sphinx?
Sphinx 是一種密碼學封包格式,用於實現洋蔥路由的隱私保護。 在閃電網路中,發送者使用 Sphinx 封裝支付資訊,每個中繼節點只能看到 下一跳的資訊,無法得知完整路徑或發送者/接收者的身份。
洋蔥類比: Sphinx 封包像洋蔥一樣有多層加密。每個節點剝開一層, 看到自己的指令,然後將剩餘部分傳遞給下一跳。
封包結構
Sphinx Onion Packet Structure (1366 bytes) ┌──────────────────────────────────────────────────────────┐ │ Version (1 byte) │ ├──────────────────────────────────────────────────────────┤ │ Ephemeral Public Key (33 bytes) │ ├──────────────────────────────────────────────────────────┤ │ Routing Info (1300 bytes) │ │ ┌────────────────────────────────────────────────────┐ │ │ │ Hop 1 payload (encrypted) │ │ │ ├────────────────────────────────────────────────────┤ │ │ │ Hop 2 payload (double encrypted) │ │ │ ├────────────────────────────────────────────────────┤ │ │ │ Hop 3 payload (triple encrypted) │ │ │ ├────────────────────────────────────────────────────┤ │ │ │ ... │ │ │ ├────────────────────────────────────────────────────┤ │ │ │ Padding (random data) │ │ │ └────────────────────────────────────────────────────┘ │ ├──────────────────────────────────────────────────────────┤ │ HMAC (32 bytes) - verifies packet integrity │ └──────────────────────────────────────────────────────────┘ Why Fixed Size Matters: • Every node sees same size packet • Cannot infer remaining hops from size • Supports up to 20 hops
加密過程
Sender Builds Onion Path: Alice -> Bob -> Carol -> Dave 1. Generate Ephemeral Key Pair ephemeral_privkey = random() ephemeral_pubkey = ephemeral_privkey * G 2. Compute Shared Secret for Each Hop (using ECDH) shared_secret_bob = SHA256( ephemeral_privkey * Bob_pubkey ) shared_secret_carol = SHA256( ephemeral_privkey' * Carol_pubkey ) (ephemeral_privkey' is derived blinded key) shared_secret_dave = SHA256( ephemeral_privkey'' * Dave_pubkey ) 3. Encrypt in Reverse Order (start from last hop) • First encrypt Dave's payload • Then encrypt entire packet with Carol's key • Then encrypt entire packet with Bob's key • Result: outermost layer is Bob's encryption
解密過程
Relay Node Processes Onion Bob receives onion: 1. Compute shared secret shared_secret = SHA256(Bob_privkey * ephemeral_pubkey) 2. Verify HMAC expected_hmac = HMAC(shared_secret, routing_info) if hmac != expected_hmac: reject 3. Decrypt routing info decrypted = ChaCha20(routing_info, shared_secret) 4. Read own payload • short_channel_id: next hop channel • amt_to_forward: forward amount • outgoing_cltv_value: CLTV 5. Build new onion for next hop • Blind ephemeral pubkey • Remove own payload • Add padding • Update HMAC Ephemeral Pubkey Blinding: blinding_factor = SHA256(ephemeral_pubkey || shared_secret) new_ephemeral = ephemeral_pubkey * blinding_factor Each hop changes ephemeral pubkey, but next hop can still compute correct shared secret
Payload 格式
TLV Payload Format (Modern) ┌──────────────────────────────────────────────────────────┐ │ length (BigSize): payload length │ ├──────────────────────────────────────────────────────────┤ │ TLV Records: │ │ type=2: amt_to_forward (tu64) │ │ type=4: outgoing_cltv_value (tu32) │ │ type=6: short_channel_id (8 bytes) │ │ type=8: payment_data (for final hop) │ │ -> payment_secret + total_msat │ │ [other optional TLVs...] │ ├──────────────────────────────────────────────────────────┤ │ hmac (32 bytes): HMAC for next packet │ └──────────────────────────────────────────────────────────┘ Relay Node vs Final Node Payload: Relay Node: • short_channel_id: required • amt_to_forward: required • outgoing_cltv_value: required Final Node: • amt_to_forward: payment amount • outgoing_cltv_value: final CLTV • payment_secret: prevents probing • total_msat: MPP total • NO short_channel_id
隱私保護
發送者匿名
中繼節點不知道誰是發送者。第一跳只知道它是第一跳, 但不知道是發送者還是另一個中繼。
接收者匿名
中繼節點不知道誰是接收者。每跳只知道下一跳, 不知道剩餘多少跳。
路徑長度隱藏
固定大小的封包使得無法從大小推斷路徑長度。 填充確保短路徑看起來和長路徑一樣。
不可關聯性
臨時公鑰每跳變化,使得無法將入站和出站封包關聯。 (但 payment_hash 仍可關聯)
錯誤返回
Error Message Onion Encryption When error occurs: Failing node builds error message: • failure_code: error type • data: additional info Hop-by-hop encrypted return: 1. Failing node encrypts error with shared secret 2. Each relay node re-encrypts with its shared secret 3. Sender receives multi-layer encrypted error Sender decryption: 1. Try decrypting with each hop's key 2. Successfully decrypted layer corresponds to failing node 3. Read error code and info Error Message Structure: ┌──────────────────────────────────────────────────────────┐ │ hmac (32 bytes) │ │ failure_len (2 bytes) │ │ failuremsg (failure_len bytes) │ │ pad_len (2 bytes) │ │ pad (pad_len bytes) │ └──────────────────────────────────────────────────────────┘
與 Route Blinding 結合
Route Blinding Enhancement Traditional Sphinx: • Sender knows complete path • Sender knows receiver node • Invoice exposes receiver location Sphinx + Route Blinding: Receiver pre-builds blinded path: • Entry node pubkey (visible) • Blinded subsequent nodes • Encrypted payloads Sender: • Builds Sphinx to entry node • Appends blinded path to onion end • Does not know path after entry Result: Sender does not know receiver's real location
限制: 雖然 Sphinx 保護路徑隱私,但 payment_hash 在所有跳間相同, 使得這些 HTLC 可被關聯。PTLCs 將解決此問題。
相關資源
下一步: 了解 網路拓撲 如何影響支付路由。
已複製連結