use core::fmt;
use p256::elliptic_curve::Group as _;
use p256::elliptic_curve::ff::Field as _;
use zeroize::{Zeroize, Zeroizing};
use crate::Error;
use crate::suite::sealed::{Bytes as _, Group as _};
use crate::suite::{Group, Point, Scalar, ScalarBytes, Suite};
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
pub struct Context<'a> {
pub context: &'a [u8],
pub prover_id: &'a [u8],
pub verifier_id: &'a [u8],
}
fn nonzero<S: Suite>(scalar: Scalar<S>) -> Result<Scalar<S>, Error> {
if bool::from(scalar.is_zero()) {
return Err(Error::InvalidScalar);
}
Ok(scalar)
}
pub struct ProverSecret<S: Suite> {
w0: Scalar<S>,
w1: Scalar<S>,
}
impl<S: Suite> ProverSecret<S> {
pub fn from_pbkdf_output(output: &[u8]) -> Result<Self, Error> {
let refused = Error::PbkdfOutputLength {
actual: output.len(),
};
if output.len() % 2 != 0
|| output.len() < S::MIN_PBKDF_OUTPUT_LEN
|| output.len() > S::MAX_PBKDF_OUTPUT_LEN
{
return Err(refused);
}
let (w0s, w1s) = output.split_at(output.len() / 2);
let (Some(w0), Some(w1)) = (Group::<S>::reduce(w0s), Group::<S>::reduce(w1s)) else {
return Err(refused);
};
Ok(Self {
w0: nonzero::<S>(w0)?,
w1: nonzero::<S>(w1)?,
})
}
#[must_use]
pub fn verifier_record(&self) -> VerifierRecord<S> {
VerifierRecord {
w0: self.w0,
l: Point::<S>::generator() * self.w1,
}
}
pub(crate) fn w0(&self) -> &Scalar<S> {
&self.w0
}
pub(crate) fn w1(&self) -> &Scalar<S> {
&self.w1
}
}
impl<S: Suite> Clone for ProverSecret<S> {
fn clone(&self) -> Self {
Self {
w0: self.w0,
w1: self.w1,
}
}
}
impl<S: Suite> Drop for ProverSecret<S> {
fn drop(&mut self) {
self.w0.zeroize();
self.w1.zeroize();
}
}
impl<S: Suite> fmt::Debug for ProverSecret<S> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("ProverSecret(..)")
}
}
pub struct VerifierRecord<S: Suite> {
w0: Scalar<S>,
l: Point<S>,
}
impl<S: Suite> VerifierRecord<S> {
pub fn from_bytes(bytes: &[u8]) -> Result<Self, Error> {
let expected = size_of::<S::Record>();
let length = Error::Length {
expected,
actual: bytes.len(),
};
if bytes.len() != expected {
return Err(length);
}
let (w0, l) = bytes
.split_at_checked(size_of::<ScalarBytes<S>>())
.ok_or(length)?;
Ok(Self {
w0: nonzero::<S>(Group::<S>::scalar_from_bytes(w0).ok_or(Error::InvalidScalar)?)?,
l: Group::<S>::decode(l).ok_or(Error::InvalidPoint)?,
})
}
#[must_use]
pub fn to_bytes(&self) -> Zeroizing<S::Record> {
let mut record = Zeroizing::new(S::Record::zeroed());
let w0 = Zeroizing::new(Group::<S>::scalar_to_bytes(&self.w0));
let (head, tail) = record.as_mut().split_at_mut(w0.as_ref().len());
head.copy_from_slice(w0.as_ref());
let _encoded: Option<()> = Group::<S>::encode(&self.l, tail);
record
}
pub(crate) fn w0(&self) -> &Scalar<S> {
&self.w0
}
pub(crate) fn l(&self) -> &Point<S> {
&self.l
}
}
impl<S: Suite> Clone for VerifierRecord<S> {
fn clone(&self) -> Self {
Self {
w0: self.w0,
l: self.l,
}
}
}
impl<S: Suite> Drop for VerifierRecord<S> {
fn drop(&mut self) {
self.w0.zeroize();
self.l.zeroize();
}
}
impl<S: Suite> fmt::Debug for VerifierRecord<S> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("VerifierRecord(..)")
}
}