1 // Copyright (c) 2013-2022 The btcsuite developers
2 3 package musig2
4 5 import (
6 "fmt"
7 8 "next.orly.dev/pkg/nostr/crypto/ec"
9 "next.orly.dev/pkg/nostr/crypto/ec/schnorr"
10 "next.orly.dev/pkg/lol/chk"
11 )
12 13 var (
14 // ErrSignersNotSpecified is returned when a caller attempts to create
15 // a context without specifying either the total number of signers, or
16 // the complete set of singers.
17 ErrSignersNotSpecified = fmt.Errorf(
18 "total number of signers or all " +
19 "signers must be known",
20 )
21 // ErrSignerNotInKeySet is returned when a the secret key for a signer
22 // isn't included in the set of signing public keys.
23 ErrSignerNotInKeySet = fmt.Errorf(
24 "signing key is not found in key" +
25 " set",
26 )
27 // ErrAlreadyHaveAllNonces is called when RegisterPubNonce is called too
28 // many times for a given signing session.
29 //
30 // ErrAlreadyHaveAllNonces is returned when a caller attempts to
31 // register a signer, once we already have the total set of known
32 // signers.
33 ErrAlreadyHaveAllNonces = fmt.Errorf("already have all nonces")
34 // ErrNotEnoughSigners is returned when a caller attempts to create a
35 // session from a context, but before all the required signers are
36 // known.
37 //
38 // ErrNotEnoughSigners is returned if a caller attempts to obtain an
39 // early nonce when it wasn't specified
40 ErrNotEnoughSigners = fmt.Errorf("not enough signers")
41 ErrAlreadyHaveAllSigners = fmt.Errorf("all signers registered")
42 // ErrAlredyHaveAllSigs is called when CombineSig is called too many
43 // times for a given signing session.
44 ErrAlredyHaveAllSigs = fmt.Errorf("already have all sigs")
45 // ErrSigningContextReuse is returned if a user attempts to sign using
46 // the same signing context more than once.
47 ErrSigningContextReuse = fmt.Errorf("nonce already used")
48 // ErrFinalSigInvalid is returned when the combined signature turns out
49 // to be invalid.
50 ErrFinalSigInvalid = fmt.Errorf("final signature is invalid")
51 // ErrCombinedNonceUnavailable is returned when a caller attempts to
52 // sign a partial signature, without first having collected all the
53 // required combined nonces.
54 ErrCombinedNonceUnavailable = fmt.Errorf("missing combined nonce")
55 // ErrTaprootInternalKeyUnavailable is returned when a user attempts to
56 // obtain the
57 ErrTaprootInternalKeyUnavailable = fmt.Errorf("taproot tweak not used")
58 ErrNoEarlyNonce = fmt.Errorf("no early nonce available")
59 )
60 61 // Context is a managed signing context for musig2. It takes care of things
62 // like securely generating secret nonces, aggregating keys and nonces, etc.
63 type Context struct {
64 // signingKey is the key we'll use for signing.
65 signingKey *btcec.SecretKey
66 // pubKey is our even-y coordinate public key.
67 pubKey *btcec.PublicKey
68 // combinedKey is the aggregated public key.
69 combinedKey *AggregateKey
70 // uniqueKeyIndex is the index of the second unique key in the keySet.
71 // This is used to speed up signing and verification computations.
72 uniqueKeyIndex int
73 // keysHash is the hash of all the keys as defined in musig2.
74 keysHash []byte
75 // opts is the set of options for the context.
76 opts *contextOptions
77 // shouldSort keeps track of if the public keys should be sorted before
78 // any operations.
79 shouldSort bool
80 // sessionNonce will be populated if the earlyNonce option is true.
81 // After the first session is created, this nonce will be blanked out.
82 sessionNonce *Nonces
83 }
84 85 // ContextOption is a functional option argument that allows callers to modify
86 // the musig2 signing is done within a context.
87 type ContextOption func(*contextOptions)
88 89 // contextOptions houses the set of functional options that can be used to
90 // musig2 signing protocol.
91 type contextOptions struct {
92 // tweaks is the set of optinoal tweaks to apply to the combined public
93 // key.
94 tweaks []KeyTweakDesc
95 // taprootTweak specifies the taproot tweak. If specified, then we'll
96 // use this as the script root for the BIP 341 taproot (x-only) tweak.
97 // Normally we'd just apply the raw 32 byte tweak, but for taproot, we
98 // first need to compute the aggregated key before tweaking, and then
99 // use it as the internal key. This is required as the taproot tweak
100 // also commits to the public key, which in this case is the aggregated
101 // key before the tweak.
102 taprootTweak []byte
103 // bip86Tweak if true, then the weak will just be
104 // h_tapTweak(internalKey) as there is no true script root.
105 bip86Tweak bool
106 // keySet is the complete set of signers for this context.
107 keySet []*btcec.PublicKey
108 // numSigners is the total number of signers that will eventually be a
109 // part of the context.
110 numSigners int
111 // earlyNonce determines if a nonce should be generated during context
112 // creation, to be automatically passed to the created session.
113 earlyNonce bool
114 }
115 116 // defaultContextOptions returns the default context options.
117 func defaultContextOptions() *contextOptions { return &contextOptions{} }
118 119 // WithTweakedContext specifies that within the context, the aggregated public
120 // key should be tweaked with the specified tweaks.
121 func WithTweakedContext(tweaks ...KeyTweakDesc) ContextOption {
122 return func(o *contextOptions) { o.tweaks = tweaks }
123 }
124 125 // WithTaprootTweakCtx specifies that within this context, the final key should
126 // use the taproot tweak as defined in BIP 341: outputKey = internalKey +
127 // h_tapTweak(internalKey || scriptRoot). In this case, the aggreaged key
128 // before the tweak will be used as the internal key.
129 func WithTaprootTweakCtx(scriptRoot []byte) ContextOption {
130 return func(o *contextOptions) { o.taprootTweak = scriptRoot }
131 }
132 133 // WithBip86TweakCtx specifies that within this context, the final key should
134 // use the taproot tweak as defined in BIP 341, with the BIP 86 modification:
135 // outputKey = internalKey + h_tapTweak(internalKey)*G. In this case, the
136 // aggreaged key before the tweak will be used as the internal key.
137 func WithBip86TweakCtx() ContextOption {
138 return func(o *contextOptions) { o.bip86Tweak = true }
139 }
140 141 // WithKnownSigners is an optional parameter that should be used if a session
142 // can be created as soon as all the singers are known.
143 func WithKnownSigners(signers []*btcec.PublicKey) ContextOption {
144 return func(o *contextOptions) {
145 o.keySet = signers
146 o.numSigners = len(signers)
147 }
148 }
149 150 // WithNumSigners is a functional option used to specify that a context should
151 // be created without knowing all the signers. Instead the total number of
152 // signers is specified to ensure that a session can only be created once all
153 // the signers are known.
154 //
155 // NOTE: Either WithKnownSigners or WithNumSigners MUST be specified.
156 func WithNumSigners(n int) ContextOption {
157 return func(o *contextOptions) { o.numSigners = n }
158 }
159 160 // WithEarlyNonceGen allow a caller to specify that a nonce should be generated
161 // early, before the session is created. This should be used in protocols that
162 // require some partial nonce exchange before all the signers are known.
163 //
164 // NOTE: This option must only be specified with the WithNumSigners option.
165 func WithEarlyNonceGen() ContextOption {
166 return func(o *contextOptions) { o.earlyNonce = true }
167 }
168 169 // NewContext creates a new signing context with the passed singing key and set
170 // of public keys for each of the other signers.
171 //
172 // NOTE: This struct should be used over the raw Sign API whenever possible.
173 func NewContext(
174 signingKey *btcec.SecretKey, shouldSort bool,
175 ctxOpts ...ContextOption,
176 ) (*Context, error) {
177 178 // First, parse the set of optional context options.
179 opts := defaultContextOptions()
180 for _, option := range ctxOpts {
181 option(opts)
182 }
183 pubKey := signingKey.PubKey()
184 ctx := &Context{
185 signingKey: signingKey,
186 pubKey: pubKey,
187 opts: opts,
188 shouldSort: shouldSort,
189 }
190 switch {
191 // We know all the signers, so we can compute the aggregated key, along
192 // with all the other intermediate state we need to do signing and
193 // verification.
194 case opts.keySet != nil:
195 if err := ctx.combineSignerKeys(); chk.T(err) {
196 return nil, err
197 }
198 // The total signers are known, so we add ourselves, and skip key
199 // aggregation.
200 case opts.numSigners != 0:
201 // Otherwise, we'll add ourselves as the only known signer, and
202 // await further calls to RegisterSigner before a session can
203 // be created.
204 opts.keySet = make([]*btcec.PublicKey, 0, opts.numSigners)
205 opts.keySet = append(opts.keySet, pubKey)
206 default:
207 return nil, ErrSignersNotSpecified
208 }
209 // If early nonce generation is specified, then we'll generate the
210 // nonce now to pass in to the session once all the callers are known.
211 if opts.earlyNonce {
212 var err error
213 ctx.sessionNonce, err = GenNonces(
214 WithPublicKey(ctx.pubKey),
215 WithNonceSecretKeyAux(signingKey),
216 )
217 if err != nil {
218 return nil, err
219 }
220 }
221 return ctx, nil
222 }
223 224 // combineSignerKeys is used to compute the aggregated signer key once all the
225 // signers are known.
226 func (c *Context) combineSignerKeys() error {
227 // As a sanity check, make sure the signing key is actually
228 // amongst the sit of signers.
229 var keyFound bool
230 for _, key := range c.opts.keySet {
231 if key.IsEqual(c.pubKey) {
232 keyFound = true
233 break
234 }
235 }
236 if !keyFound {
237 return ErrSignerNotInKeySet
238 }
239 240 // Now that we know that we're actually a signer, we'll
241 // generate the key hash finger print and second unique key
242 // index so we can speed up signing later.
243 c.keysHash = keyHashFingerprint(c.opts.keySet, c.shouldSort)
244 c.uniqueKeyIndex = secondUniqueKeyIndex(
245 c.opts.keySet, c.shouldSort,
246 )
247 keyAggOpts := []KeyAggOption{
248 WithKeysHash(c.keysHash),
249 WithUniqueKeyIndex(c.uniqueKeyIndex),
250 }
251 switch {
252 case c.opts.bip86Tweak:
253 keyAggOpts = append(
254 keyAggOpts, WithBIP86KeyTweak(),
255 )
256 case c.opts.taprootTweak != nil:
257 keyAggOpts = append(
258 keyAggOpts, WithTaprootKeyTweak(c.opts.taprootTweak),
259 )
260 case len(c.opts.tweaks) != 0:
261 keyAggOpts = append(keyAggOpts, WithKeyTweaks(c.opts.tweaks...))
262 }
263 // Next, we'll use this information to compute the aggregated
264 // public key that'll be used for signing in practice.
265 var err error
266 c.combinedKey, _, _, err = AggregateKeys(
267 c.opts.keySet, c.shouldSort, keyAggOpts...,
268 )
269 if err != nil {
270 return err
271 }
272 return nil
273 }
274 275 // EarlySessionNonce returns the early session nonce, if available.
276 func (c *Context) EarlySessionNonce() (*Nonces, error) {
277 if c.sessionNonce == nil {
278 return nil, ErrNoEarlyNonce
279 }
280 return c.sessionNonce, nil
281 }
282 283 // RegisterSigner allows a caller to register a signer after the context has
284 // been created. This will be used in scenarios where the total number of
285 // signers is known, but nonce exchange needs to happen before all the signers
286 // are known.
287 //
288 // A bool is returned which indicates if all the signers have been registered.
289 //
290 // NOTE: If the set of keys are not to be sorted during signing, then the
291 // ordering each key is registered with MUST match the desired ordering.
292 func (c *Context) RegisterSigner(pub *btcec.PublicKey) (bool, error) {
293 haveAllSigners := len(c.opts.keySet) == c.opts.numSigners
294 if haveAllSigners {
295 return false, ErrAlreadyHaveAllSigners
296 }
297 c.opts.keySet = append(c.opts.keySet, pub)
298 // If we have the expected number of signers at this point, then we can
299 // generate the aggregated key and other necessary information.
300 haveAllSigners = len(c.opts.keySet) == c.opts.numSigners
301 if haveAllSigners {
302 if err := c.combineSignerKeys(); chk.T(err) {
303 return false, err
304 }
305 }
306 return haveAllSigners, nil
307 }
308 309 // NumRegisteredSigners returns the total number of registered signers.
310 func (c *Context) NumRegisteredSigners() int { return len(c.opts.keySet) }
311 312 // CombinedKey returns the combined public key that will be used to generate
313 // multi-signatures against.
314 func (c *Context) CombinedKey() (*btcec.PublicKey, error) {
315 // If the caller hasn't registered all the signers at this point, then
316 // the combined key won't be available.
317 if c.combinedKey == nil {
318 return nil, ErrNotEnoughSigners
319 }
320 return c.combinedKey.FinalKey, nil
321 }
322 323 // PubKey returns the public key of the signer of this session.
324 func (c *Context) PubKey() btcec.PublicKey { return *c.pubKey }
325 326 // SigningKeys returns the set of keys used for signing.
327 func (c *Context) SigningKeys() []*btcec.PublicKey {
328 keys := make([]*btcec.PublicKey, len(c.opts.keySet))
329 copy(keys, c.opts.keySet)
330 return keys
331 }
332 333 // TaprootInternalKey returns the internal taproot key, which is the aggregated
334 // key _before_ the tweak is applied. If a taproot tweak was specified, then
335 // CombinedKey() will return the fully tweaked output key, with this method
336 // returning the internal key. If a taproot tweak wasn't specified, then this
337 // method will return an error.
338 func (c *Context) TaprootInternalKey() (*btcec.PublicKey, error) {
339 // If the caller hasn't registered all the signers at this point, then
340 // the combined key won't be available.
341 if c.combinedKey == nil {
342 return nil, ErrNotEnoughSigners
343 }
344 if c.opts.taprootTweak == nil && !c.opts.bip86Tweak {
345 return nil, ErrTaprootInternalKeyUnavailable
346 }
347 return c.combinedKey.PreTweakedKey, nil
348 }
349 350 // SessionOption is a functional option argument that allows callers to modify
351 // the musig2 signing is done within a session.
352 type SessionOption func(*sessionOptions)
353 354 // sessionOptions houses the set of functional options that can be used to
355 // modify the musig2 signing protocol.
356 type sessionOptions struct {
357 externalNonce *Nonces
358 }
359 360 // defaultSessionOptions returns the default session options.
361 func defaultSessionOptions() *sessionOptions { return &sessionOptions{} }
362 363 // WithPreGeneratedNonce allows a caller to start a session using a nonce
364 // they've generated themselves. This may be useful in protocols where all the
365 // signer keys may not be known before nonce exchange needs to occur.
366 func WithPreGeneratedNonce(nonce *Nonces) SessionOption {
367 return func(o *sessionOptions) { o.externalNonce = nonce }
368 }
369 370 // Session represents a musig2 signing session. A new instance should be
371 // created each time a multi-signature is needed. The session struct handles
372 // nonces management, incremental partial sig vitrifaction, as well as final
373 // signature combination. Errors are returned when unsafe behavior such as
374 // nonce re-use is attempted.
375 //
376 // NOTE: This struct should be used over the raw Sign API whenever possible.
377 type Session struct {
378 opts *sessionOptions
379 ctx *Context
380 localNonces *Nonces
381 pubNonces [][PubNonceSize]byte
382 combinedNonce *[PubNonceSize]byte
383 msg [32]byte
384 ourSig *PartialSignature
385 sigs []*PartialSignature
386 finalSig *schnorr.Signature
387 }
388 389 // NewSession creates a new musig2 signing session.
390 func (c *Context) NewSession(options ...SessionOption) (*Session, error) {
391 opts := defaultSessionOptions()
392 for _, opt := range options {
393 opt(opts)
394 }
395 // At this point we verify that we know of all the signers, as
396 // otherwise we can't proceed with the session. This check is intended
397 // to catch misuse of the API wherein a caller forgets to register the
398 // remaining signers if they're doing nonce generation ahead of time.
399 if len(c.opts.keySet) != c.opts.numSigners {
400 return nil, ErrNotEnoughSigners
401 }
402 // If an early nonce was specified, then we'll automatically add the
403 // corresponding session option for the caller.
404 var localNonces *Nonces
405 if c.sessionNonce != nil {
406 // Apply the early nonce to the session, and also blank out the
407 // session nonce on the context to ensure it isn't ever re-used
408 // for another session.
409 localNonces = c.sessionNonce
410 c.sessionNonce = nil
411 } else if opts.externalNonce != nil {
412 // Otherwise if there's a custom nonce passed in via the
413 // session options, then use that instead.
414 localNonces = opts.externalNonce
415 }
416 // Now that we know we have enough signers, we'll either use the caller
417 // specified nonce, or generate a fresh set.
418 var err error
419 if localNonces == nil {
420 // At this point we need to generate a fresh nonce. We'll pass
421 // in some auxiliary information to strengthen the nonce
422 // generated.
423 localNonces, err = GenNonces(
424 WithPublicKey(c.pubKey),
425 WithNonceSecretKeyAux(c.signingKey),
426 WithNonceCombinedKeyAux(c.combinedKey.FinalKey),
427 )
428 if err != nil {
429 return nil, err
430 }
431 }
432 s := &Session{
433 opts: opts,
434 ctx: c,
435 localNonces: localNonces,
436 pubNonces: make([][PubNonceSize]byte, 0, c.opts.numSigners),
437 sigs: make([]*PartialSignature, 0, c.opts.numSigners),
438 }
439 s.pubNonces = append(s.pubNonces, localNonces.PubNonce)
440 return s, nil
441 }
442 443 // PublicNonce returns the public nonce for a signer. This should be sent to
444 // other parties before signing begins, so they can compute the aggregated
445 // public nonce.
446 func (s *Session) PublicNonce() [PubNonceSize]byte {
447 return s.localNonces.PubNonce
448 }
449 450 // NumRegisteredNonces returns the total number of nonces that have been
451 // regsitered so far.
452 func (s *Session) NumRegisteredNonces() int { return len(s.pubNonces) }
453 454 // RegisterPubNonce should be called for each public nonce from the set of
455 // signers. This method returns true once all the public nonces have been
456 // accounted for.
457 func (s *Session) RegisterPubNonce(nonce [PubNonceSize]byte) (bool, error) {
458 // If we already have all the nonces, then this method was called too
459 // many times.
460 haveAllNonces := len(s.pubNonces) == s.ctx.opts.numSigners
461 if haveAllNonces {
462 return false, ErrAlreadyHaveAllNonces
463 }
464 // Add this nonce and check again if we already have tall the nonces we
465 // need.
466 s.pubNonces = append(s.pubNonces, nonce)
467 haveAllNonces = len(s.pubNonces) == s.ctx.opts.numSigners
468 // If we have all the nonces, then we can go ahead and combine them
469 // now.
470 if haveAllNonces {
471 combinedNonce, err := AggregateNonces(s.pubNonces)
472 if err != nil {
473 return false, err
474 }
475 s.combinedNonce = &combinedNonce
476 }
477 return haveAllNonces, nil
478 }
479 480 // Sign generates a partial signature for the target message, using the target
481 // context. If this method is called more than once per context, then an error
482 // is returned, as that means a nonce was re-used.
483 func (s *Session) Sign(
484 msg [32]byte,
485 signOpts ...SignOption,
486 ) (*PartialSignature, error) {
487 488 switch {
489 // If no local nonce is present, then this means we already signed, so
490 // we'll return an error to prevent nonce re-use.
491 case s.localNonces == nil:
492 return nil, ErrSigningContextReuse
493 // We also need to make sure we have the combined nonce, otherwise this
494 // funciton was called too early.
495 case s.combinedNonce == nil:
496 return nil, ErrCombinedNonceUnavailable
497 }
498 switch {
499 case s.ctx.opts.bip86Tweak:
500 signOpts = append(
501 signOpts, WithBip86SignTweak(),
502 )
503 case s.ctx.opts.taprootTweak != nil:
504 signOpts = append(
505 signOpts, WithTaprootSignTweak(s.ctx.opts.taprootTweak),
506 )
507 case len(s.ctx.opts.tweaks) != 0:
508 signOpts = append(signOpts, WithTweaks(s.ctx.opts.tweaks...))
509 }
510 partialSig, err := Sign(
511 s.localNonces.SecNonce, s.ctx.signingKey, *s.combinedNonce,
512 s.ctx.opts.keySet, msg, signOpts...,
513 )
514 // Now that we've generated our signature, we'll make sure to blank out
515 // our signing nonce.
516 s.localNonces = nil
517 if err != nil {
518 return nil, err
519 }
520 s.msg = msg
521 s.ourSig = partialSig
522 s.sigs = append(s.sigs, partialSig)
523 return partialSig, nil
524 }
525 526 // CombineSig buffers a partial signature received from a signing party. The
527 // method returns true once all the signatures are available, and can be
528 // combined into the final signature.
529 func (s *Session) CombineSig(sig *PartialSignature) (bool, error) {
530 // First check if we already have all the signatures we need. We
531 // already accumulated our own signature when we generated the sig.
532 haveAllSigs := len(s.sigs) == len(s.ctx.opts.keySet)
533 if haveAllSigs {
534 return false, ErrAlredyHaveAllSigs
535 }
536 // TODO(roasbeef): incremental check for invalid sig, or just detect at
537 // the very end?
538 //
539 // Accumulate this sig, and check again if we have all the sigs we
540 // need.
541 s.sigs = append(s.sigs, sig)
542 haveAllSigs = len(s.sigs) == len(s.ctx.opts.keySet)
543 // If we have all the signatures, then we can combine them all into the
544 // final signature.
545 if haveAllSigs {
546 var combineOpts []CombineOption
547 switch {
548 case s.ctx.opts.bip86Tweak:
549 combineOpts = append(
550 combineOpts, WithBip86TweakedCombine(
551 s.msg, s.ctx.opts.keySet,
552 s.ctx.shouldSort,
553 ),
554 )
555 case s.ctx.opts.taprootTweak != nil:
556 combineOpts = append(
557 combineOpts, WithTaprootTweakedCombine(
558 s.msg, s.ctx.opts.keySet,
559 s.ctx.opts.taprootTweak, s.ctx.shouldSort,
560 ),
561 )
562 case len(s.ctx.opts.tweaks) != 0:
563 combineOpts = append(
564 combineOpts, WithTweakedCombine(
565 s.msg, s.ctx.opts.keySet,
566 s.ctx.opts.tweaks, s.ctx.shouldSort,
567 ),
568 )
569 }
570 finalSig := CombineSigs(s.ourSig.R, s.sigs, combineOpts...)
571 // We'll also verify the signature at this point to ensure it's
572 // valid.
573 //
574 // TODO(roasbef): allow skipping?
575 if !finalSig.Verify(s.msg[:], s.ctx.combinedKey.FinalKey) {
576 return false, ErrFinalSigInvalid
577 }
578 s.finalSig = finalSig
579 }
580 return haveAllSigs, nil
581 }
582 583 // FinalSig returns the final combined multi-signature, if present.
584 func (s *Session) FinalSig() *schnorr.Signature { return s.finalSig }
585