generateNonce method

NoncePair generateNonce(
  1. Uint8List secretKey
)

Generate a nonce pair per BIP-327 NonceGen.

Secret nonce scalars (k1, k2) can be re-derived from the same inputs via deriveSecretScalars.

Implementation

NoncePair generateNonce(Uint8List secretKey) {
  // BIP-327 NonceGen:
  // rand' = H("MuSig/nonce", rand || sk || pk || aggpk || msg)
  // k1 = int(H("MuSig/aux", rand')) mod n
  // k2 = int(H("MuSig/aux", rand' || 0x01)) mod n
  // R1 = k1*G, R2 = k2*G

  final rand = generateSecureBytes(32);
  final pk = VaultKeeper.vault.curve.derivePublicKey(secretKey);

  final auxInput = concatBytes([
    rand,
    secretKey,
    pk,
    aggKey.xOnly,
    message,
  ]);
  final randPrime = taggedHash('MuSig/nonce', auxInput);

  final k1Hash = taggedHash('MuSig/aux', randPrime);
  final k1 = bytesToBigInt(k1Hash) % secp256k1N;
  if (k1 == BigInt.zero) {
    throw StateError('Nonce generation produced zero k1');
  }

  final k2Input = concatBytes([randPrime, Uint8List.fromList([0x01])]);
  final k2Hash = taggedHash('MuSig/aux', k2Input);
  final k2 = bytesToBigInt(k2Hash) % secp256k1N;
  if (k2 == BigInt.zero) {
    throw StateError('Nonce generation produced zero k2');
  }

  final r1Point = ecScalarMult(k1, secp256k1G);
  final r2Point = ecScalarMult(k2, secp256k1G);

  return NoncePair(
    r1: ecPointToBytes(r1Point, compressed: true),
    r2: ecPointToBytes(r2Point, compressed: true),
  );
}