nonces.go raw

   1  // Copyright 2013-2022 The btcsuite developers
   2  
   3  package musig2
   4  
   5  import (
   6  	"bytes"
   7  	"crypto/rand"
   8  	"encoding/binary"
   9  	"errors"
  10  	"io"
  11  
  12  	"next.orly.dev/pkg/nostr/crypto/ec"
  13  	"next.orly.dev/pkg/nostr/crypto/ec/chainhash"
  14  	"next.orly.dev/pkg/nostr/crypto/ec/schnorr"
  15  	"next.orly.dev/pkg/lol/chk"
  16  )
  17  
  18  const (
  19  	// PubNonceSize is the size of the public nonces. Each public nonce is
  20  	// serialized the full compressed encoding, which uses 32 bytes for each
  21  	// nonce.
  22  	PubNonceSize = 66
  23  	// SecNonceSize is the size of the secret nonces for musig2. The secret
  24  	// nonces are the corresponding secret keys to the public nonce points.
  25  	SecNonceSize = 97
  26  )
  27  
  28  var (
  29  	// NonceAuxTag is the tag used to optionally mix in the secret key with
  30  	// the set of aux randomness.
  31  	NonceAuxTag = []byte("MuSig/aux")
  32  	// NonceGenTag is used to generate the value (from a set of required an
  33  	// optional field) that will be used as the part of the secret nonce.
  34  	NonceGenTag = []byte("MuSig/nonce")
  35  	byteOrder   = binary.BigEndian
  36  	// ErrPubkeyInvalid is returned when the pubkey of the WithPublicKey
  37  	// option is not passed or of invalid length.
  38  	ErrPubkeyInvalid = errors.New("nonce generation requires a valid pubkey")
  39  )
  40  
  41  // zeroSecNonce is a secret nonce that's all zeroes. This is used to check that
  42  // we're not attempting to re-use a nonce, and also protect callers from it.
  43  var zeroSecNonce [SecNonceSize]byte
  44  
  45  // Nonces holds the public and secret nonces required for musig2.
  46  //
  47  // TODO(roasbeef): methods on this to help w/ parsing, etc?
  48  type Nonces struct {
  49  	// PubNonce holds the two 33-byte compressed encoded points that serve
  50  	// as the public set of nonces.
  51  	PubNonce [PubNonceSize]byte
  52  	// SecNonce holds the two 32-byte scalar values that are the secret
  53  	// keys to the two public nonces.
  54  	SecNonce [SecNonceSize]byte
  55  }
  56  
  57  // secNonceToPubNonce takes our two secrete nonces, and produces their two
  58  // corresponding EC points, serialized in compressed format.
  59  func secNonceToPubNonce(secNonce [SecNonceSize]byte) [PubNonceSize]byte {
  60  	var k1Mod, k2Mod btcec.ModNScalar
  61  	k1Mod.SetByteSlice(secNonce[:btcec.SecKeyBytesLen])
  62  	k2Mod.SetByteSlice(secNonce[btcec.SecKeyBytesLen:])
  63  	var r1, r2 btcec.JacobianPoint
  64  	btcec.ScalarBaseMultNonConst(&k1Mod, &r1)
  65  	btcec.ScalarBaseMultNonConst(&k2Mod, &r2)
  66  	// Next, we'll convert the key in jacobian format to a normal public
  67  	// key expressed in affine coordinates.
  68  	r1.ToAffine()
  69  	r2.ToAffine()
  70  	r1Pub := btcec.NewPublicKey(&r1.X, &r1.Y)
  71  	r2Pub := btcec.NewPublicKey(&r2.X, &r2.Y)
  72  	var pubNonce [PubNonceSize]byte
  73  	// The public nonces are serialized as: R1 || R2, where both keys are
  74  	// serialized in compressed format.
  75  	copy(pubNonce[:], r1Pub.SerializeCompressed())
  76  	copy(
  77  		pubNonce[btcec.PubKeyBytesLenCompressed:],
  78  		r2Pub.SerializeCompressed(),
  79  	)
  80  	return pubNonce
  81  }
  82  
  83  // NonceGenOption is a function option that allows callers to modify how nonce
  84  // generation happens.
  85  type NonceGenOption func(*nonceGenOpts)
  86  
  87  // nonceGenOpts is the set of options that control how nonce generation
  88  // happens.
  89  type nonceGenOpts struct {
  90  	// randReader is what we'll use to generate a set of random bytes. If
  91  	// unspecified, then the normal crypto/rand rand.Read method will be
  92  	// used in place.
  93  	randReader io.Reader
  94  	// publicKey is the mandatory public key that will be mixed into the nonce
  95  	// generation.
  96  	publicKey []byte
  97  	// secretKey is an optional argument that's used to further augment the
  98  	// generated nonce by xor'ing it with this secret key.
  99  	secretKey []byte
 100  	// combinedKey is an optional argument that if specified, will be
 101  	// combined along with the nonce generation.
 102  	combinedKey []byte
 103  	// msg is an optional argument that will be mixed into the nonce
 104  	// derivation algorithm.
 105  	msg []byte
 106  	// auxInput is an optional argument that will be mixed into the nonce
 107  	// derivation algorithm.
 108  	auxInput []byte
 109  }
 110  
 111  // cryptoRandAdapter is an adapter struct that allows us to pass in the package
 112  // level Read function from crypto/rand into a context that accepts an
 113  // io.Reader.
 114  type cryptoRandAdapter struct{}
 115  
 116  // Read implements the io.Reader interface for the crypto/rand package.  By
 117  // default, we always use the crypto/rand reader, but the caller is able to
 118  // specify their own generation, which can be useful for deterministic tests.
 119  func (c *cryptoRandAdapter) Read(p []byte) (n int, err error) {
 120  	return rand.Read(p)
 121  }
 122  
 123  // defaultNonceGenOpts returns the default set of nonce generation options.
 124  func defaultNonceGenOpts() *nonceGenOpts {
 125  	return &nonceGenOpts{randReader: &cryptoRandAdapter{}}
 126  }
 127  
 128  // WithCustomRand allows a caller to use a custom random number generator in
 129  // place for crypto/rand. This should only really be used to generate
 130  // determinstic tests.
 131  func WithCustomRand(r io.Reader) NonceGenOption {
 132  	return func(o *nonceGenOpts) { o.randReader = r }
 133  }
 134  
 135  // WithPublicKey is the mandatory public key that will be mixed into the nonce
 136  // generation.
 137  func WithPublicKey(pubKey *btcec.PublicKey) NonceGenOption {
 138  	return func(o *nonceGenOpts) {
 139  		o.publicKey = pubKey.SerializeCompressed()
 140  	}
 141  }
 142  
 143  // WithNonceSecretKeyAux allows a caller to optionally specify a secret key
 144  // that should be used to augment the randomness used to generate the nonces.
 145  func WithNonceSecretKeyAux(secKey *btcec.SecretKey) NonceGenOption {
 146  	return func(o *nonceGenOpts) { o.secretKey = secKey.Serialize() }
 147  }
 148  
 149  var WithNoncePrivateKeyAux = WithNonceSecretKeyAux
 150  
 151  // WithNonceCombinedKeyAux allows a caller to optionally specify the combined
 152  // key used in this signing session to further augment the randomness used to
 153  // generate nonces.
 154  func WithNonceCombinedKeyAux(combinedKey *btcec.PublicKey) NonceGenOption {
 155  	return func(o *nonceGenOpts) {
 156  		o.combinedKey = schnorr.SerializePubKey(combinedKey)
 157  	}
 158  }
 159  
 160  // WithNonceMessageAux allows a caller to optionally specify a message to be
 161  // mixed into the randomness generated to create the nonce.
 162  func WithNonceMessageAux(msg [32]byte) NonceGenOption {
 163  	return func(o *nonceGenOpts) { o.msg = msg[:] }
 164  }
 165  
 166  // WithNonceAuxInput is a set of auxiliary randomness, similar to BIP 340 that
 167  // can be used to further augment the nonce generation process.
 168  func WithNonceAuxInput(aux []byte) NonceGenOption {
 169  	return func(o *nonceGenOpts) { o.auxInput = aux }
 170  }
 171  
 172  // withCustomOptions allows a caller to pass a complete set of custom
 173  // nonceGenOpts, without needing to create custom and checked structs such as
 174  // *btcec.SecretKey. This is mainly used to match the testcases provided by
 175  // the MuSig2 BIP.
 176  func withCustomOptions(customOpts nonceGenOpts) NonceGenOption {
 177  	return func(o *nonceGenOpts) {
 178  		o.randReader = customOpts.randReader
 179  		o.secretKey = customOpts.secretKey
 180  		o.combinedKey = customOpts.combinedKey
 181  		o.auxInput = customOpts.auxInput
 182  		o.msg = customOpts.msg
 183  		o.publicKey = customOpts.publicKey
 184  	}
 185  }
 186  
 187  // lengthWriter is a function closure that allows a caller to control how the
 188  // length prefix of a byte slice is written.
 189  //
 190  // TODO(roasbeef): use type params once we bump repo version
 191  type lengthWriter func(w io.Writer, b []byte) error
 192  
 193  // uint8Writer is an implementation of lengthWriter that writes the length of
 194  // the byte slice using 1 byte.
 195  func uint8Writer(w io.Writer, b []byte) error {
 196  	return binary.Write(w, byteOrder, uint8(len(b)))
 197  }
 198  
 199  // uint32Writer is an implementation of lengthWriter that writes the length of
 200  // the byte slice using 4 bytes.
 201  func uint32Writer(w io.Writer, b []byte) error {
 202  	return binary.Write(w, byteOrder, uint32(len(b)))
 203  }
 204  
 205  // uint32Writer is an implementation of lengthWriter that writes the length of
 206  // the byte slice using 8 bytes.
 207  func uint64Writer(w io.Writer, b []byte) error {
 208  	return binary.Write(w, byteOrder, uint64(len(b)))
 209  }
 210  
 211  // writeBytesPrefix is used to write out: len(b) || b, to the passed io.Writer.
 212  // The lengthWriter function closure is used to allow the caller to specify the
 213  // precise byte packing of the length.
 214  func writeBytesPrefix(w io.Writer, b []byte, lenWriter lengthWriter) error {
 215  	// Write out the length of the byte first, followed by the set of bytes
 216  	// itself.
 217  	if err := lenWriter(w, b); chk.T(err) {
 218  		return err
 219  	}
 220  	if _, err := w.Write(b); chk.T(err) {
 221  		return err
 222  	}
 223  	return nil
 224  }
 225  
 226  // genNonceAuxBytes writes out the full byte string used to derive a secret
 227  // nonce based on some initial randomness as well as the series of optional
 228  // fields. The byte string used for derivation is:
 229  //   - tagged_hash("MuSig/nonce", rand || len(pk) || pk ||
 230  //     len(aggpk) || aggpk || m_prefixed || len(in) || in || i).
 231  //
 232  // where i is the ith secret nonce being generated and m_prefixed is:
 233  //   - bytes(1, 0) if the message is blank
 234  //   - bytes(1, 1) || bytes(8, len(m)) || m if the message is present.
 235  func genNonceAuxBytes(
 236  	rand []byte, pubkey []byte, i int,
 237  	opts *nonceGenOpts,
 238  ) (*chainhash.Hash, error) {
 239  
 240  	var w bytes.Buffer
 241  	// First, write out the randomness generated in the prior step.
 242  	if _, err := w.Write(rand); chk.T(err) {
 243  		return nil, err
 244  	}
 245  	// Next, we'll write out: len(pk) || pk
 246  	err := writeBytesPrefix(&w, pubkey, uint8Writer)
 247  	if err != nil {
 248  		return nil, err
 249  	}
 250  	// Next, we'll write out: len(aggpk) || aggpk.
 251  	err = writeBytesPrefix(&w, opts.combinedKey, uint8Writer)
 252  	if err != nil {
 253  		return nil, err
 254  	}
 255  	switch {
 256  	// If the message isn't present, then we'll just write out a single
 257  	// uint8 of a zero byte: m_prefixed = bytes(1, 0).
 258  	case opts.msg == nil:
 259  		if _, err := w.Write([]byte{0x00}); chk.T(err) {
 260  			return nil, err
 261  		}
 262  	// Otherwise, we'll write a single byte of 0x01 with a 1 byte length
 263  	// prefix, followed by the message itself with an 8 byte length prefix:
 264  	// m_prefixed = bytes(1, 1) || bytes(8, len(m)) || m.
 265  	case len(opts.msg) == 0:
 266  		fallthrough
 267  	default:
 268  		if _, err := w.Write([]byte{0x01}); chk.T(err) {
 269  			return nil, err
 270  		}
 271  		err = writeBytesPrefix(&w, opts.msg, uint64Writer)
 272  		if err != nil {
 273  			return nil, err
 274  		}
 275  	}
 276  	// Finally we'll write out the auxiliary input.
 277  	err = writeBytesPrefix(&w, opts.auxInput, uint32Writer)
 278  	if err != nil {
 279  		return nil, err
 280  	}
 281  	// Next we'll write out the interaction/index number which will
 282  	// uniquely generate two nonces given the rest of the possibly static
 283  	// parameters.
 284  	if err := binary.Write(&w, byteOrder, uint8(i)); chk.T(err) {
 285  		return nil, err
 286  	}
 287  	// With the message buffer complete, we'll now derive the tagged hash
 288  	// using our set of params.
 289  	return chainhash.TaggedHash(NonceGenTag, w.Bytes()), nil
 290  }
 291  
 292  // GenNonces generates the secret nonces, as well as the public nonces which
 293  // correspond to an EC point generated using the secret nonce as a secret key.
 294  func GenNonces(options ...NonceGenOption) (*Nonces, error) {
 295  	opts := defaultNonceGenOpts()
 296  	for _, opt := range options {
 297  		opt(opts)
 298  	}
 299  	// We require the pubkey option.
 300  	if opts.publicKey == nil || len(opts.publicKey) != 33 {
 301  		return nil, ErrPubkeyInvalid
 302  	}
 303  	// First, we'll start out by generating 32 random bytes drawn from our
 304  	// CSPRNG.
 305  	var randBytes [32]byte
 306  	if _, err := opts.randReader.Read(randBytes[:]); chk.T(err) {
 307  		return nil, err
 308  	}
 309  	// If the options contain a secret key, we XOR it with with the tagged
 310  	// random bytes.
 311  	if len(opts.secretKey) == 32 {
 312  		taggedHash := chainhash.TaggedHash(NonceAuxTag, randBytes[:])
 313  
 314  		for i := 0; i < chainhash.HashSize; i++ {
 315  			randBytes[i] = opts.secretKey[i] ^ taggedHash[i]
 316  		}
 317  	}
 318  	// Using our randomness, pubkey and the set of optional params, generate our
 319  	// two secret nonces: k1 and k2.
 320  	k1, err := genNonceAuxBytes(randBytes[:], opts.publicKey, 0, opts)
 321  	if err != nil {
 322  		return nil, err
 323  	}
 324  	k2, err := genNonceAuxBytes(randBytes[:], opts.publicKey, 1, opts)
 325  	if err != nil {
 326  		return nil, err
 327  	}
 328  	var k1Mod, k2Mod btcec.ModNScalar
 329  	k1Mod.SetBytes((*[32]byte)(k1))
 330  	k2Mod.SetBytes((*[32]byte)(k2))
 331  	// The secret nonces are serialized as the concatenation of the two 32
 332  	// byte secret nonce values and the pubkey.
 333  	var nonces Nonces
 334  	k1Mod.PutBytesUnchecked(nonces.SecNonce[:])
 335  	k2Mod.PutBytesUnchecked(nonces.SecNonce[btcec.SecKeyBytesLen:])
 336  	copy(nonces.SecNonce[btcec.SecKeyBytesLen*2:], opts.publicKey)
 337  	// Next, we'll generate R_1 = k_1*G and R_2 = k_2*G. Along the way we
 338  	// need to map our nonce values into mod n scalars so we can work with
 339  	// the btcec API.
 340  	nonces.PubNonce = secNonceToPubNonce(nonces.SecNonce)
 341  	return &nonces, nil
 342  }
 343  
 344  // AggregateNonces aggregates the set of a pair of public nonces for each party
 345  // into a single aggregated nonces to be used for multi-signing.
 346  func AggregateNonces(pubNonces [][PubNonceSize]byte) (
 347  	[PubNonceSize]byte,
 348  	error,
 349  ) {
 350  
 351  	// combineNonces is a helper function that aggregates (adds) up a
 352  	// series of nonces encoded in compressed format. It uses a slicing
 353  	// function to extra 33 bytes at a time from the packed 2x public
 354  	// nonces.
 355  	type nonceSlicer func([PubNonceSize]byte) []byte
 356  	combineNonces := func(slicer nonceSlicer) (btcec.JacobianPoint, error) {
 357  		// Convert the set of nonces into jacobian coordinates we can
 358  		// use to accumulate them all into each other.
 359  		pubNonceJs := make([]*btcec.JacobianPoint, len(pubNonces))
 360  		for i, pubNonceBytes := range pubNonces {
 361  			// Using the slicer, extract just the bytes we need to
 362  			// decode.
 363  			var nonceJ btcec.JacobianPoint
 364  			nonceJ, err := btcec.ParseJacobian(slicer(pubNonceBytes))
 365  			if err != nil {
 366  				return btcec.JacobianPoint{}, err
 367  			}
 368  			pubNonceJs[i] = &nonceJ
 369  		}
 370  		// Now that we have the set of complete nonces, we'll aggregate
 371  		// them: R = R_i + R_i+1 + ... + R_i+n.
 372  		var aggregateNonce btcec.JacobianPoint
 373  		for _, pubNonceJ := range pubNonceJs {
 374  			btcec.AddNonConst(
 375  				&aggregateNonce, pubNonceJ, &aggregateNonce,
 376  			)
 377  		}
 378  		aggregateNonce.ToAffine()
 379  		return aggregateNonce, nil
 380  	}
 381  	// The final nonce public nonce is actually two nonces, one that
 382  	// aggregate the first nonce of all the parties, and the other that
 383  	// aggregates the second nonce of all the parties.
 384  	var finalNonce [PubNonceSize]byte
 385  	combinedNonce1, err := combineNonces(
 386  		func(n [PubNonceSize]byte) []byte {
 387  			return n[:btcec.PubKeyBytesLenCompressed]
 388  		},
 389  	)
 390  	if err != nil {
 391  		return finalNonce, err
 392  	}
 393  	combinedNonce2, err := combineNonces(
 394  		func(n [PubNonceSize]byte) []byte {
 395  			return n[btcec.PubKeyBytesLenCompressed:]
 396  		},
 397  	)
 398  	if err != nil {
 399  		return finalNonce, err
 400  	}
 401  	copy(finalNonce[:], btcec.JacobianToByteSlice(combinedNonce1))
 402  	copy(
 403  		finalNonce[btcec.PubKeyBytesLenCompressed:],
 404  		btcec.JacobianToByteSlice(combinedNonce2),
 405  	)
 406  	return finalNonce, nil
 407  }
 408