lnurl-auth (LUD-04)
Autentícate en un servicio usando LNURL-auth (Lightning "Inicia sesión con Lightning")
completamente del lado del cliente. Esto es solo autenticación: el servidor envía un desafío k1,
tú firmas el k1 de 32 bytes en bruto con una clave privada secp256k1 y devuelves sig + key
a través de un GET al callback. Sin factura, sin pago, sin nodo Lightning.
Cuándo usarlo
- Un sitio muestra "Inicia sesión con Lightning" / LNURL-auth.
- Te dan una cadena
lnurl1...(desde un código QR, un enlace o texto pegado). - No debes gastar dinero ni ejecutar un nodo Lightning.
Comando
Ejecuta con Node (ya instalado). El script se encuentra en:
<skill_dir>/lnurl_auth.js
node <skill_dir>/lnurl_auth.js --lnurl <lnurl1...> [opciones]
# o pasa el lnurl posicionalmente:
node <skill_dir>/lnurl_auth.js <lnurl1...>
Opciones
| Opción | Descripción |
|---|---|
--lnurl <str> | La cadena lnurl1... (o pásala posicionalmente) |
--key <hex> | Usa esta clave privada hexadecimal como secreto maestro |
--keyfile <ruta> | Lee el secreto maestro (hex) desde un archivo |
--keyout <ruta> | Dónde persistir un secreto maestro generado (por defecto ~/.config/lnurl-auth/master.key) |
--generate | Forzar la generación de un nuevo secreto maestro, sobrescribiendo cualquier keyfile existente |
--single-key | Usa una clave de enlace global para todos los servicios (sin derivación por dominio) |
--no-t | Opción de compatibilidad; el callback no añade un parámetro t |
--action <a> | Afirmar/sobrescribir acción: register, login, link o auth |
--callback <url> | Sobrescribe la URL a la que se envía la firma |
--dry-run | Decodifica, obtiene k1, firma — pero no envía el callback |
--json | Emite JSON legible por máquina |
-v, --verbose | Registro detallado |
-q, --quiet | Suprime registros de progreso |
-h, --help | Muestra ayuda |
Gestión de claves (por defecto, preserva la privacidad)
- En el primer uso se genera un secreto maestro de 32 bytes y se guarda en
~/.config/lnurl-auth/master.key(modo0600). - Para cada servicio se deriva una clave de enlace de forma determinista:
linkingPriv = HMAC-SHA256(maestro, dominioDelServicio). - Mismo servicio → misma clave (usuario recurrente). Servicios diferentes → claves diferentes (privacidad — en el espíritu de LUD-05/LUD-13).
- Usa
--single-keypara una clave de enlace global en todos los servicios.
Flujo del protocolo (LUD-04)
lnurl1...esbech32("lnurl", utf8(urlDelServicio)). Decodifica -> URL que contienek1(desafío hex de 32 bytes) y opcionalmenteaction.- Firma el
k1de 32 bytes en bruto con la clave privada de enlace usando ECDSA (secp256k1,prehash: false), luego codifica en DER la firma. - Haz un GET a la URL del servicio con
&sig=<firma DER hex>&key=<clave pública comprimida hex>añadido, preservando los parámetros de consulta existentes. - El servidor verifica la firma y responde
{"status":"OK"}o{"status":"ERROR","reason":"..."}.
Referencia: https://github.com/lnurl/luds/blob/luds/04.md
Salida
- Los mensajes de progreso van a stderr.
- La respuesta del servidor (JSON) va a stdout.
{"status":"OK"}→ código de salida0.{"status":"ERROR",...}→ código de salida3.- Respuesta no JSON o no 200 → código de salida
4.
Ejemplos
Inicio de sesión básico
node <skill_dir>/lnurl_auth.js --lnurl "lnurl1dp68gurn8ghj7..."
Dry-run primero (inspeccionar sin enviar)
node <skill_dir>/lnurl_auth.js "lnurl1..." --dry-run --json
Usar una clave específica
node <skill_dir>/lnurl_auth.js "lnurl1..." --key <clave-privada-hex-64-caracteres>
Forzar nueva identidad
node <skill_dir>/lnurl_auth.js "lnurl1..." --generate
Dependencias
- Node.js v20.19+ (se recomienda v22).
- Dos paquetes npm pequeños de JS puro, incluidos dentro de
node_modules/:@noble/secp256k1(firmar/verificar, pequeño, sin dependencias)bech32(decodificar/codificar lnurl)
- Sin compilación nativa; las llamadas de red se limitan al GET opcional del desafío y al GET final del callback.
- Sin costo, sin nodo Lightning.
Instalar / actualizar dependencias incluidas
cd <skill_dir>
npm install
Autoprueba (sin servicios externos, sin costo)
Un servidor LUD-04 simulado local valida el ciclo completo de firmar → enviar → verificar:
cd <skill_dir>
npm test
Cubre: camino feliz, rechazo de repetición, seguridad de dry-run, rechazo de k1 manipulado,
estabilidad de clave por dominio, sobrescritura con --generate y validación de hex impar.
Verificación en el mundo real
Verificado contra dos servicios públicos:
| Servicio | Respuesta |
|---|---|
| bitsimp.com | {"status":"OK"} |
| lightninglogin.live | {"status":"OK"} |
Limitaciones
- Esto realiza el apretón de manos criptográfico; la creación de cuenta/inicio de sesión depende de que el servicio remoto reconozca la clave.
- La clave de enlace predeterminada se deriva por dominio de un secreto maestro local; no es la misma identidad que produciría la billetera móvil de un usuario. Suficiente para autenticación de agentes.
- Requiere salida de red para el GET opcional del desafío y el GET final del callback (sin pago, sin nodo Lightning).