Deep Dive

Schnorr signatures, and what Taproot did with them

Schnorr signatures are linear: several public keys add into one key, and several signature shares add into one signature. That single property is what lets a cooperative multisig spend look identical on chain to a single-key spend.

8 min readCryptography
Schnorr signatures, and what Taproot did with them

The short answer

Bitcoin has always used digital signatures to prove a spend was authorised. Until November 2021 it had exactly one signature scheme, ECDSA, and ECDSA signatures do not combine. Taproot added a second, Schnorr, which does: several public keys add into one public key, and the matching signature shares add into one signature that verifies against it. The specification has a name for that property: linearity.

Everything Taproot is celebrated for follows from that, plus one structural change: an output can now commit to a tree of alternative spending conditions and publish only the branch used. A spend requiring five people to agree can reach the chain as one signature against one key, indistinguishable from one person spending alone.

What a signature proves

An output has no owner in any sense the software understands. It carries a condition, and whoever satisfies it moves the coins. A signature satisfies the most common condition: it proves the spender holds a private key without putting that key where a node could read it. Asymmetric cryptography is the piece underneath this one. The scheme doing the proving is a choice, and Bitcoin made a different one in 2021.

Where ECDSA stops

BIP 340 names what Bitcoin had been doing, ECDSA over the secp256k1 curve with SHA256 hashes, then lists its downsides against Schnorr over the same curve. Schnorr signatures are provably secure under weaker assumptions. They are non-malleable, where ECDSA signatures are "inherently malleable": a third party without the secret key can alter a valid signature into another valid one for the same key and message. They encode in a fixed 64 bytes rather than a variable DER encoding of up to 72. Their public keys are 32 bytes rather than 33. And they can be verified in batches, which the standardised formulation of ECDSA cannot.

The one that matters here is linearity. In BIP 340's words, Schnorr signatures "provide a simple and efficient method that enables multiple collaborating parties to produce a signature that is valid for the sum of their public keys."

The reason is in the verification equation. A BIP 340 signature is a pair (r, s) and it verifies when s·G = R + h(r || pk || m)·P, where P is the public key, R a nonce point, G the curve's base point and h a tagged hash. Public keys are points, and points add; the s values are integers, and integers add. So a group agreeing on a shared R can each compute a share of s from their own secret, and those shares sum to an s valid for the sum of their keys. ECDSA's s involves a modular inverse of the nonce, which breaks the symmetry.

None of this makes multi-party ECDSA impossible. BIP 340 notes that recent papers claim these applications "are also possible with ECDSA", but that consensus support for Schnorr "would significantly simplify the constructions."

Three BIPs, and which does what

The upgrade is usually spoken of as one thing. It is three specifications, all marked Deployed, and conflating them is where the confusion starts.

BIPTitleWhat it specifies
340Schnorr Signatures for secp256k1The signature scheme itself: 64-byte signatures, 32-byte X-only public keys, tagged hashes, batch verification. On its own it changes no Bitcoin rule.
341Taproot: SegWit version 1 spending rulesThe output type and how it is spent: a 32-byte witness program, a key path, a script path, and the Merkle tree of scripts behind it.
342Validation of Taproot ScriptsTapscript: the script rules inside a leaf of that tree.

BIP 342 is the one people skip, and it carries a real change. Inside tapscript, OP_CHECKSIG and OP_CHECKSIGVERIFY verify BIP 340 signatures instead of ECDSA ones, OP_CHECKMULTISIG and OP_CHECKMULTISIGVERIFY are disabled outright, and a new OP_CHECKSIGADD replaces them so the same multisignature policies stay batch-verifiable. The three activated together at block 709,632, covered here when it happened.

The output key, and the tree behind it

A Taproot output is a SegWit version 1 output whose 32-byte witness program is a public key, the output key q. BIP 341 builds it as Q = P + int(hash_TapTweak(p || k))·G, where p is an internal public key and k the Merkle root of a tree whose leaves each hold a version number and a script.

