# State of Signature Crypto

## Overview

• n-of-n multisig (MuSig variants)
• MuSig2 usage patterns
• implementation status
• discussion about open questions in practice
• t-of-n threshold sig (FROST)
• signature aggregation
• half aggregation
• full aggregation

# MuSig

## MuSig Variants

• MuSig1 (deprecated)
• MuSig-DN (or alternatively GKMN'21 https://eprint.iacr.org/2021/1055.pdf )
• MuSig2

## MuSig2: High Level Explanation

• multiple parties (each having an individual pubkey) sign the same message under a *single* aggregate pubkey
• great for Taproot
• simple key setup: everybody can compute aggregate pubkey from individual pubkeys
• 2-round signing protocol
(all signers send two broadcast messages)
• first round can be run before message to be signed (transaction) is known
• effectively one round

## MuSig2: 2-of-2 example

$$X_1$$

$$X_2$$

$$R_1', R_1''$$

$$R_2', R_2''$$

$$s_1$$

$$s_2$$

$$R_i=R_i'(R_i'')^b$$

$$b = H_\textit{non}(\widetilde X,m, R_1'R_2', R_1''R_2'')$$

$$c = H_\textit{sig}(\widetilde X, R_1R_2, m)$$

$$\text{return}\ (R_1R_2,s_1+s_2)$$

$$\widetilde X=X_1^{\textcolor{#00c3ff}{}{a_1}}\cdot X_2^{\textcolor{#00c3ff}{}{a_2}}$$

$$a_i = H_\textit{agg}(X_i, \{\textit{pk}_1, \textit{pk}_2\})$$

## MuSig2: 2-of-2 example

$$X_1$$

$$X_2$$

$$R_1', R_1'', m$$

$$R_2', R_2''$$

$$s_2$$

$$\text{return}\ (R_1R_2,s_1+s_2)$$

$$\widetilde X=X_1^{\textcolor{#00c3ff}{}{a_1}}\cdot X_2^{\textcolor{#00c3ff}{}{a_2}}$$

$$a_i = H_\textit{agg}(X_i, \{\textit{pk}_1, \textit{pk}_2\})$$

## MuSig2: 2-of-2 example (precomp)

$$X_1$$

$$X_2$$

$$R_1', R_1''$$

$$R_2', R_2''$$

$$s_2, m$$

$$\text{return}\ (R_1R_2,s_1+s_2)$$

$$\widetilde X=X_1^{\textcolor{#00c3ff}{}{a_1}}\cdot X_2^{\textcolor{#00c3ff}{}{a_2}}$$

$$a_i = H_\textit{agg}(X_i, \{\textit{pk}_1, \textit{pk}_2\})$$

### libsecp256k1-zkp implementation

• (draft) key agg spec: src/modules/musig/musig-spec.mediawiki
• Jonas' MuSig2 PR #131 (needs review)
• API is safe to use, if you
• provide fresh, uniform randomness to nonce gen fn (which returns a "secnonce")
• the secnonce structure is never copied or serialized.
• opaque data structures are never written to or read from directly.

## Discussion

• (Hardware) Wallets
• need to keep state between rounds
• current workflow vs MuSig2 workflow
• sweet case:
Taproot(key = 2of2 MuSig,
script = 2of3 multisig)
• Key derivation and descriptors?
• musig(xpub1/*, xpub2/*) vs
• musig(xpub1, xpub2)/*
• it would mean that to the outside world, the combined wallet is just an xpub.

• PSBT

## Threshold

• t-of-n instead of n-of-n
• looks similar but key setup in fact much more involved
• no spontaneous key aggregation as in MuSig
• secure broadcast channel necessary
• key shares of other parties need to be backed up
• candidate scheme: FROST
• signing very similar to MuSig2
• looks solid
• there are bip340 compatible implementations
• ElementsProject/secp256k1-zkp/pull/138
• taurusgroup/multi-party-sig
•  Tim is working on improvements

# Cross-Input Signature Aggregation

## Signature Aggregation

• AggVerify((pk_1, m_1), ..., (pk_n, m_n), sig) -> {true, false}

• ​​Trivial solution:

  sig = (sig_1, ..., sig_n)
• Goal Nr 2: sig should be short

• Note the different messages != multisignatures, MuSig, etc.

## Schnorr Half Aggregation

• Aggregate(sig_1, ..., sig_n) -> sig
• |sig| ≈ 1/2 (|sig_1| + ... + |sig_n|)
• aggregation is non-interactive (can be done by block producers)
• proposed on Bitcoin mailing list ~2017, recent academic paper (Chalkias et al.)

## Schnorr Full Aggregation

• |sig| = |sig_1|

• aggregation _is_ interactive

• Tx-wide aggregation

• can be combined with half aggregation

## Consensus

• Requires new signature verification algorithm
• Only available update path: new SegWit version due to interactions with OP_SUCCESS
• Option: new SegWit version, only allow aggregation of key path spends
• But that's limiting
• Better: Move public keys out of Script
• instead of taproot merkle tree leafs being scripts
• leafs consist of both pubkey and script
• in order to spend need both sig for pubkey and script inputs
• Most advanced in that family of ideas: entroot (surprisingly elegant & simple update)

## Savings for typical tx

|                                               | bytes | weight units |
|-----------------------------------------------+-------+--------------|
| half aggregation                              | 20.6% |         7.6% |
| full aggregation                              | 26.1% |         9.6% |
| both                                          | 33.6% |        12.4% |
| max (like infinite large full agged coinjoin)  | 41.2% |        15.2% |


## Discussion

• full aggregation: nonce generation similar to MuSig. Unless all other partial signatures come from trusted signers, no deterministic nonce generation, hence randomness (or non-repeating counter) required
• half aggregation:
• how to resubmit transactions after a reorgs (only a problem if used across transactions)?
• breaks adaptor sigs?
• more CPU/byte necessary to verify a block
• github.com/ElementsProject/cross-input-aggregation

# State of libsecp256k1

## libsecp256k1

• started by Pieter Wuille in 2013 to replace OpenSSL's ECDSA implementation in Bitcoin Core
• written in C (... C89)
• general-purpose library but written with Bitcoin Core as a main user in mind
• ECDSA and tweaking keys (e.g., for BIP32)
• modules for
• ECDSA with key recovery
• ECDH
• Schnorr sigs (experimental?!)
• extra keys (experimental?!)

## Problems

• No clear rule what should be in libsecp256k1
• only stuff used by Core?
• counter-example: ECDH
• "things relevant to the wider Bitcoin ecosystem"
• should those be in forks like libsecp256k1-zkp?
• No release ever
• experimental modules
• Lack of developers
• lots of abandoned PRs
• people think they can't contribute because they lack expertise in cryptography but that's just not true

By iamjon

• 186