use rand_core::{CryptoRng, RngCore};
use crate::{scalar_mul::VartimeMultiscalarMul, Ciphersuite, Element, *};
#[derive(Clone, Debug)]
pub struct Item<C: Ciphersuite> {
vk: VerifyingKey<C>,
sig: Signature<C>,
c: Challenge<C>,
}
impl<C> Item<C>
where
C: Ciphersuite,
{
pub fn new<M>(vk: VerifyingKey<C>, sig: Signature<C>, msg: M) -> Result<Self, Error<C>>
where
M: AsRef<[u8]>,
{
let (msg, sig, vk) = <C>::pre_verify(msg.as_ref(), &sig, &vk)?;
let c = <C>::challenge(&sig.R, &vk, &msg)?;
Ok(Self {
vk: *vk,
sig: *sig,
c,
})
}
}
impl<C> Item<C>
where
C: Ciphersuite,
{
pub fn verify_single(self) -> Result<(), Error<C>> {
self.vk.verify_prehashed(self.c, &self.sig)
}
}
pub struct Verifier<C: Ciphersuite> {
signatures: Vec<Item<C>>,
}
impl<C> Verifier<C>
where
C: Ciphersuite,
{
pub fn new() -> Verifier<C> {
Verifier::default()
}
pub fn queue<I: Into<Item<C>>>(&mut self, item: I) {
self.signatures.push(item.into());
}
pub fn verify<R: RngCore + CryptoRng>(self, mut rng: R) -> Result<(), Error<C>> {
let n = self.signatures.len();
if n == 0 {
return Err(Error::InvalidSignature);
}
let mut VK_coeffs = Vec::with_capacity(n);
let mut VKs = Vec::with_capacity(n);
let mut R_coeffs = Vec::with_capacity(n);
let mut Rs = Vec::with_capacity(n);
let mut P_coeff_acc = <<C::Group as Group>::Field>::zero();
for item in self.signatures.iter() {
let z = item.sig.z;
let R = item.sig.R;
let blind = <<C::Group as Group>::Field>::random(&mut rng);
let P_coeff = blind * z;
P_coeff_acc = P_coeff_acc - P_coeff;
R_coeffs.push(blind);
Rs.push(R);
VK_coeffs.push(<<C::Group as Group>::Field>::zero() + (blind * item.c.0));
VKs.push(item.vk.to_element());
}
let scalars = core::iter::once(&P_coeff_acc)
.chain(VK_coeffs.iter())
.chain(R_coeffs.iter());
let basepoints = [C::Group::generator()];
let points = basepoints.iter().chain(VKs.iter()).chain(Rs.iter());
let check: Element<C> =
VartimeMultiscalarMul::<C>::vartime_multiscalar_mul(scalars, points);
if (check * <C::Group>::cofactor()) == <C::Group>::identity() {
Ok(())
} else {
Err(Error::InvalidSignature)
}
}
}
impl<C> Default for Verifier<C>
where
C: Ciphersuite,
{
fn default() -> Self {
Self {
signatures: Vec::new(),
}
}
}