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