use k256::{
elliptic_curve::{ff::PrimeField, group::GroupEncoding, sec1::FromEncodedPoint},
AffinePoint, EncodedPoint, ProjectivePoint, Scalar,
};
use tiny_keccak::{Hasher, Keccak};
pub fn new_candidate_point(b: &[u8]) -> AffinePoint {
let x = field_hash(b);
let mut y = y_squared(&x).square();
if y.is_odd().unwrap_u8() == 1 {
y = y.negate();
}
let x_bytes = x.to_bytes();
let y_bytes = y.to_bytes();
let encoded_point = EncodedPoint::from_affine_coordinates(&x_bytes, &y_bytes, false);
AffinePoint::from_encoded_point(&encoded_point).unwrap()
}
pub fn field_hash(b: &[u8]) -> Scalar {
let mut output = [0u8; 32];
let mut hasher = Keccak::v256();
hasher.update(b);
hasher.finalize(&mut output);
Scalar::from_repr(output.into()).unwrap()
}
pub fn y_squared(x: &Scalar) -> Scalar {
let t = *x;
t * t * t + Scalar::from_u128(7)
}
pub fn hash_to_curve_prefix(alpha: &Scalar, pk: &AffinePoint) -> AffinePoint {
let packed = [
Scalar::from_u128(1).to_bytes().as_slice(),
pk.to_bytes().as_slice(),
alpha.to_bytes().as_slice(),
]
.concat();
new_candidate_point(&packed)
}
pub fn hash_points(
g: &AffinePoint,
h: &AffinePoint,
pk: &AffinePoint,
gamma: &AffinePoint,
kg: &AffinePoint,
kh: &AffinePoint,
) -> Scalar {
let mut output = [0u8; 32];
let mut hasher = Keccak::v256();
let all_points = [g, h, pk, gamma, kg, kh];
for point in all_points {
hasher.update(point.to_bytes().as_ref());
}
hasher.finalize(&mut output);
Scalar::from_repr(output.into()).unwrap()
}
pub fn hash_points_prefix(
hash: &AffinePoint,
pk: &AffinePoint,
gamma: &AffinePoint,
u_witness: &Scalar,
v: &AffinePoint,
) -> Scalar {
let mut output = [0u8; 32];
let mut hasher = Keccak::v256();
let all_points = [hash, pk, gamma, v];
hasher.update(Scalar::from_u128(2).to_bytes().as_slice());
for point in all_points {
hasher.update(point.to_bytes().as_ref());
}
hasher.update(u_witness.to_bytes().as_ref());
hasher.finalize(&mut output);
Scalar::from_repr(output.into()).unwrap()
}
pub fn hash_to_curve(alpha: &Scalar, y: Option<&AffinePoint>) -> AffinePoint {
let mut r = ProjectivePoint::GENERATOR * alpha;
if let Some(y) = y {
r += ProjectivePoint::from(*y);
}
r.to_affine()
}