use alloc::vec::Vec;
use rand_core::CryptoRng;
use zeroize::{Zeroize, Zeroizing};
use crate::ciphersuite::CpaceCiphersuite;
use crate::error::CpaceError;
use crate::generator::calculate_generator;
use crate::initiator::CpaceOutput;
use crate::transcript::{derive_isk, derive_session_id, CpaceMode};
use pakery_core::crypto::CpaceGroup;
pub struct CpaceResponder<C: CpaceCiphersuite>(core::marker::PhantomData<C>);
impl<C: CpaceCiphersuite> CpaceResponder<C> {
#[allow(clippy::too_many_arguments)]
pub fn respond(
initiator_share: &[u8],
password: &[u8],
ci: &[u8],
sid: &[u8],
ad_initiator: &[u8],
ad_responder: &[u8],
mode: CpaceMode,
rng: &mut impl CryptoRng,
) -> Result<(Vec<u8>, CpaceOutput), CpaceError> {
let ya = C::Group::from_bytes(initiator_share).map_err(|_| CpaceError::InvalidPoint)?;
if ya.is_identity() {
return Err(CpaceError::IdentityPoint);
}
let g = calculate_generator::<C>(password, ci, sid)?;
let mut yb_scalar = C::Group::random_scalar(rng);
let yb_point = g.scalar_mul(&yb_scalar);
let yb_bytes = yb_point.to_bytes();
let k = ya.scalar_mul(&yb_scalar);
yb_scalar.zeroize();
if k.is_identity() {
return Err(CpaceError::IdentityPoint);
}
let k_bytes = Zeroizing::new(k.to_bytes());
let isk = derive_isk::<C>(
sid,
&k_bytes,
initiator_share,
ad_initiator,
&yb_bytes,
ad_responder,
mode,
);
let session_id =
derive_session_id::<C>(initiator_share, ad_initiator, &yb_bytes, ad_responder, mode);
Ok((yb_bytes, CpaceOutput { isk, session_id }))
}
}