batchVerify function
Implementation
bool batchVerify(List<PublicKey> publicKeys, List<List<int>> messages,
List<Signature> signatures) {
if (publicKeys.isEmpty) {
throw SchnorrException(
'publicKeys must be an array with one or more elements');
}
if (messages.isEmpty) {
throw SchnorrException(
'messages must be an array with one or more elements');
}
if (signatures.isEmpty) {
throw SchnorrException(
'signatures must be an array with one or more elements');
}
if (publicKeys.length != messages.length ||
messages.length != signatures.length) {
throw SchnorrException(
'all parameters must be an array with the same length');
}
var curve = publicKeys[0].curve;
var ls = BigInt.zero;
var a = BigInt.one;
var rs = AffinePoint();
var big7 = BigInt.from(7);
var result = false;
for (final i in signatures.asMap().keys) {
var signature = signatures[i];
var publicKey = publicKeys[i];
var message = messages[i];
if (curve != publicKey.curve) {
throw SchnorrException('publickeys must be on the same curve');
}
if (!curve.isOnCurve(publicKey)) {
throw SchnorrException('publickey is not on the curve');
}
var r = signature.R;
if (r >= curve.p) {
throw SchnorrException('r is larger than or equal to field size');
}
var s = signature.S;
if (s >= curve.n) {
throw SchnorrException('s is larger than or equal to curve order');
}
var e = getE(curve, publicKey, intToByte(curve, r), message);
var r2 = r.pow(3);
r2 = r2 + big7;
r2 = r2 % curve.p;
var c = r2;
var exp = curve.p + BigInt.one;
exp = exp >> 2;
var y = c.modPow(exp, curve.p);
if (y.modPow(BigInt.two, curve.p) != c) {
break;
}
var R = AffinePoint.fromXY(r, y);
if (i != 0) {
a = deterministicGetRandA(curve);
}
var aR = curve.scalarMul(R, intToByte(curve, a));
var ae = (a * e);
var aeHex = ae.toRadixString(16).padLeft((ae.bitLength + 7) >> 3, '0');
var aeBytes = List<int>.generate((ae.bitLength + 7) >> 3,
(index) => int.parse(aeHex.substring(2 * index, 2 * index + 2)));
var aeP = curve.scalarMul(publicKey, aeBytes);
rs = curve.add(rs, aR);
rs = curve.add(rs, aeP);
s = s * a;
ls = ls + s;
}
var G = curve.scalarBaseMul(intToByte(curve, ls % curve.n));
if (G != rs) {
return false;
}
return result;
}