lnurl-auth(LUD-04)
使用 LNURL-auth(閃電網路「使用閃電網路登入」)在完全客戶端進行服務驗證。此為純驗證:伺服器發送一個 k1 挑戰,你使用 secp256k1 私鑰對原始 32 位元組的 k1 進行簽章,並透過 GET 請求將 sig + key 回傳至回呼 URL。不涉發票、支付或閃電網路節點。
使用時機
- 網站顯示「使用閃電網路登入」/ LNURL-auth。
- 你取得一個
lnurl1...字串(來自 QR 碼、連結或貼上的文字)。 - 你不可花費金錢或執行閃電網路節點。
指令
使用 Node(已安裝)執行。腳本位於:
<skill_dir>/lnurl_auth.js
node <skill_dir>/lnurl_auth.js --lnurl <lnurl1...> [選項]
# 或直接將 lnurl 作為位置參數傳入:
node <skill_dir>/lnurl_auth.js <lnurl1...>
選項
| 選項 | 說明 |
|---|---|
--lnurl <str> | lnurl1... 字串(或作為位置參數傳入) |
--key <hex> | 使用此十六進位私鑰作為主密鑰 |
--keyfile <path> | 從檔案讀取主密鑰(十六進位) |
--keyout <path> | 產生的主密鑰儲存位置(預設 ~/.config/lnurl-auth/master.key) |
--generate | 強制產生新的主密鑰,覆寫任何現有密鑰檔案 |
--single-key | 對所有服務使用單一全域連結密鑰(不進行逐網域推導) |
--no-t | 相容選項;回呼時不附加 t 參數 |
--action <a> | 斷言/覆寫動作:register、login、link 或 auth |
--callback <url> | 覆寫簽章提交的目標 URL |
--dry-run | 解碼、擷取 k1、簽章 — 但不提交回呼 |
--json | 輸出機器可讀的 JSON |
-v、--verbose | 詳細輸出 |
-q、--quiet | 隱藏進度訊息 |
-h、--help | 顯示說明 |
密鑰管理(預設,隱私保護)
- 首次使用時會產生一個 32 位元組的主密鑰,並儲存至
~/.config/lnurl-auth/master.key(權限0600)。 - 對每個服務,連結密鑰是確定性推導的:
linkingPriv = HMAC-SHA256(master, serviceDomain)。 - 相同服務 → 相同密鑰(返回使用者)。不同服務 → 不同密鑰(隱私 — 遵循 LUD-05/LUD-13 精神)。
- 使用
--single-key可對所有服務使用單一全域連結密鑰。
協定流程(LUD-04)
lnurl1...是bech32("lnurl", utf8(serviceURL))。解碼 → 取得包含k1(32 位元組十六進位挑戰)以及選擇性action的 URL。- 使用 ECDSA(secp256k1,
prehash: false)以連結私鑰簽署原始 32 位元組k1,然後進行 DER 編碼。 - 對服務 URL 發送 GET 請求,附加
&sig=<hex DER sig>&key=<hex compressed pubkey>,同時保留原有的查詢參數。 - 伺服器驗證簽章並回應
{"status":"OK"}或{"status":"ERROR","reason":"..."}。
參考資料:https://github.com/lnurl/luds/blob/luds/04.md
輸出
- 進度訊息輸出至 stderr。
- 伺服器回應(JSON)輸出至 stdout。
{"status":"OK"}→ 退出碼0。{"status":"ERROR",...}→ 退出碼3。- 非 JSON 或非 200 回應 → 退出碼
4。
範例
基本登入
node <skill_dir>/lnurl_auth.js --lnurl "lnurl1dp68gurn8ghj7..."
先乾執行(查看但不提交)
node <skill_dir>/lnurl_auth.js "lnurl1..." --dry-run --json
使用指定密鑰
node <skill_dir>/lnurl_auth.js "lnurl1..." --key <64-char-hex-private-key>
強制建立新身份
node <skill_dir>/lnurl_auth.js "lnurl1..." --generate
相依性
- Node.js v20.19+(建議 v22)。
- 兩個極簡純 JS npm 套件,內建於
node_modules/目錄:@noble/secp256k1(簽章/驗證,體積小,無依賴)bech32(lnurl 解碼/編碼)
- 無需本機編譯;網路呼叫僅限於選用的挑戰 GET 與最終回呼 GET。
- 無費用,無閃電網路節點。
安裝/更新內建依賴
cd <skill_dir>
npm install
自我測試(無需外部服務,無成本)
本機模擬 LUD-04 伺服器驗證完整的簽署 → 提交 → 驗證流程:
cd <skill_dir>
npm test
涵蓋:正常路徑、重播拒絕、乾執行安全、竄改 k1 拒絕、逐網域密鑰穩定性、--generate 覆寫以及奇數長度十六進位驗證。
真實服務驗證
已對兩個公開服務進行驗證:
| 服務 | 回應 |
|---|---|
| bitsimp.com | {"status":"OK"} |
| lightninglogin.live | {"status":"OK"} |
限制
- 此工具僅執行密碼學握手;帳號建立/登入需依賴遠端服務識別該密鑰。
- 預設連結密鑰是從本機主密鑰逐網域推導的 — 並非使用者手機錢包會產生的同一身份。但對代理人驗證而言已足夠。
- 需要對外網路連線以進行選用的挑戰 GET 與最終回呼 GET(無支付,無閃電網路節點)。