musig2_test.go raw

   1  // Copyright 2013-2022 The btcsuite developers
   2  
   3  package musig2
   4  
   5  import (
   6  	"errors"
   7  	"fmt"
   8  	"sync"
   9  	"testing"
  10  
  11  	"next.orly.dev/pkg/nostr/crypto/ec"
  12  	"next.orly.dev/pkg/nostr/encoders/hex"
  13  	"github.com/minio/sha256-simd"
  14  )
  15  
  16  const (
  17  	testVectorBaseDir = "data"
  18  )
  19  
  20  func mustParseHex(str string) []byte {
  21  	b, err := hex.Dec(str)
  22  	if err != nil {
  23  		panic(fmt.Errorf("unable to parse hex: %v", err))
  24  	}
  25  	return b
  26  }
  27  
  28  type signer struct {
  29  	privKey    *btcec.SecretKey
  30  	pubKey     *btcec.PublicKey
  31  	nonces     *Nonces
  32  	partialSig *PartialSignature
  33  }
  34  
  35  type signerSet []signer
  36  
  37  func (s signerSet) keys() []*btcec.PublicKey {
  38  	keys := make([]*btcec.PublicKey, len(s))
  39  	for i := 0; i < len(s); i++ {
  40  		keys[i] = s[i].pubKey
  41  	}
  42  	return keys
  43  }
  44  
  45  func (s signerSet) partialSigs() []*PartialSignature {
  46  	sigs := make([]*PartialSignature, len(s))
  47  	for i := 0; i < len(s); i++ {
  48  		sigs[i] = s[i].partialSig
  49  	}
  50  	return sigs
  51  }
  52  
  53  func (s signerSet) pubNonces() [][PubNonceSize]byte {
  54  	nonces := make([][PubNonceSize]byte, len(s))
  55  	for i := 0; i < len(s); i++ {
  56  		nonces[i] = s[i].nonces.PubNonce
  57  	}
  58  	return nonces
  59  }
  60  
  61  func (s signerSet) combinedKey() *btcec.PublicKey {
  62  	uniqueKeyIndex := secondUniqueKeyIndex(s.keys(), false)
  63  	key, _, _, _ := AggregateKeys(
  64  		s.keys(), false, WithUniqueKeyIndex(uniqueKeyIndex),
  65  	)
  66  	return key.FinalKey
  67  }
  68  
  69  // testMultiPartySign executes a multi-party signing context w/ 100 signers.
  70  func testMultiPartySign(
  71  	t *testing.T, taprootTweak []byte,
  72  	tweaks ...KeyTweakDesc,
  73  ) {
  74  
  75  	const numSigners = 100
  76  	// First generate the set of signers along with their public keys.
  77  	signerKeys := make([]*btcec.SecretKey, numSigners)
  78  	signSet := make([]*btcec.PublicKey, numSigners)
  79  	for i := 0; i < numSigners; i++ {
  80  		privKey, err := btcec.NewSecretKey()
  81  		if err != nil {
  82  			t.Fatalf("unable to gen priv key: %v", err)
  83  		}
  84  		pubKey := privKey.PubKey()
  85  		signerKeys[i] = privKey
  86  		signSet[i] = pubKey
  87  	}
  88  	var combinedKey *btcec.PublicKey
  89  	var ctxOpts []ContextOption
  90  	switch {
  91  	case len(taprootTweak) == 0:
  92  		ctxOpts = append(ctxOpts, WithBip86TweakCtx())
  93  	case taprootTweak != nil:
  94  		ctxOpts = append(ctxOpts, WithTaprootTweakCtx(taprootTweak))
  95  	case len(tweaks) != 0:
  96  		ctxOpts = append(ctxOpts, WithTweakedContext(tweaks...))
  97  	}
  98  	ctxOpts = append(ctxOpts, WithKnownSigners(signSet))
  99  	// Now that we have all the signers, we'll make a new context, then
 100  	// generate a new session for each of them(which handles nonce
 101  	// generation).
 102  	signers := make([]*Session, numSigners)
 103  	for i, signerKey := range signerKeys {
 104  		signCtx, err := NewContext(
 105  			signerKey, false, ctxOpts...,
 106  		)
 107  		if err != nil {
 108  			t.Fatalf("unable to generate context: %v", err)
 109  		}
 110  		if combinedKey == nil {
 111  			combinedKey, err = signCtx.CombinedKey()
 112  			if err != nil {
 113  				t.Fatalf("combined key not available: %v", err)
 114  			}
 115  		}
 116  		session, err := signCtx.NewSession()
 117  		if err != nil {
 118  			t.Fatalf("unable to generate new session: %v", err)
 119  		}
 120  		signers[i] = session
 121  	}
 122  	// Next, in the pre-signing phase, we'll send all the nonces to each
 123  	// signer.
 124  	var wg sync.WaitGroup
 125  	for i, signCtx := range signers {
 126  		signCtx := signCtx
 127  		wg.Add(1)
 128  		go func(idx int, signer *Session) {
 129  			defer wg.Done()
 130  			for j, otherCtx := range signers {
 131  				if idx == j {
 132  					continue
 133  				}
 134  				nonce := otherCtx.PublicNonce()
 135  				haveAll, err := signer.RegisterPubNonce(nonce)
 136  				if err != nil {
 137  					t.Fatalf("unable to add public nonce")
 138  				}
 139  				if j == len(signers)-1 && !haveAll {
 140  					t.Fatalf("all public nonces should have been detected")
 141  				}
 142  			}
 143  		}(i, signCtx)
 144  	}
 145  	wg.Wait()
 146  	msg := sha256.Sum256([]byte("let's get taprooty"))
 147  	// In the final step, we'll use the first signer as our combiner, and
 148  	// generate a signature for each signer, and then accumulate that with
 149  	// the combiner.
 150  	combiner := signers[0]
 151  	for i := range signers {
 152  		signer := signers[i]
 153  		partialSig, err := signer.Sign(msg)
 154  		if err != nil {
 155  			t.Fatalf("unable to generate partial sig: %v", err)
 156  		}
 157  		// We don't need to combine the signature for the very first
 158  		// signer, as it already has that partial signature.
 159  		if i != 0 {
 160  			haveAll, err := combiner.CombineSig(partialSig)
 161  			if err != nil {
 162  				t.Fatalf("unable to combine sigs: %v", err)
 163  			}
 164  
 165  			if i == len(signers)-1 && !haveAll {
 166  				t.Fatalf("final sig wasn't reconstructed")
 167  			}
 168  		}
 169  	}
 170  	// Finally we'll combined all the nonces, and ensure that it validates
 171  	// as a single schnorr signature.
 172  	finalSig := combiner.FinalSig()
 173  	if !finalSig.Verify(msg[:], combinedKey) {
 174  		t.Fatalf("final sig is invalid!")
 175  	}
 176  	// Verify that if we try to sign again with any of the existing
 177  	// signers, then we'll get an error as the nonces have already been
 178  	// used.
 179  	for _, signer := range signers {
 180  		_, err := signer.Sign(msg)
 181  		if err != ErrSigningContextReuse {
 182  			t.Fatalf("expected to get signing context reuse")
 183  		}
 184  	}
 185  }
 186  
 187  // TestMuSigMultiParty tests that for a given set of 100 signers, we're able to
 188  // properly generate valid sub signatures, which ultimately can be combined
 189  // into a single valid signature.
 190  func TestMuSigMultiParty(t *testing.T) {
 191  	t.Parallel()
 192  	testTweak := [32]byte{
 193  		0xE8, 0xF7, 0x91, 0xFF, 0x92, 0x25, 0xA2, 0xAF,
 194  		0x01, 0x02, 0xAF, 0xFF, 0x4A, 0x9A, 0x72, 0x3D,
 195  		0x96, 0x12, 0xA6, 0x82, 0xA2, 0x5E, 0xBE, 0x79,
 196  		0x80, 0x2B, 0x26, 0x3C, 0xDF, 0xCD, 0x83, 0xBB,
 197  	}
 198  	t.Run(
 199  		"no_tweak", func(t *testing.T) {
 200  			t.Parallel()
 201  
 202  			testMultiPartySign(t, nil)
 203  		},
 204  	)
 205  	t.Run(
 206  		"tweaked", func(t *testing.T) {
 207  			t.Parallel()
 208  
 209  			testMultiPartySign(
 210  				t, nil, KeyTweakDesc{
 211  					Tweak: testTweak,
 212  				},
 213  			)
 214  		},
 215  	)
 216  	t.Run(
 217  		"tweaked_x_only", func(t *testing.T) {
 218  			t.Parallel()
 219  
 220  			testMultiPartySign(
 221  				t, nil, KeyTweakDesc{
 222  					Tweak:   testTweak,
 223  					IsXOnly: true,
 224  				},
 225  			)
 226  		},
 227  	)
 228  	t.Run(
 229  		"taproot_tweaked_x_only", func(t *testing.T) {
 230  			t.Parallel()
 231  
 232  			testMultiPartySign(t, testTweak[:])
 233  		},
 234  	)
 235  	t.Run(
 236  		"taproot_bip_86", func(t *testing.T) {
 237  			t.Parallel()
 238  
 239  			testMultiPartySign(t, []byte{})
 240  		},
 241  	)
 242  }
 243  
 244  // TestMuSigEarlyNonce tests that for protocols where nonces need to be
 245  // exchagned before all signers are known, the context API works as expected.
 246  func TestMuSigEarlyNonce(t *testing.T) {
 247  	t.Parallel()
 248  	privKey1, err := btcec.NewSecretKey()
 249  	if err != nil {
 250  		t.Fatalf("unable to gen priv key: %v", err)
 251  	}
 252  	privKey2, err := btcec.NewSecretKey()
 253  	if err != nil {
 254  		t.Fatalf("unable to gen priv key: %v", err)
 255  	}
 256  	// If we try to make a context, with just the secret key and sorting
 257  	// value, we should get an error.
 258  	_, err = NewContext(privKey1, true)
 259  	if !errors.Is(err, ErrSignersNotSpecified) {
 260  		t.Fatalf("unexpected ctx error: %v", err)
 261  	}
 262  	signers := []*btcec.PublicKey{privKey1.PubKey(), privKey2.PubKey()}
 263  	numSigners := len(signers)
 264  	ctx1, err := NewContext(
 265  		privKey1, true, WithNumSigners(numSigners), WithEarlyNonceGen(),
 266  	)
 267  	if err != nil {
 268  		t.Fatalf("unable to make ctx: %v", err)
 269  	}
 270  	pubKey1 := ctx1.PubKey()
 271  	ctx2, err := NewContext(
 272  		privKey2, true, WithKnownSigners(signers), WithEarlyNonceGen(),
 273  	)
 274  	if err != nil {
 275  		t.Fatalf("unable to make ctx: %v", err)
 276  	}
 277  	pubKey2 := ctx2.PubKey()
 278  	// At this point, the combined key shouldn't be available for signer 1,
 279  	// but should be for signer 2, as they know about all signers.
 280  	if _, err := ctx1.CombinedKey(); !errors.Is(err, ErrNotEnoughSigners) {
 281  		t.Fatalf("unepxected error: %v", err)
 282  	}
 283  	_, err = ctx2.CombinedKey()
 284  	if err != nil {
 285  		t.Fatalf("unable to get combined key: %v", err)
 286  	}
 287  	// The early nonces _should_ be available at this point.
 288  	nonce1, err := ctx1.EarlySessionNonce()
 289  	if err != nil {
 290  		t.Fatalf("session nonce not available: %v", err)
 291  	}
 292  	nonce2, err := ctx2.EarlySessionNonce()
 293  	if err != nil {
 294  		t.Fatalf("session nonce not available: %v", err)
 295  	}
 296  	// The number of registered signers should still be 1 for both parties.
 297  	if ctx1.NumRegisteredSigners() != 1 {
 298  		t.Fatalf(
 299  			"expected 1 signer, instead have: %v",
 300  			ctx1.NumRegisteredSigners(),
 301  		)
 302  	}
 303  	if ctx2.NumRegisteredSigners() != 2 {
 304  		t.Fatalf(
 305  			"expected 2 signers, instead have: %v",
 306  			ctx2.NumRegisteredSigners(),
 307  		)
 308  	}
 309  	// If we try to make a session, we should get an error since we dn't
 310  	// have all the signers yet.
 311  	if _, err := ctx1.NewSession(); !errors.Is(err, ErrNotEnoughSigners) {
 312  		t.Fatalf("unexpected session key error: %v", err)
 313  	}
 314  	// The combined key should also be unavailable as well.
 315  	if _, err := ctx1.CombinedKey(); !errors.Is(err, ErrNotEnoughSigners) {
 316  		t.Fatalf("unexpected combined key error: %v", err)
 317  	}
 318  	// We'll now register the other signer for party 1.
 319  	done, err := ctx1.RegisterSigner(&pubKey2)
 320  	if err != nil {
 321  		t.Fatalf("unable to register signer: %v", err)
 322  	}
 323  	if !done {
 324  		t.Fatalf("signer 1 doesn't have all keys")
 325  	}
 326  	// If we try to register the signer again, we should get an error.
 327  	_, err = ctx2.RegisterSigner(&pubKey1)
 328  	if !errors.Is(err, ErrAlreadyHaveAllSigners) {
 329  		t.Fatalf("should not be able to register too many signers")
 330  	}
 331  	// We should be able to create the session at this point.
 332  	session1, err := ctx1.NewSession()
 333  	if err != nil {
 334  		t.Fatalf("unable to create new session: %v", err)
 335  	}
 336  	session2, err := ctx2.NewSession()
 337  	if err != nil {
 338  		t.Fatalf("unable to create new session: %v", err)
 339  	}
 340  	msg := sha256.Sum256([]byte("let's get taprooty, LN style"))
 341  	// If we try to sign before we have the combined nonce, we shoudl get
 342  	// an error.
 343  	_, err = session1.Sign(msg)
 344  	if !errors.Is(err, ErrCombinedNonceUnavailable) {
 345  		t.Fatalf("unable to gen sig: %v", err)
 346  	}
 347  	// Now we can exchange nonces to continue with the rest of the signing
 348  	// process as normal.
 349  	done, err = session1.RegisterPubNonce(nonce2.PubNonce)
 350  	if err != nil {
 351  		t.Fatalf("unable to register nonce: %v", err)
 352  	}
 353  	if !done {
 354  		t.Fatalf("signer 1 doesn't have all nonces")
 355  	}
 356  	done, err = session2.RegisterPubNonce(nonce1.PubNonce)
 357  	if err != nil {
 358  		t.Fatalf("unable to register nonce: %v", err)
 359  	}
 360  	if !done {
 361  		t.Fatalf("signer 2 doesn't have all nonces")
 362  	}
 363  	// Registering the nonce again should error out.
 364  	_, err = session2.RegisterPubNonce(nonce1.PubNonce)
 365  	if !errors.Is(err, ErrAlreadyHaveAllNonces) {
 366  		t.Fatalf("shouldn't be able to register nonces twice")
 367  	}
 368  	// Sign the message and combine the two partial sigs into one.
 369  	_, err = session1.Sign(msg)
 370  	if err != nil {
 371  		t.Fatalf("unable to gen sig: %v", err)
 372  	}
 373  	sig2, err := session2.Sign(msg)
 374  	if err != nil {
 375  		t.Fatalf("unable to gen sig: %v", err)
 376  	}
 377  	done, err = session1.CombineSig(sig2)
 378  	if err != nil {
 379  		t.Fatalf("unable to combine sig: %v", err)
 380  	}
 381  	if !done {
 382  		t.Fatalf("all sigs should be known now: %v", err)
 383  	}
 384  	// If we try to combine another sig, then we should get an error.
 385  	_, err = session1.CombineSig(sig2)
 386  	if !errors.Is(err, ErrAlredyHaveAllSigs) {
 387  		t.Fatalf("shouldn't be able to combine again")
 388  	}
 389  	// Finally, verify that the final signature is valid.
 390  	combinedKey, err := ctx1.CombinedKey()
 391  	if err != nil {
 392  		t.Fatalf("unexpected combined key error: %v", err)
 393  	}
 394  	finalSig := session1.FinalSig()
 395  	if !finalSig.Verify(msg[:], combinedKey) {
 396  		t.Fatalf("final sig is invalid!")
 397  	}
 398  }
 399  
 400  type memsetRandReader struct {
 401  	i int
 402  }
 403  
 404  func (mr *memsetRandReader) Read(buf []byte) (n int, err error) {
 405  	for i := range buf {
 406  		buf[i] = byte(mr.i)
 407  	}
 408  	return len(buf), nil
 409  }
 410