use core::fmt;
use p256::elliptic_curve::Group as _;
use p256::elliptic_curve::rand_core::CryptoRng;
use zeroize::{Zeroize, Zeroizing};
use crate::schedule::{Keys, SharedPoints, Transcript, unmask};
use crate::suite::sealed::Group as _;
use crate::suite::{Group, Point, Scalar, Suite};
use crate::{ConfirmP, ConfirmV, Context, Error, ShareP, ShareV, SharedKey, VerifierRecord};
pub struct Verifier<S: Suite> {
record: VerifierRecord<S>,
y: Scalar<S>,
share: ShareV<S>,
transcript: Transcript<S>,
}
impl<S: Suite> Verifier<S> {
pub fn start<R: CryptoRng + ?Sized>(
record: &VerifierRecord<S>,
context: &Context<'_>,
rng: &mut R,
) -> (Self, ShareV<S>) {
let mask = Zeroizing::new(Group::<S>::fixed(Group::<S>::N) * *record.w0());
loop {
let mut y = Group::<S>::random(rng);
if let Ok(share) = ShareV::from_point(&(Point::<S>::generator() * y + *mask)) {
let verifier = Self {
record: record.clone(),
y,
share,
transcript: Transcript::new(context),
};
return (verifier, share);
}
y.zeroize();
}
}
pub fn receive(
self,
share_p: &ShareP<S>,
) -> Result<(VerifierConfirming<S>, ConfirmV<S>), Error> {
let (z, v) = self.shared(share_p)?;
let keys =
self.transcript
.clone()
.finish(share_p, &self.share, (&z, &v), self.record.w0())?;
let confirm_v = ConfirmV::new(keys.confirm_v);
Ok((VerifierConfirming { keys }, confirm_v))
}
pub(crate) fn shared(&self, share_p: &ShareP<S>) -> Result<SharedPoints<S>, Error> {
let unmasked = unmask::<S>(share_p, Group::<S>::M, self.record.w0())?;
Ok((
Zeroizing::new(*unmasked * self.y),
Zeroizing::new(*self.record.l() * self.y),
))
}
}
impl<S: Suite> Drop for Verifier<S> {
fn drop(&mut self) {
self.y.zeroize();
}
}
impl<S: Suite> fmt::Debug for Verifier<S> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("Verifier(..)")
}
}
pub struct VerifierConfirming<S: Suite> {
keys: Keys<S>,
}
impl<S: Suite> VerifierConfirming<S> {
pub fn finish(self, confirm_p: &ConfirmP<S>) -> Result<SharedKey<S>, Error> {
confirm_p.check(&self.keys.confirm_p)?;
Ok(SharedKey::new(self.keys.shared))
}
}
impl<S: Suite> fmt::Debug for VerifierConfirming<S> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("VerifierConfirming(..)")
}
}