隱身地址詳解:一次性地址如何運作

· 6 分鐘閱讀

隱身地址讓你只需公開一個地址,而付給你的每一筆款項仍然會落在鏈上的一個新位置。本指南以 Blocknet 為例,說明它是如何做到的、檢視金鑰與花費金鑰各自的作用,以及錢包如何找到屬於自己的款項。

什麼是隱身地址?

簡短回答

隱身地址是一個從不出現在區塊鏈上的公開地址。它包含兩把公鑰:花費金鑰與檢視金鑰。每一筆付款時,發送方的錢包都會把它們與一個新的隨機數結合,產生一個一次性地址,只有接收方能辨識它並從中花費。

在公開帳本上,一般地址會出現在它收到的每一筆付款中。標準的比特幣地址就是這樣:任何知道它的人都可以查到每一筆付款並算出總額。這就是許多比特幣錢包會為每筆付款提供新地址的原因。

隱身地址替你完成了這件事。你只需分享一個地址,可以放在網站上、寫進個人檔案,或者用 @name 的形式,每個發送方都會從它推導出不同的一次性地址。付給你的十筆款項會變成十個輸出,它們彼此之間、與你分享的地址之間都沒有任何可見的關聯。整個過程不需要來回溝通:發送方僅憑你的公開地址與一個隨機數,就能獨自算出一次性地址。

隱身地址從何而來?

Monero、Blocknet 與其他幣所使用的一次性地址設計,可以追溯到 Nicolas van Saberhagen 撰寫、日期為 2013 年 10 月 17 日的 CryptoNote v2.0 白皮書。白皮書把這個想法稱為「unlinkable payments」(無法關聯的支付),並描述發送方如何根據接收方的地址產生「one-time public key」(一次性公鑰)。Monero 的文件將隱身地址描述為讓發送方「代表接收方為每筆交易建立隨機的一次性地址」(create random one-time addresses for every transaction on behalf of the recipient)。

這個想法已經擴展到隱私幣之外。比特幣的 BIP 352「Silent Payments」(靜默支付)讓一個固定的比特幣地址可以接收在鏈上無法關聯的付款;以太坊的 ERC-5564 建立於 2022 年,為以太坊帳戶制定了隱身地址標準。兩者在各自的鏈上都是選用功能。在 Blocknet 中,每一筆付款都使用一次性地址。

隱身地址如何運作?

簡短回答

發送方選取一個隨機數 r,在交易中公布 R = r·G,並把 r 與接收方的公開檢視金鑰結合成一個共享密鑰。把這個共享密鑰加到公開花費金鑰上,就得到一次性金鑰。接收方用 R 與自己的私有檢視金鑰重建同一個共享密鑰,所以只有接收方能找到這筆付款。

你的錢包持有兩組金鑰對。每把私鑰都是一個祕密數字(s 用於花費,v 用於檢視),每把公鑰是這個數字乘以曲線上一個固定的點 G。你的地址就是這兩把公鑰 S 與 V。整個過程如下:

Receiver publishes:   S = s·G   and   V = v·G
Sender picks r:       R = r·G                 (stored in the transaction)
One-time key:         P = H(r·V)·G + S
Receiver checks:      H(v·R)·G + S == P       (true because r·V = v·R)
Key to spend it:      x = H(v·R) + s          (so P = x·G)

其中的關鍵是 Diffie-Hellman 金鑰交換。發送方計算 r·V,接收方計算 v·R,兩者得到的是同一個點,因為它們都等於 r·v·G。其他人既不知道 r 也不知道 v,所以無法算出這個點。對這個點做雜湊(H)就得到共享密鑰,而一次性金鑰 P 就是把這個共享密鑰轉換成點後,再加上你的公開花費金鑰。

掃描時,你用 R 與你的私有檢視金鑰重新算出共享密鑰,並檢查它是否能得到 P。如果能,這個輸出就是你的。要花費它,錢包會把同一個共享密鑰加到你的私有花費金鑰上,得到這一個輸出專用的私鑰 x。

Blocknet 在 Curve25519 之上的 Ristretto 群上採用這個設計,雜湊使用 SHA-256,並加上 Blocknet 專用的網域標籤。它還會把每個輸出在交易中的位置混入雜湊,因此即使一筆交易中有兩個輸出付給同一個人,它們得到的金鑰也毫無關聯。同一個共享密鑰還會推導出隱藏輸出金額的盲化因子與加密備註的金鑰,接收方正是藉此讀取金額與備註的。

檢視金鑰與花費金鑰分別有什麼作用?

把金鑰分開,你就有了兩個層級的存取權限:

