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, ProverSecret, ShareP, ShareV, SharedKey};
pub struct Prover<S: Suite> {
secret: ProverSecret<S>,
x: Scalar<S>,
share: ShareP<S>,
transcript: Transcript<S>,
}
impl<S: Suite> Prover<S> {
pub fn start<R: CryptoRng + ?Sized>(
secret: &ProverSecret<S>,
context: &Context<'_>,
rng: &mut R,
) -> (Self, ShareP<S>) {
let mask = Zeroizing::new(Group::<S>::fixed(Group::<S>::M) * *secret.w0());
loop {
let mut x = Group::<S>::random(rng);
if let Ok(share) = ShareP::from_point(&(Point::<S>::generator() * x + *mask)) {
let prover = Self {
secret: secret.clone(),
x,
share,
transcript: Transcript::new(context),
};
return (prover, share);
}
x.zeroize();
}
}
pub fn receive(self, share_v: &ShareV<S>) -> Result<ProverConfirming<S>, Error> {
let (z, v) = self.shared(share_v)?;
let keys =
self.transcript
.clone()
.finish(&self.share, share_v, (&z, &v), self.secret.w0())?;
Ok(ProverConfirming { keys })
}
pub(crate) fn shared(&self, share_v: &ShareV<S>) -> Result<SharedPoints<S>, Error> {
let unmasked = unmask::<S>(share_v, Group::<S>::N, self.secret.w0())?;
Ok((
Zeroizing::new(*unmasked * self.x),
Zeroizing::new(*unmasked * *self.secret.w1()),
))
}
}
impl<S: Suite> Drop for Prover<S> {
fn drop(&mut self) {
self.x.zeroize();
}
}
impl<S: Suite> fmt::Debug for Prover<S> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("Prover(..)")
}
}
pub struct ProverConfirming<S: Suite> {
keys: Keys<S>,
}
impl<S: Suite> ProverConfirming<S> {
pub fn finish(self, confirm_v: &ConfirmV<S>) -> Result<(ConfirmP<S>, SharedKey<S>), Error> {
confirm_v.check(&self.keys.confirm_v)?;
Ok((
ConfirmP::new(self.keys.confirm_p),
SharedKey::new(self.keys.shared),
))
}
#[must_use]
pub fn confirm_first(self) -> (ConfirmP<S>, ProverConfirmedFirst<S>) {
(
ConfirmP::new(self.keys.confirm_p),
ProverConfirmedFirst { keys: self.keys },
)
}
}
impl<S: Suite> fmt::Debug for ProverConfirming<S> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("ProverConfirming(..)")
}
}
pub struct ProverConfirmedFirst<S: Suite> {
keys: Keys<S>,
}
impl<S: Suite> ProverConfirmedFirst<S> {
pub fn finish(self, confirm_v: &ConfirmV<S>) -> Result<SharedKey<S>, Error> {
confirm_v.check(&self.keys.confirm_v)?;
Ok(SharedKey::new(self.keys.shared))
}
}
impl<S: Suite> fmt::Debug for ProverConfirmedFirst<S> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("ProverConfirmedFirst(..)")
}
}