1#![allow(non_snake_case)]
2use ark_ec::twisted_edwards::TECurveConfig;
3
4use crate::ark_curve::edwards::{Decaf377EdwardsConfig, EdwardsProjective};
5
6use crate::{
7 ark_curve::constants::{ONE, TWO, ZETA},
8 ark_curve::on_curve::OnCurve,
9 sign::Sign,
10 Element, Fq,
11};
12
13impl Element {
14 fn elligator_map(r_0: &Fq) -> Element {
16 let A = Decaf377EdwardsConfig::COEFF_A;
18 let D = Decaf377EdwardsConfig::COEFF_D;
19
20 let r = ZETA * r_0.square();
21
22 let den = (D * r - (D - A)) * ((D - A) * r - D);
23 let num = (r + *ONE) * (A - *TWO * D);
24
25 let x = num * den;
26 let (iss, mut isri) = Fq::sqrt_ratio_zeta(&ONE, &x);
27
28 let sgn;
29 let twiddle;
30 if iss {
31 sgn = *ONE;
32 twiddle = *ONE;
33 } else {
34 sgn = -(*ONE);
35 twiddle = *r_0;
36 }
37
38 isri *= twiddle;
39
40 let mut s = isri * num;
41 let t = -(sgn) * isri * s * (r - *ONE) * (A - *TWO * D).square() - *ONE;
42
43 if s.is_negative() == iss {
44 s = -s
45 }
46
47 let E = *TWO * s;
49 let F = *ONE + Decaf377EdwardsConfig::COEFF_A * s.square();
50 let G = *ONE - Decaf377EdwardsConfig::COEFF_A * s.square();
51 let H = t;
52 let result = Element {
53 inner: EdwardsProjective::new(E * H, F * G, E * G, F * H),
54 };
55
56 debug_assert!(
57 result.inner.is_on_curve(),
58 "resulting point must be on the curve",
59 );
60
61 result
62 }
63
64 pub fn hash_to_curve(r_1: &Fq, r_2: &Fq) -> Element {
68 let R_1 = Element::elligator_map(r_1);
69 let R_2 = Element::elligator_map(r_2);
70 &R_1 + &R_2
71 }
72
73 pub fn encode_to_curve(r: &Fq) -> Element {
75 Element::elligator_map(r)
76 }
77}
78
79#[cfg(test)]
80mod tests {
81 use crate::ark_curve::edwards::EdwardsAffine;
82
83 use super::*;
84
85 #[test]
86 fn test_elligator() {
87 let inputs = [
89 [
90 221, 101, 215, 58, 170, 229, 36, 124, 172, 234, 94, 214, 186, 163, 242, 30, 65,
91 123, 76, 74, 56, 60, 24, 213, 240, 137, 49, 189, 138, 39, 90, 6,
92 ],
93 [
94 23, 203, 214, 51, 26, 149, 7, 160, 228, 239, 208, 147, 124, 109, 75, 72, 64, 16,
95 64, 215, 53, 185, 249, 168, 188, 49, 22, 194, 118, 7, 242, 16,
96 ],
97 [
98 177, 123, 90, 180, 115, 7, 108, 183, 161, 167, 24, 15, 248, 218, 206, 227, 76, 137,
99 162, 187, 148, 174, 66, 44, 205, 1, 211, 91, 140, 50, 144, 1,
100 ],
101 [
102 204, 225, 121, 228, 145, 30, 86, 208, 132, 242, 203, 9, 153, 90, 195, 150, 215, 49,
103 166, 70, 78, 68, 47, 98, 30, 130, 115, 139, 168, 242, 238, 8,
104 ],
105 [
106 59, 150, 40, 159, 229, 96, 201, 47, 170, 163, 9, 208, 205, 201, 112, 241, 179, 82,
107 198, 79, 207, 160, 184, 245, 63, 189, 101, 115, 217, 228, 74, 13,
108 ],
109 [
110 74, 159, 227, 190, 73, 213, 131, 200, 50, 102, 249, 230, 48, 103, 85, 168, 239,
111 149, 7, 164, 12, 42, 217, 177, 189, 97, 214, 98, 102, 73, 10, 16,
112 ],
113 [
114 183, 227, 227, 192, 119, 10, 155, 143, 64, 60, 249, 165, 240, 39, 31, 197, 159,
115 121, 64, 82, 10, 1, 34, 35, 121, 34, 146, 69, 226, 196, 156, 14,
116 ],
117 [
118 61, 21, 56, 224, 11, 181, 71, 186, 238, 126, 234, 240, 14, 168, 75, 73, 251, 111,
119 175, 85, 108, 9, 77, 2, 88, 249, 24, 235, 53, 96, 51, 15,
120 ],
121 ];
122
123 let expected_xy_coordinates = [
124 [
125 ark_ff::MontFp!(
126 "1267955849280145133999011095767946180059440909377398529682813961428156596086"
127 ),
128 ark_ff::MontFp!(
129 "5356565093348124788258444273601808083900527100008973995409157974880178412098"
130 ),
131 ],
132 [
133 ark_ff::MontFp!(
134 "1502379126429822955521756759528876454108853047288874182661923263559139887582"
135 ),
136 ark_ff::MontFp!(
137 "7074060208122316523843780248565740332109149189893811936352820920606931717751"
138 ),
139 ],
140 [
141 ark_ff::MontFp!(
142 "2943006201157313879823661217587757631000260143892726691725524748591717287835"
143 ),
144 ark_ff::MontFp!(
145 "4988568968545687084099497807398918406354768651099165603393269329811556860241"
146 ),
147 ],
148 [
149 ark_ff::MontFp!(
150 "2893226299356126359042735859950249532894422276065676168505232431940642875576"
151 ),
152 ark_ff::MontFp!(
153 "5540423804567408742733533031617546054084724133604190833318816134173899774745"
154 ),
155 ],
156 [
157 ark_ff::MontFp!(
158 "2950911977149336430054248283274523588551527495862004038190631992225597951816"
159 ),
160 ark_ff::MontFp!(
161 "4487595759841081228081250163499667279979722963517149877172642608282938805393"
162 ),
163 ],
164 [
165 ark_ff::MontFp!(
166 "3318574188155535806336376903248065799756521242795466350457330678746659358665"
167 ),
168 ark_ff::MontFp!(
169 "7706453242502782485686954136003233626318476373744684895503194201695334921001"
170 ),
171 ],
172 [
173 ark_ff::MontFp!(
174 "3753408652523927772367064460787503971543824818235418436841486337042861871179"
175 ),
176 ark_ff::MontFp!(
177 "2820605049615187268236268737743168629279853653807906481532750947771625104256"
178 ),
179 ],
180 [
181 ark_ff::MontFp!(
182 "7803875556376973796629423752730968724982795310878526731231718944925551226171"
183 ),
184 ark_ff::MontFp!(
185 "7033839813997913565841973681083930410776455889380940679209912201081069572111"
186 ),
187 ],
188 ];
189
190 use ark_serialize::CanonicalDeserialize;
191
192 for (ind, input) in inputs.iter().enumerate() {
193 let input_element =
194 Fq::deserialize_compressed(&input[..]).expect("encoding of test vector is valid");
195
196 let expected: Element = Element {
197 inner: EdwardsAffine::new(
198 crate::ark_curve::constants::from_ark_fq(expected_xy_coordinates[ind][0]),
199 crate::ark_curve::constants::from_ark_fq(expected_xy_coordinates[ind][1]),
200 )
201 .into(),
202 };
203
204 let actual = Element::elligator_map(&input_element);
205
206 assert_eq!(actual, expected);
207 }
208 }
209}