sign static method
List<int>
sign({
- required List<
int> secnonce, - required List<
int> sk, - required MuSig2Session session,
Generates a MuSig2 partial signature
Implementation
static List<int> sign(
{required List<int> secnonce,
required List<int> sk,
required MuSig2Session session}) {
if (secnonce.length != MuSig2Const.secnoncelength) {
throw MuSig2Exception("Invalid secrent nonce length.", details: {
"expected": MuSig2Const.secnoncelength,
"length": secnonce.length
});
}
final values = MuSig2Utils.decodeSession(session);
BigInt k1 = BigintUtils.fromBytes(
secnonce.sublist(0, MuSig2Const.xOnlyBytesLength));
BigInt k2 = BigintUtils.fromBytes(secnonce.sublist(
MuSig2Const.xOnlyBytesLength, MuSig2Const.xOnlyBytesLength * 2));
if (k1 <= BigInt.zero || k1 >= MuSig2Const.order) {
throw MuSig2Exception("Invalid secret nonce.");
}
if (k2 <= BigInt.zero || k2 >= MuSig2Const.order) {
throw MuSig2Exception("Invalid secret nonce.");
}
BigInt kE1 = k1;
BigInt kE2 = k2;
if (values.r.isOdd) {
kE1 = MuSig2Const.order - k1;
kE2 = MuSig2Const.order - k2;
}
BigInt d = BigintUtils.fromBytes(sk);
if (d <= BigInt.zero || d >= MuSig2Const.order) {
throw MuSig2Exception("Second secnonce is invalid.");
}
final p = MuSig2Const.generator * d;
final pkBytes = p.toBytes();
final pkOffset = MuSig2Const.xOnlyBytesLength * 2;
if (!BytesUtils.bytesEqual(
secnonce.sublist(
pkOffset, pkOffset + EcdsaKeysConst.pubKeyCompressedByteLen),
pkBytes)) {
throw MuSig2Exception(
"invalid secret key. nonce public key does not match with secret pub key.");
}
final a = MuSig2Utils.getSessionKeyAggCoeff(session: session, pk: p);
BigInt g = BigInt.one;
if (values.publicKey.isOdd) {
g = MuSig2Const.order - BigInt.one;
}
d = g * values.gacc * d % MuSig2Const.order;
final s = (kE1 + values.b * kE2 + values.e * a * d) % MuSig2Const.order;
final sig = BigintUtils.toBytes(s, length: BigintUtils.bitlengthInBytes(s))
.toImutableBytes;
final rS1 = MuSig2Const.generator * k1;
final rS2 = MuSig2Const.generator * k2;
final List<int> pubnonce = [...rS1.toBytes(), ...rS2.toBytes()];
final verify = partialSigVerify(
signature: sig, pubnonce: pubnonce, pk: pkBytes, session: session);
if (!verify) {
throw MuSig2Exception("Generated signature does not pass verification.");
}
return sig;
}