Consensus picks between two ways to spend it by counting the witness stack. If exactly one element is left after the optional annex is removed, it is a key path spend and that element is the signature, checked against q. If two or more are left, it is a script path spend: the second-to-last element is the script, the last a control block of 33 + 32m bytes carrying the internal key and the Merkle path, and the node recomputes the root to check it produces q.

That is what MAST buys. BIP 341 states it in one line: Merkle branches "let us only reveal the actually executed part of the script to the blockchain, as opposed to all possible ways a script can be executed." A wallet can hold an everyday path, a timelocked recovery path and a co-signer path; a spend reveals one, and the rest stay hashes inside a root that was never expanded. The key path is stronger still, because BIP 341 notes that "as long as the key-based spending path is used for spending, it is not revealed whether a script path was permitted as well."

The size claim is exact, not approximate. A key path witness is a single 64-byte signature, or 65 with an explicit sighash byte, and the output is 32 bytes. Neither number depends on how many people cooperated to produce that signature. Same weight, same fee, same appearance.

Adding keys is not, by itself, multisig

This is where popular accounts go wrong. Linearity means keys and signature shares can be summed. It does not mean summing them is safe.

Take Alice with public key XA and Bob with XB, aggregating by adding the two points. Bob publishes not XB but XB minus XA. Pieter Wuille, one of BIP 340's authors, set out what follows in January 2018:

If he does so, others will assume that XA + XB' is the aggregated key that Alice and Bob need to cooperate in order to sign for. Unfortunately, that sum is equal to XB, and Bob can clearly sign for this by himself.

The sum everyone treats as the joint key is a key Bob alone controls. This is a rogue-key attack. Requiring each party to prove they hold the private key behind the key they publish closes it, but Wuille calls that mitigation "fragile at best", which is why aggregation needs a protocol rather than an addition.

BIP 327 specifies that scheme, MuSig2. It weights each key by a coefficient derived from a hash of the whole key list before summing, which removes the attack, and defines a two-round interactive signing protocol. Three limits belong with it. It is informational rather than consensus, so it is a convention between wallets, not a rule nodes enforce. It is an n-of-n scheme and explicitly "not a t-of-n threshold-signature scheme", so a 2-of-3 arrangement still needs either a threshold scheme such as FROST or a script leaf using OP_CHECKSIGADD. And BIP 340 warns, in bold, that multisignature signing schemes "in general are insecure" with the deterministic nonce generation it otherwise specifies, the reverse of the advice for a single signer. Aggregated multisig is a wallet engineering problem Taproot made possible, not one it solved.

BIP 341 adds a related trap. If the aggregate is a plain sum, one party can slip a script path into the tweak unnoticed and spend around the policy. The BIP's advice is to commit to an unspendable script path even when none is wanted.

What it does not do

It is not privacy for the chain. Amounts, addresses and the links between transactions are as public as in 2009. Taproot narrows one leak, the shape of the spending condition, and touches nothing else.

It did not make older outputs insecure or obsolete. Taproot is a soft fork, and BIP 341 is explicit that outputs other than 32-byte version 1 ones "remain unencumbered". Nothing about a P2WPKH or P2PKH address changed.

It is not automatic. A Taproot output exists only if a wallet builds one, and key aggregation only if wallets implement an interactive protocol and agree on it. Adoption is a per-wallet decision, made repeatedly over years.

And the privacy property is collective. A cooperative multisig spend is indistinguishable from a single-key spend only in a crowd of single-key spends. BIP 341's construction guidance shows how sharp this is: where key path spending is genuinely impossible, it recommends deriving the internal key as a Nothing Up My Sleeve point plus a random offset, purely "to avoid leaking the information that key path spending is not possible." A property everyone has to maintain individually is one you can opt out of by accident.

Sources

Newsletter

Bitcoin, without the noise

What happened in Bitcoin, what it actually changes, and the sources so you can check us. One issue at a time, straight to your inbox.

  • One email per issue, never a drip campaign
  • No tracking pixels and no shared addresses
  • Unsubscribe from any issue in one click

Get the next issue

One email per issue, no tracking pixels, and unsubscribe from any of them. We do not share your address. Privacy policy