lnurl-auth (LUD-04)
LNURL-auth(Lightning「Sign in with Lightning」)を使って、サーバーに認証します。
これは認証のみです。サーバーから送られるk1チャレンジに対し、あなたはsecp256k1秘密鍵で生の32バイトk1を署名し、コールバックにGETでsigとkeyを返します。インボイスも支払いもLightningノードも必要ありません。
使用するタイミング
- サイトに「Sign in with Lightning」/ LNURL-authが表示されている。
lnurl1...形式の文字列(QRコード、リンク、または貼り付けテキストから)が与えられている。- お金を使ったり、Lightningノードを実行したりしてはいけない。
コマンド
Node(インストール済み)で実行します。スクリプトは次の場所にあります:
<skill_dir>/lnurl_auth.js
node <skill_dir>/lnurl_auth.js --lnurl <lnurl1...> [オプション]
# またはlnurlを位置引数として渡す:
node <skill_dir>/lnurl_auth.js <lnurl1...>
オプション
| オプション | 説明 |
|---|---|
--lnurl <文字列> | lnurl1...文字列(位置引数としても可) |
--key <16進> | この16進秘密鍵をマスターシークレットとして使用 |
--keyfile <パス> | マスターシークレット(16進)をファイルから読み込む |
--keyout <パス> | 生成したマスターシークレットを保存する場所(デフォルト ~/.config/lnurl-auth/master.key) |
--generate | 新しいマスターシークレットを強制生成し、既存のキーファイルを上書き |
--single-key | すべてのサービスで1つのグローバルリンキングキーを使用(ドメインごとの導出なし) |
--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の精神に基づく)。
- 全サービスで1つのグローバルリンキングキーを使用するには
--single-keyを使用します。
プロトコルフロー(LUD-04)
lnurl1...はbech32("lnurl", utf8(serviceURL))です。デコード→k1(32バイトの16進チャレンジ)とオプションでactionを含むURLを取得。- 生の32バイト
k1をリンキング秘密鍵でECDSA(secp256k1、prehash: false)を使って署名し、その後署名をDERエンコード。 - 既存のクエリパラメータを保持しながら、
&sig=<16進DER署名>&key=<16進圧縮公開鍵>を付加してサービスURLにGETリクエスト。 - サーバーが署名を検証し、
{"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文字の16進秘密鍵>
新しいアイデンティティを強制
node <skill_dir>/lnurl_auth.js "lnurl1..." --generate
依存関係
- Node.js v20.19以上(v22推奨)。
- 2つの小さな純粋JavaScript npmパッケージ、
node_modules/内にベンダリング:@noble/secp256k1(署名/検証、軽量、依存関係ゼロ)bech32(lnurlのデコード/エンコード)
- ネイティブビルドは不要。ネットワーク呼び出しはオプションのチャレンジGETと最終コールバックGETに限定。
- コストもLightningノードも不要。
ベンダリング依存関係のインストール/リフレッシュ
cd <skill_dir>
npm install
セルフテスト(外部サービス不要、コスト不要)
ローカルのモックLUD-04サーバーが、完全な署名→送信→検証のラウンドトリップを検証します:
cd <skill_dir>
npm test
対象:正常系、リプレイ拒否、ドライラン安全性、改ざんされたk1拒否、ドメインごとのキー安定性、--generate上書き、奇数長16進検証。
実環境での検証
2つのパブリックサービスで検証済み:
| サービス | 応答 |
|---|---|
| bitsimp.com | {"status":"OK"} |
| lightninglogin.live | {"status":"OK"} |
制限事項
- これは暗号化ハンドシェイクを実行します。アカウント作成/ログインはリモートサービスがキーを認識するかどうかに依存します。
- デフォルトのリンキングキーはローカルマスターシークレットからドメインごとに導出されます — ユーザーの電話ウォレットが生成するものと同じIDではありません。エージェント認証には十分です。
- オプションのチャレンジGETと最終コールバックGETのためのネットワーク出力が必要です(支払いもLightningノードも不要)。