這種分離讓僅檢視錢包成為可能。在 Blocknet 命令列錢包中,viewkeys 會用你的檢視金鑰建立一個獨立的錢包檔案。錢包的說明文字把它描述為一個「can monitor but cannot spend」(可以查看但不能花費)的檔案,適用於「you want watch-only access on another machine」(想在另一台機器上取得僅檢視權限)的情況。執行這個指令時,錢包會說明它要建立什麼:

# View Keys
  This will create a view-only wallet that can monitor incoming
  funds but CANNOT spend. Anyone with this file can see your
  balance and transaction history.

只把僅檢視錢包交給你願意向其展示交易紀錄的人,例如你的會計師,或者把它放在你自己的第二台電腦上。無論哪種方式,它都能看到資金入帳,而你的花費金鑰始終留在你信任的那台機器上。

錢包如何找到自己的款項?

由於一次性金鑰看起來與你的地址毫無關聯,鏈上沒有任何標記表明哪些輸出屬於你。你的錢包會自己檢查。對於每個新區塊中的每筆交易,它取出 R,用你的私有檢視金鑰計算共享密鑰,再用上面的公式檢驗每個輸出。這就是錢包在同步時所做的事情。

Blocknet 的掃描器讓這個過程保持快速。最耗時的一步,也就是用你的檢視金鑰乘以 R,每筆交易只執行一次,然後用結果檢查這筆交易中的每個輸出。當某個輸出相符時,錢包會解密金額,並先與該輸出的 Pedersen 承諾核對,再計入你的餘額。

掃描也讓復原變得簡單。Blocknet 的兩組金鑰對都來自你的 12 個單字的復原助記詞,因此在新電腦上復原助記詞就能重建金鑰,錢包會重新掃描區塊鏈,找到屬於你的每一個輸出。Blocknet 錢包指南介紹了如何備份與復原助記詞。

Blocknet 中的隱身地址

在 Blocknet 中,隱身地址就是你的地址。它是你的公開花費金鑰、公開檢視金鑰與 4 位元組檢查碼的 base58 編碼,長度為 92 或 93 個字元。付給你的每一筆款項都使用它,因為交易格式沒有透明模式。區塊獎勵同樣發送到一次性金鑰,所以獨立挖礦者的 coinbase 輸出也是透過同樣的掃描找到的。

隱身地址與 Blocknet 的其他隱私保護搭配運作:16 成員的環隱藏一筆花費來自哪個輸出,承諾隱藏金額,Dandelion++ 隱藏交易進入網路的位置。Blocknet 隱私指南逐層介紹了這些保護。

隱身地址也能搭配名稱使用。像 @yourname 這樣的 Blocknet ID 短名稱會公開對應到你的地址,方便發送方在 blocknet.id 上查詢。而付款本身仍然發送到全新的一次性金鑰,所以你的名稱不會透露你收到了什麼。

因此短名稱很適合用作挖礦的收款地址。啟動 seine,在提示處輸入你的地址或 @yourname,並接受預設礦池 bntpool.com。挖礦指南介紹了其餘步驟,而你挖到的 BNT 會由錢包透過上面介紹的同一種檢視金鑰掃描找到。

常見問題

隱身地址和一次性地址是同一回事嗎?

它們是同一套機制的兩個部分。隱身地址是你公開的地址,由公開花費金鑰與公開檢視金鑰組成。一次性地址是發送方為某一筆付款從它推導出的全新金鑰。鏈上只會出現一次性地址,你公開的地址從不出現。

別人知道我的隱身地址,能看到我的餘額嗎?

不能。知道你公開的地址並不能讓任何人找到你收到的款項,因為每一筆都落在一個看起來與它毫無關聯的一次性金鑰上。要找到這些款項需要你的私有檢視金鑰,所以只有你的錢包能列出你收到了什麼。在 Blocknet 中金額同樣是隱藏的,所以連輸出本身也不顯示數值。

別人拿到我的私有檢視金鑰能做什麼?

持有私有檢視金鑰的人可以找到付給你的款項,並讀取它們的金額與備註。它無法花費任何資金,因為花費需要私有花費金鑰。在 Blocknet 中,viewkeys 指令可以把你的檢視金鑰做成一個僅檢視錢包,方便在第二台電腦上查看資金。請只把它交給你信任的人。

在 Blocknet 中需要手動開啟隱身地址嗎?

不需要。每一筆 Blocknet 付款都會自動發送到一次性隱身地址,因為交易格式沒有透明模式。你發送時,錢包會產生一次性金鑰;錢包同步時,會用你的檢視金鑰找到收到的款項。無論你付款給地址還是 @name,都不需要任何設定。