Function verifyBatch [src]
Verify several signatures in a single operation, much faster than verifying signatures one-by-one
Prototype
pub fn verifyBatch(comptime count: usize, signature_batch: [count]BatchElement) (SignatureVerificationError || IdentityElementError || WeakPublicKeyError || EncodingError || NonCanonicalError)!void
Parameters
count: usize
signature_batch: [count]BatchElement
Source
pub fn verifyBatch(comptime count: usize, signature_batch: [count]BatchElement) (SignatureVerificationError || IdentityElementError || WeakPublicKeyError || EncodingError || NonCanonicalError)!void {
var r_batch: [count]CompressedScalar = undefined;
var s_batch: [count]CompressedScalar = undefined;
var a_batch: [count]Curve = undefined;
var expected_r_batch: [count]Curve = undefined;
for (signature_batch, 0..) |signature, i| {
const r = signature.sig.r;
const s = signature.sig.s;
try Curve.scalar.rejectNonCanonical(s);
const a = try Curve.fromBytes(signature.public_key.bytes);
try a.rejectIdentity();
try Curve.rejectNonCanonical(r);
const expected_r = try Curve.fromBytes(r);
try expected_r.rejectIdentity();
expected_r_batch[i] = expected_r;
r_batch[i] = r;
s_batch[i] = s;
a_batch[i] = a;
}
var hram_batch: [count]Curve.scalar.CompressedScalar = undefined;
for (signature_batch, 0..) |signature, i| {
var h = Sha512.init(.{});
h.update(&r_batch[i]);
h.update(&signature.public_key.bytes);
h.update(signature.msg);
var hram64: [Sha512.digest_length]u8 = undefined;
h.final(&hram64);
hram_batch[i] = Curve.scalar.reduce64(hram64);
}
var z_batch: [count]Curve.scalar.CompressedScalar = undefined;
for (&z_batch) |*z| {
crypto.random.bytes(z[0..16]);
@memset(z[16..], 0);
}
var zs_sum = Curve.scalar.zero;
for (z_batch, 0..) |z, i| {
const zs = Curve.scalar.mul(z, s_batch[i]);
zs_sum = Curve.scalar.add(zs_sum, zs);
}
zs_sum = Curve.scalar.mul8(zs_sum);
var zhs: [count]Curve.scalar.CompressedScalar = undefined;
for (z_batch, 0..) |z, i| {
zhs[i] = Curve.scalar.mul(z, hram_batch[i]);
}
const zr = (try Curve.mulMulti(count, expected_r_batch, z_batch)).clearCofactor();
const zah = (try Curve.mulMulti(count, a_batch, zhs)).clearCofactor();
const zsb = try Curve.basePoint.mulPublic(zs_sum);
if (zr.add(zah).sub(zsb).rejectIdentity()) |_| {
return error.SignatureVerificationFailed;
} else |_| {}
}