lnurl-auth (LUD-04)
使用 LNURL-auth(闪电网络“通过闪电网络登录”)在客户端侧完成服务认证。仅限认证:服务发送 k1 挑战,你用 secp256k1 私钥对原始 32 字节 k1 进行签名,并通过 GET 请求将 sig + key 返回给回调 URL。不涉及发票、支付或闪电节点。
使用场景
- 网站显示“通过闪电网络登录”/LNURL-auth。
- 你得到了一个
lnurl1...字符串(来自二维码、链接或粘贴文本)。 - 你无需花钱或运行闪电节点。
命令
通过 Node.js(已安装)运行。脚本位于:
<skill_dir>/lnurl_auth.js
node <skill_dir>/lnurl_auth.js --lnurl <lnurl1...> [选项]
# 或者将 lnurl 作为位置参数传递:
node <skill_dir>/lnurl_auth.js <lnurl1...>
选项
| 选项 | 描述 |
|---|---|
--lnurl <字符串> | lnurl1... 字符串(或作为位置参数传递) |
--key <十六进制> | 使用此十六进制私钥作为主密钥 |
--keyfile <路径> | 从文件中读取主密钥(十六进制) |
--keyout <路径> | 存储生成的主密钥的位置(默认 ~/.config/lnurl-auth/master.key) |
--generate | 强制生成新的主密钥,覆盖任何已有的密钥文件 |
--single-key | 对所有服务使用一个全局链接密钥(不按域名派生) |
--no-t | 兼容性选项;回调不添加 t 参数 |
--action <动作> | 断言/覆盖动作: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=<十六进制 DER 签名>&key=<十六进制压缩公钥>,同时保留现有查询参数。 - 服务端验证签名并返回
{"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位十六进制私钥>
强制重置身份
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 (无支付,无需闪电节点)。