PartialSig.sign constructor
PartialSig.sign({
- required Uint8List secretKey,
- required List<
Uint8List> secretNonces, - required NonceSession session,
BIP-327 Sign:
- Aggregate nonces -> R, compute coefficient b.
- e = H("BIP0340/challenge", R_x || Q_x || msg) mod n.
- k = k1 + b*k2 (mod n); negate if R has odd y.
- d = a * sk (mod n); negate if Q has odd y.
- s = k + e*d (mod n).
Implementation
factory PartialSig.sign({
required Uint8List secretKey,
required List<Uint8List> secretNonces,
required NonceSession session,
}) {
if (secretNonces.length != 2) {
throw ArgumentError('Expected 2 secret nonces (k1, k2)');
}
final pubKeyBytes = VaultKeeper.vault.curve.derivePublicKey(secretKey);
final signerPubKey = PublicKey(pubKeyBytes);
final aggR = session.aggregateNonces();
final rPoint = ecBytesToPoint(aggR);
EcPoint aggR1 = EcPoint.infinity();
EcPoint aggR2 = EcPoint.infinity();
for (final nonce in session.nonces) {
aggR1 = ecPointAdd(aggR1, ecBytesToPoint(nonce.r1));
aggR2 = ecPointAdd(aggR2, ecBytesToPoint(nonce.r2));
}
// BIP-327 sec. GetSessionValues: noncecoef DOES include the message (b is
// hashed over aggnonce || Q_x || msg).
final aggR1Bytes = aggR1.isInfinity ? Uint8List(33) : ecPointToBytes(aggR1, compressed: true);
final aggR2Bytes = aggR2.isInfinity ? Uint8List(33) : ecPointToBytes(aggR2, compressed: true);
final bInput = concatBytes(
[aggR1Bytes, aggR2Bytes, session.aggKey.xOnly, session.message]);
final bHash = taggedHash('MuSig/noncecoef', bInput);
final b = bytesToBigInt(bHash) % secp256k1N;
// e = H("BIP0340/challenge", R_x || Q_x || msg) mod n
final rX = bigIntToBytes(rPoint.x, 32);
final challengeInput = concatBytes([
rX,
session.aggKey.xOnly,
session.message,
]);
final eHash = taggedHash('BIP0340/challenge', challengeInput);
final e = bytesToBigInt(eHash) % secp256k1N;
// k = k1 + b*k2; negate if R has odd y
final k1 = bytesToBigInt(secretNonces[0]);
final k2 = bytesToBigInt(secretNonces[1]);
BigInt k = (k1 + b * k2) % secp256k1N;
if (!rPoint.y.isEven) {
k = (secp256k1N - k) % secp256k1N;
}
// d = a * sk; negate if Q has odd y
final aBytes = session.aggKey.coefficient(signerPubKey);
final a = bytesToBigInt(aBytes);
BigInt d = (a * bytesToBigInt(secretKey)) % secp256k1N;
if (!session.aggKey.yIsEven) {
d = (secp256k1N - d) % secp256k1N;
}
// s = k + e * d (mod n)
final s = (k + e * d) % secp256k1N;
return PartialSig(
signerKey: signerPubKey,
partialS: bigIntToBytes(s, 32),
);
}