aggregateSign function

Signature aggregateSign(
  1. List<PrivateKey> privateKeys,
  2. List<int> message
)

Implementation

Signature aggregateSign(List<PrivateKey> privateKeys, List<int> message) {
  if (privateKeys.isEmpty) {
    throw SchnorrException(
        'privateKeys must be an array with one or more elements');
  }

  var k0s = List<BigInt>.filled(privateKeys.length, BigInt.zero);
  var P = AffinePoint();
  var R = AffinePoint();
  var curve = privateKeys[0].curve;
  var privMap = privateKeys.asMap();

  for (final i in privMap.keys) {
    if (privateKeys[i].curve != curve) {
      throw SchnorrException('privatekeys must be on the same curve');
    }

    if (privateKeys[i].D < BigInt.one ||
        privateKeys[i].D > curve.n - BigInt.one) {
      throw SchnorrException(
          'the private key must be an integer in the range 1..n-1');
    }

    var d = intToByte(curve, privateKeys[i].D);
    var k0i = deterministicGetK0(curve, d, message);

    var Ri = curve.scalarBaseMul(intToByte(curve, k0i));
    var Pi = curve.scalarBaseMul(d);

    k0s[i] = k0i;

    R = curve.add(R, Ri);
    P = curve.add(P, Pi);
  }

  var rX = intToByte(curve, R.X);
  var e = getE(curve, P, rX, message);
  var s = BigInt.zero;

  for (final j in k0s.asMap().keys) {
    var k = getK(curve, R, k0s[j]);
    k = k + (e * privateKeys[j].D);
    s = s + k;
  }

  return Signature.fromRS(R.X, s % curve.n);
}