March 28, 2026

SplitSig: Non-Custodial Key Derivation from Lightning Wallets

Every web application that handles Bitcoin faces the same dilemma: the user needs a signing key, but where does that key live? If the server generates it, the service is custodial. If the browser generates it, the user loses it when they clear their cache. If you derive it from the wallet, the server sees the derivation material.

I built a scheme that solves this. I call it SplitSig.

The Formula

privkey = SHA256( ecdsa_signature + nonce )
                 ───────────────   ─────
                 server sees this   browser-only

Two pieces. The server has one. The browser has the other. Neither alone can derive the private key.

How It Works

When a user authenticates with their Lightning wallet via LNURL-auth, the wallet signs a challenge with ECDSA. That signature goes to the server — that's how LNURL-auth works, it's inherent to the protocol.

Most signature-derived key systems (zkSync, Umbra, StarkWare) would simply hash that signature to produce a private key. But the server saw the signature, so the server could do the same hash and have the key. That's custodial.

SplitSig adds a second ingredient: a random 256-bit nonce generated in the browser via crypto.getRandomValues(). The nonce never leaves the browser. The server never sees it.

The split:

Server has: signature (from LNURL-auth callback)

Browser has: signature + nonce

Only the browser can compute SHA256(sig + nonce) = private key

Recovery

The nonce is saved in a recovery kit that the user downloads. To re-derive the key on a new device:

The LNURL-auth linking key is derived from the wallet's BIP-32 seed at path m/138'/... (LUD-04). It's stable across app updates, OS upgrades, and device changes. As long as the wallet seed is the same, the key is recoverable.

What's New

Deriving keys from signatures isn't new. These systems do it in production:

SystemKey from signature?Split knowledge?
zkSyncyesno
Umbra Protocolyesno
EIP-2645 / StarkWareyesno
Web3Auth / tKeyno (Shamir)yes
SplitSigyesyes

To my knowledge, SplitSig is the first to combine signature-derived keys with a client-side nonce split. The reason it hasn't appeared before is likely that LNURL-auth is a Bitcoin/Lightning niche, while most signature-derived key work happened in the Ethereum ecosystem where the wallet signs locally and the server never sees the signature.

Threat Model

Compromised server: Has the signature but not the nonce. Cannot derive the key. Even storing all signatures forever, brute-forcing a 256-bit nonce is infeasible.

Compromised browser: Has both pieces. Can derive the key. This is the "trusted code delivery problem" — an inherent limitation of all web applications. Blockstream has stated that "a browser must always be considered compromised." Native apps with reproducible builds are the only full mitigation.

Stolen recovery kit: Has the nonce but not the signature. Cannot derive the key without the wallet's BIP-32 seed.

Lost wallet seed: Different seed = different signature = different key. Same risk as any seed-based system.

Applications

SplitSig works for any web application that uses LNURL-auth and needs non-custodial signing keys:

Try It

The interactive demo walks through each step of the protocol, showing exactly what the server sees and what stays in the browser.

github.com/Antisys/splitsig

Protocol spec · Test vectors · Demo video · GPL-3.0