Black start

Recover with your 12 words alone — when the phone, its cloud copy and your provider are all gone. Everything here runs in your browser.

Keep your own copy of this page

This page is one file with nothing else to load. Save it now, keep it with your 12 words, and on the day you need it open the saved copy — then no server is involved. Download this page

Check the copy before you trust it with your words

The file's SHA-256 must equal the recover/index.html hash in docs/releases.md of the lightninginajar repository on GitHub (github.com/dav1dpgit/lightninginajar), in the row for the page build shown at the foot of this page. To get the hash of your copy: Mac shasum -a 256 lij-black-start.html · Windows certutil -hashfile lij-black-start.html SHA256 · Linux sha256sum lij-black-start.html. A copy that does not match is not this page — do not give it your words.

Your words are used once, here in your browser, to make two things — the key that opens your kit and your public name — and are then erased from this page. What the page keeps cannot spend your coins.

Where the page looks

What a kit is

A Black start kit is the set of transactions your wallet pre-signed for the day nothing else is left, sealed so that only your 12 words open it. Two transactions per channel: the close (your latest commitment, already carrying your provider’s signature) and the collect (the sweep of your side of it to an address on your words, usable after the channel’s delay). The wallet seals the kit and hands the sealed copy to your provider, twenty other LIJOX providers and public Nostr relays whenever a channel changes. Holders and relays keep ciphertext and the public name it is filed under — nothing that opens it.

What a kit looks like — inside (what this page shows you after it opens)
{ "v": 1, "made_at": 1758600000000, "seq": 1758600000000, "lsp": { "pubkey": "02a1b2…(66 hex)", "endpoint": "https://lsp.example.net" }, "sweep_destination_index": 3, "sweep_destination_address": "bc1q…", "feerate_normal_sat_vb": 10, "feerate_high_sat_vb": 40, "channels": [ { "channel_id": "8f3c…(64 hex)", "open": true, "claimable_sats": 123456, "funding_txo": "…(txid):1", "counterparty": "02a1b2…", "commitment_txid": "…(64 hex)", "commitment_hex": "0200000001…", ← THE CLOSE "htlc_tx_hexes": [], "to_self_delay": 144, "our_to_local_sats": 123456, "has_to_local": true, "sweep_txid_normal": "…", "sweep_hex_normal": "0200000001…", ← THE COLLECT (normal fee) "sweep_txid_high": "…", "sweep_hex_high": "0200000001…" ← THE COLLECT (high fee) } ] }

A wallet with no open channels keeps an empty kit ("channels": []) so this page can tell “nothing to close” from “nothing found”. seq is the freshness order: the newest copy wins.

What a kit looks like — sealed (what holders and relays keep)
{ "v": 1, "alg": "A256GCM", "kdf": "hkdf-sha256:lijox-black-start:escape-kit-v1", "npub": "17162c92…(64 hex — your public name, from your words)", "seq": 1758600000000, "nonce": "9f1e…(24 hex, fresh for every seal)", "ct": "…(hex — the kit above, encrypted, plus a 16-byte check tag)" }

A holder stores { "seq", "at", "pubkey", "kit": <that envelope> } under your npub and serves it back to anyone who asks — it is ciphertext. A relay stores it as a Nostr event of kind 30078 with the tag ["d","lijox-kit-v1"], its content the envelope as text, signed by your key.

How it is sealed, and how this page opens it
  1. seed = PBKDF2-HMAC-SHA512 over your 12 words (NFKD, joined by spaces), salt "mnemonic", 2048 rounds, 64 bytes — BIP39, no passphrase (as your wallet has always done).
  2. root = the first 32 bytes of HMAC-SHA512(key "Bitcoin seed", seed) — the BIP32 master private key.
  3. kit key K = HKDF-SHA256(ikm = root, salt "lijox-black-start", info "escape-kit-v1", 32 bytes). Used for AES-256-GCM only; it is not the cloud copy’s key.
  4. identity = the BIP32 child key at m/44'/1237'/0'/0/0 (NIP-06). pubkey = its 33-byte compressed public key; npub = the x coordinate, 32 bytes hex. That is the name every holder and relay files your kit under — public by design.
  5. seal (the wallet): AES-256-GCM with K, a fresh random 12-byte nonce, and the associated data "lijox-kit-v1:" + npub (so a kit cannot be re-filed under another name); the ciphertext and its 16-byte tag are ct. The envelope is { v, alg, kdf, npub, seq, nonce, ct }.
  6. hand-out (the wallet): to a holder, POST /v1/kit with an ECDSA signature by the identity key over SHA-256 of "lijox-kit-put-v1" ‖ pubkey ‖ seq (8 bytes big-endian) ‖ SHA-256(envelope); the holder keeps the highest seq. To a relay, the envelope as the content of a kind-30078 event, Schnorr-signed (BIP-340) by the same key.
  7. open (this page): steps 1–4 again from your words, here in the browser (WebCrypto and a small secp256k1). It asks every provider in the directory GET /v1/kit?npub=… and every relay for kind 30078 by your npub, then tries the copies newest first: AES-256-GCM decrypt with K, the copy’s nonce and the same associated data. A wrong key, a wrong name or a single changed byte fails the tag and the copy “did not open”. Nothing secret leaves the page — the requests carry only your npub.

To look at a copy yourself: a holder answers https://<provider>/v1/kit?npub=<your npub> in any browser; a relay answers the request ["REQ","x",{"kinds":[30078],"authors":["<your npub>"],"#d":["lijox-kit-v1"]}] over its websocket (with the nak tool: nak req -k 30078 -a <npub> -t d=lijox-kit-v1 wss://relay.damus.io). After a search, the copies card above lists every copy this page saw, with its raw envelope and those links, and whether your words opened it. The standard is docs/black-start-standard.md in the lightninginajar repository.

Black start page — build · lightninginajar.xyz/recover · the standard: docs/black-start-standard.md in the lightninginajar repository