sign static method

List<int> sign({
  1. required List<int> secnonce,
  2. required List<int> sk,
  3. 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;
}