use super::{constants::*, errors::*};
use crate::common::*;
use core::fmt::Debug;
use curve25519_dalek::{
edwards::{CompressedEdwardsY, EdwardsPoint},
scalar::Scalar,
};
use sha2::*;
pub fn hash_points(pts: &[CompressedEdwardsY]) -> Scalar {
let mut hash: Sha512 = Sha512::new();
hash.update(SUITE_STRING);
hash.update(TWO_STRING);
for p in pts {
hash.update(p.to_bytes());
}
hash.update(ZERO_STRING);
let mut c_bytes: [u8; 32] = [0; 32];
c_bytes[0..16].copy_from_slice(&hash.finalize().as_slice()[0..16]);
Scalar::from_bytes_mod_order(c_bytes)
}
#[derive(Clone, PartialEq, Eq)]
pub struct Proof(pub EdwardsPoint, pub Scalar, pub Scalar);
impl Serial for Proof {
#[inline]
fn serial<B: Buffer>(&self, x: &mut B) {
let c = &self.1.to_bytes();
assert_eq!(c[16..32], [0u8; 16]);
x.write_all(&self.0.compress().to_bytes()[..])
.expect("Writing to buffer should succeed.");
x.write_all(&c[..16])
.expect("Writing to buffer should succeed.");
x.write_all(&self.2.to_bytes()[..])
.expect("Writing to buffer should succeed.");
}
}
impl Deserial for Proof {
#[inline]
fn deserial<R: ReadBytesExt>(source: &mut R) -> ParseResult<Self> {
let mut point_bytes: [u8; 32] = [0u8; 32];
source.read_exact(&mut point_bytes)?;
let mut scalar_bytes1: [u8; 32] = [0u8; 32];
source.read_exact(&mut scalar_bytes1[0..16])?;
let mut scalar_bytes2: [u8; 32] = [0u8; 32];
source.read_exact(&mut scalar_bytes2)?;
let compressed_point = CompressedEdwardsY(point_bytes);
match compressed_point.decompress() {
None => Err(ProofError(InternalError::PointDecompression).into()),
Some(p) => match Scalar::from_canonical_bytes(scalar_bytes1).into() {
None => Err(ProofError(InternalError::ScalarFormat).into()),
Some(s1) => match Scalar::from_canonical_bytes(scalar_bytes2).into() {
None => Err(ProofError(InternalError::ScalarFormat).into()),
Some(s2) => Ok(Proof(p, s1, s2)),
},
},
}
}
}
impl Debug for Proof {
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
write!(f, "Proof( {:?}, {:?}, {:?} )", &self.0, &self.1, &self.2)
}
}
impl Proof {
pub fn to_hash(&self) -> [u8; 64] {
let p = self.0.mul_by_cofactor();
let hash: Sha512 = Sha512::new()
.chain_update(SUITE_STRING)
.chain_update(THREE_STRING)
.chain_update(p.compress().to_bytes())
.chain_update(ZERO_STRING);
let mut c_bytes: [u8; 64] = [0; 64];
c_bytes.copy_from_slice(hash.finalize().as_slice());
c_bytes
}
}