generateNonce method
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),
);
}