use curve25519_dalek::{
constants::RISTRETTO_BASEPOINT_POINT,
ristretto::{CompressedRistretto, RistrettoPoint},
scalar::Scalar,
};
use Error::{WiredRistrettoPointMalformed, WiredScalarMalformed};
use subtle::ConstantTimeEq;
use typenum::U64;
use digest::Digest;
use request;
#[derive(Copy, Clone, Debug)]
pub struct UnblindedSigData {
e: Scalar,
s: Scalar,
r: RistrettoPoint,
}
impl UnblindedSigData {
pub fn new(e: Scalar, s: Scalar, r: RistrettoPoint) -> Self {
Self { e, s, r }
}
pub fn authenticate(&self, pub_key: RistrettoPoint) -> bool {
self.s * RISTRETTO_BASEPOINT_POINT == self.e * pub_key + self.r
}
pub fn const_authenticate(&self, pub_key: RistrettoPoint) -> bool {
(self.s * RISTRETTO_BASEPOINT_POINT)
.ct_eq( &(self.e * pub_key + self.r) )
.unwrap_u8() == 1
}
pub fn msg_authenticate<H, M>(&self, pub_key: RistrettoPoint, msg: M) -> bool
where
H: Digest<OutputSize = U64> + Default,
M: AsRef<[u8]>,
{
let e = request::generate_e::<H>(self.r, msg.as_ref());
self.s * RISTRETTO_BASEPOINT_POINT == e * pub_key + self.r
}
pub fn msg_const_authenticate<H, M>(&self, pub_key: RistrettoPoint, msg: M) -> bool
where
H: Digest<OutputSize = U64> + Default,
M: AsRef<[u8]>,
{
let e = request::generate_e::<H>(self.r, msg.as_ref());
(self.s * RISTRETTO_BASEPOINT_POINT)
.ct_eq( &(e * pub_key + self.r) )
.unwrap_u8() == 1
}
}
pub struct WiredUnblindedSigData(pub [u8; 96]);
impl From<UnblindedSigData> for WiredUnblindedSigData {
fn from(usd: UnblindedSigData) -> Self {
let mut arr = [0; 96];
arr[0..32].copy_from_slice(usd.e.as_bytes());
arr[32..64].copy_from_slice(usd.s.as_bytes());
arr[64..96].copy_from_slice(usd.r.compress().as_bytes());
WiredUnblindedSigData(arr)
}
}
impl WiredUnblindedSigData {
pub fn to_internal_format(&self) -> ::Result<UnblindedSigData> {
let mut e_arr = [0; 32];
let mut s_arr = [0; 32];
let mut r_arr = [0; 32];
e_arr.copy_from_slice(&self.0[0..32]);
s_arr.copy_from_slice(&self.0[32..64]);
r_arr.copy_from_slice(&self.0[64..96]);
Ok(UnblindedSigData {
e: Scalar::from_canonical_bytes(e_arr).ok_or(WiredScalarMalformed)?,
s: Scalar::from_canonical_bytes(s_arr).ok_or(WiredScalarMalformed)?,
r: CompressedRistretto(r_arr)
.decompress()
.ok_or(WiredRistrettoPointMalformed)?,
})
}
pub fn as_bytes(&self) -> &[u8; 96] {
&self.0
}
pub fn to_bytes(&self) -> [u8; 96] {
self.0
}
}