Perdí la copia de seguridad de mi canal Lnd en un accidente de navegación, pero todavía tengo el mnemotécnico. Tenía un canal recién abierto a mi propio nodo c-lightning que nunca se ha utilizado. Forcé el cierre del canal desde el lado c-relámpago.
Los fondos ahora están en una dirección P2WPKH que he importado a Bitcoin Core. Ahora necesito averiguar la clave privada para barrerla. Esto requiere saber cómo derivarlo y luego cómo volcarlo.
Hay una solicitud de extracción de la utilidad de billetera que podría modificar para descargar la clave que necesito una vez que sepa cómo obtenerla.
También sé la identificación de la transacción de financiación, la identificación del canal y todos los demás detalles del canal que c-lightning escupe listfunds
.
La derivación de claves se explica en derivation.go :
m/1017'/coinType'/keyFamily'/0/index
El tipo de moneda para Bitcoin es 0, y creo que la familia de claves es 3: "usado en scripts que nos pagan directamente sin demora"
Supongo que el índice es 0 ya que fue el primer canal.
BOLT 3 luego explica cómo modificar esta clave para una transacción de compromiso. Debido a que el otro lado cerró este canal, necesito la to_remote
salida, que requiere el archivo remotepubkey
.
pubkey = basepoint + SHA256(per_commitment_point || basepoint) * G
privkey = basepoint_secret + SHA256(per_commitment_point || basepoint)
La especificación dice "remotepubkey usa el punto base de pago del nodo remoto". ¿Es esa la clave que acabamos de derivar?
Entonces eso deja el per_commitment_point
por resolver, derivado de per_commitment_secret
. Estoy confundido de dónde viene eso.
¿Qué conjuro Go debo usar para volcar la clave privada que estoy buscando?
En c-lightning, el punto por compromiso se deriva del hsm_secret
uso de per_commit_point de:
listfunds
, hasta que el canal se elimine algún tiempo después del cierre)cat ~/.lightning/debug.log | grep $node_id
), que se muestra comochan #$node_id
| grep commit
)Nos importa el punto de compromiso, no el secreto, porque la clave privada que necesitamos se deriva de la siguiente manera:
privkey = basepoint_secret + SHA256(per_commitment_point || basepoint)
Creé una herramienta para c-lightning para volcar este punto (con la ayuda de @cdecker): https://github.com/ElementsProject/lightning/pull/3115
Volviendo a Lnd... Un lugar fácil para volcar una clave privada es en el lnwallet walletinfo
comando. Agregue algo como esto a commands.go
:
basePointSecret, err := keyRing.DerivePrivKey(keychain.KeyDescriptor{
KeyLocator: keychain.KeyLocator{
Family: keychain.KeyFamilyPaymentBase,
Index: 0, // Same commitment index as used in c-lightning
},
})
// Parse per_commitment_point dumped by c-lightning:
bytes, err := hex.DecodeString(".........")
commitPoint, err := btcec.ParsePubKey(bytes, btcec.S256())
// Obtain SHA256(per_commitment_point || basepoint)
h := sha256.New()
h.Write(commitPoint.SerializeCompressed())
h.Write(basePointSecret.PubKey().SerializeCompressed())
commitTweak := h.Sum(nil)
// Obtain and dump private key
tweakedPrivkey := TweakPrivKey(basePointSecret, commitTweak)
commitmentWif, err := btcutil.NewWIF(tweakedPrivkey, &chaincfg.MainNetParams, true)
fmt.Printf("Dump commitment priv key: %s\n", commitmentWif)
Donde TweakPrivKey() se levanta de script_utils .
Importe la clave privada resultante en Bitcoin Core y ¡listo!
Eso deja el per_commitment_point por descubrir, derivado de per_commitment_secret. Estoy confundido de dónde viene eso.
Esto viene de los open_channel/accept_channel
mensajes en BOLT2. se llama first_per_commitment_point
.
Desafortunadamente, no puedo encontrar dónde puede acceder a esto en la documentación de lnd.
Una idea: consulte la documentación de copia de seguridad de lnd e intente descubrir cómo funciona. per_commitment_secret
debe tener una copia de seguridad para canjear fondos sin confianza. Dado que parece que no ofrecen un fácil acceso a eso, es posible que pueda encontrarlo en la información de la copia de seguridad.
René Pickhardt