sign method
List<int>
sign({
- required List<
int> secnonce, - required List<
int> sk, - required MuSig2Session session,
override
Generates a MuSig2 partial signature
Implementation
@override
List<int> sign({
required List<int> secnonce,
required List<int> sk,
required MuSig2Session session,
}) {
if (secnonce.length != MuSig2Constants.secnoncelength) {
throw ArgumentException.invalidOperationArguments(
"sign",
name: "secnonce",
reason: "Invalid secret nonce bytes length.",
expecteLen: MuSig2Constants.secnoncelength,
);
}
final values = MuSig2Utils.decodeSession(session);
BigInt k1 = BigintUtils.fromBytes(
secnonce.sublist(0, MuSig2Constants.xOnlyBytesLength),
);
BigInt k2 = BigintUtils.fromBytes(
secnonce.sublist(
MuSig2Constants.xOnlyBytesLength,
MuSig2Constants.xOnlyBytesLength * 2,
),
);
if (k1 <= BigInt.zero || k1 >= MuSig2Constants.order) {
throw ArgumentException.invalidOperationArguments(
"sign",
name: "secnonce",
reason: "Invalid secret nonce.",
);
}
if (k2 <= BigInt.zero || k2 >= MuSig2Constants.order) {
throw ArgumentException.invalidOperationArguments(
"sign",
name: "secnonce",
reason: "Invalid secret nonce.",
);
}
BigInt kE1 = k1;
BigInt kE2 = k2;
if (values.r.isOdd) {
kE1 = MuSig2Constants.order - k1;
kE2 = MuSig2Constants.order - k2;
}
BigInt d = BigintUtils.fromBytes(sk);
if (d <= BigInt.zero || d >= MuSig2Constants.order) {
throw ArgumentException.invalidOperationArguments(
"sign",
name: "sk",
reason: "Invalid secret key.",
);
}
final p = MuSig2Constants.generator * d;
final pkBytes = p.toBytes();
final pkOffset = MuSig2Constants.xOnlyBytesLength * 2;
if (!BytesUtils.bytesEqual(
secnonce.sublist(
pkOffset,
pkOffset + EcdsaKeysConst.pubKeyCompressedByteLen,
),
pkBytes,
)) {
throw ArgumentException.invalidOperationArguments(
"sign",
reason: "Missmatch between secret key and public key.",
);
}
final a = MuSig2Utils.getSessionKeyAggCoeff(session: session, pk: p);
BigInt g = BigInt.one;
if (values.publicKey.isOdd) {
g = MuSig2Constants.order - BigInt.one;
}
d = g * values.gaccAsInteger * d % MuSig2Constants.order;
final s =
(kE1 + values.bAsInteger * kE2 + values.eAsInteger * a * d) %
MuSig2Constants.order;
final sig = BigintUtils.toBytes(s).toImutableBytes;
final rS1 = MuSig2Constants.generator * k1;
final rS2 = MuSig2Constants.generator * k2;
final List<int> pubnonce = [...rS1.toBytes(), ...rS2.toBytes()];
final verify = partialSigVerify(
signature: sig,
pubnonce: pubnonce,
pk: pkBytes,
session: session,
);
if (!verify) {
throw CryptoSignException.signatureVerificationFailed;
}
return sig;
}