1use k256::{
2 elliptic_curve::{ff::PrimeField, group::GroupEncoding, sec1::FromEncodedPoint},
3 AffinePoint, EncodedPoint, ProjectivePoint, Scalar,
4};
5use tiny_keccak::{Hasher, Keccak};
6
7pub fn new_candidate_point(b: &[u8]) -> AffinePoint {
9 let x = field_hash(b);
11 let mut y = y_squared(&x).square();
13
14 if y.is_odd().unwrap_u8() == 1 {
15 y = y.negate();
16 }
17
18 let x_bytes = x.to_bytes();
19 let y_bytes = y.to_bytes();
20 let encoded_point = EncodedPoint::from_affine_coordinates(&x_bytes, &y_bytes, false);
21
22 AffinePoint::from_encoded_point(&encoded_point).unwrap()
23}
24
25pub fn field_hash(b: &[u8]) -> Scalar {
27 let mut output = [0u8; 32];
28 let mut hasher = Keccak::v256();
29 hasher.update(b);
30 hasher.finalize(&mut output);
31
32 Scalar::from_repr(output.into()).unwrap()
33}
34
35pub fn y_squared(x: &Scalar) -> Scalar {
37 let t = *x;
38 t * t * t + Scalar::from_u128(7)
40}
41
42pub fn hash_to_curve_prefix(alpha: &Scalar, pk: &AffinePoint) -> AffinePoint {
45 let packed = [
46 Scalar::from_u128(1).to_bytes().as_slice(),
48 pk.to_bytes().as_slice(),
50 alpha.to_bytes().as_slice(),
52 ]
53 .concat();
54
55 new_candidate_point(&packed)
56}
57
58pub fn hash_points(
60 g: &AffinePoint,
61 h: &AffinePoint,
62 pk: &AffinePoint,
63 gamma: &AffinePoint,
64 kg: &AffinePoint,
65 kh: &AffinePoint,
66) -> Scalar {
67 let mut output = [0u8; 32];
68 let mut hasher = Keccak::v256();
69 let all_points = [g, h, pk, gamma, kg, kh];
70 for point in all_points {
71 hasher.update(point.to_bytes().as_ref());
72 }
73 hasher.finalize(&mut output);
74 Scalar::from_repr(output.into()).unwrap()
75}
76
77pub fn hash_points_prefix(
80 hash: &AffinePoint,
81 pk: &AffinePoint,
82 gamma: &AffinePoint,
83 u_witness: &Scalar,
84 v: &AffinePoint,
85) -> Scalar {
86 let mut output = [0u8; 32];
87 let mut hasher = Keccak::v256();
88 let all_points = [hash, pk, gamma, v];
89 hasher.update(Scalar::from_u128(2).to_bytes().as_slice());
91 for point in all_points {
92 hasher.update(point.to_bytes().as_ref());
93 }
94 hasher.update(u_witness.to_bytes().as_ref());
95 hasher.finalize(&mut output);
96 Scalar::from_repr(output.into()).unwrap()
97}
98
99pub fn hash_to_curve(alpha: &Scalar, y: Option<&AffinePoint>) -> AffinePoint {
101 let mut r = ProjectivePoint::GENERATOR * alpha;
102
103 if let Some(y) = y {
104 r += ProjectivePoint::from(*y);
105 }
106
107 r.to_affine()
108}