Skip to content

Commit 1a12d0e

Browse files
committed
Update OSSWU code
1 parent 0af93f6 commit 1a12d0e

File tree

1 file changed

+84
-41
lines changed

1 file changed

+84
-41
lines changed
+84-41
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
//! Optimized simplified Shallue-van de Woestijne-Ulas methods.
22
//!
3-
//! <https://eprint.iacr.org/2009/340.pdf>
3+
//! <https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-16.html#straightline-sswu>
44
55
use ff::Field;
66
use subtle::Choice;
7+
use subtle::ConditionallySelectable;
8+
use subtle::ConstantTimeEq;
79

810
/// The Optimized Simplified Shallue-van de Woestijne-Ulas parameters
911
pub struct OsswuMapParams<F>
@@ -38,50 +40,91 @@ pub trait OsswuMap: Field + Sgn0 {
3840
/// should be for isogeny where A≠0 and B≠0.
3941
const PARAMS: OsswuMapParams<Self>;
4042

43+
/// Optimized sqrt_ratio for q = 3 mod 4.
44+
fn sqrt_ratio_3mod4(u: Self, v: Self) -> (Choice, Self) {
45+
// 1. tv1 = v^2
46+
let tv1 = v.square();
47+
// 2. tv2 = u * v
48+
let tv2 = u * v;
49+
// 3. tv1 = tv1 * tv2
50+
let tv1 = tv1 * tv2;
51+
// 4. y1 = tv1^c1
52+
let y1 = tv1.pow_vartime(Self::PARAMS.c1);
53+
// 5. y1 = y1 * tv2
54+
let y1 = y1 * tv2;
55+
// 6. y2 = y1 * c2
56+
let y2 = y1 * Self::PARAMS.c2;
57+
// 7. tv3 = y1^2
58+
let tv3 = y1.square();
59+
// 8. tv3 = tv3 * v
60+
let tv3 = tv3 * v;
61+
// 9. isQR = tv3 == u
62+
let is_qr = tv3.ct_eq(&u);
63+
// 10. y = CMOV(y2, y1, isQR)
64+
let y = ConditionallySelectable::conditional_select(&y2, &y1, is_qr);
65+
// 11. return (isQR, y)
66+
(is_qr, y)
67+
}
68+
4169
/// Convert this field element into an affine point on the elliptic curve
4270
/// returning (X, Y). For Weierstrass curves having A==0 or B==0
4371
/// the result is a point on an isogeny.
4472
fn osswu(&self) -> (Self, Self) {
45-
let tv1 = self.square(); // u^2
46-
let tv3 = Self::PARAMS.z * tv1; // Z * u^2
47-
let mut tv2 = tv3.square(); // tv3^2
48-
let mut xd = tv2 + tv3; // tv3^2 + tv3
49-
let x1n = Self::PARAMS.map_b * (xd + Self::ONE); // B * (xd + 1)
50-
xd *= -Self::PARAMS.map_a; // -A * xd
51-
52-
let tv = Self::PARAMS.z * Self::PARAMS.map_a;
53-
xd.conditional_assign(&tv, xd.is_zero());
54-
55-
tv2 = xd.square(); //xd^2
56-
let gxd = tv2 * xd; // xd^3
57-
tv2 *= Self::PARAMS.map_a; // A * tv2
58-
59-
let mut gx1 = x1n * (tv2 + x1n.square()); //x1n *(tv2 + x1n^2)
60-
tv2 = gxd * Self::PARAMS.map_b; // B * gxd
61-
gx1 += tv2; // gx1 + tv2
62-
63-
let mut tv4 = gxd.square(); // gxd^2
64-
tv2 = gx1 * gxd; // gx1 * gxd
65-
tv4 *= tv2;
66-
67-
let y1 = tv4.pow_vartime(Self::PARAMS.c1) * tv2; // tv4^C1 * tv2
68-
let x2n = tv3 * x1n; // tv3 * x1n
69-
70-
let y2 = y1 * Self::PARAMS.c2 * tv1 * self; // y1 * c2 * tv1 * u
71-
72-
tv2 = y1.square() * gxd; //y1^2 * gxd
73-
74-
let e2 = tv2.ct_eq(&gx1);
75-
76-
// if e2 , x = x1, else x = x2
77-
let mut x = Self::conditional_select(&x2n, &x1n, e2);
78-
// xn / xd
79-
x *= xd.invert().unwrap();
80-
81-
// if e2, y = y1, else y = y2
82-
let mut y = Self::conditional_select(&y2, &y1, e2);
83-
84-
y.conditional_assign(&-y, self.sgn0() ^ y.sgn0());
73+
// 1. tv1 = u^2
74+
let tv1 = self.square();
75+
// 2. tv1 = Z * tv1
76+
let tv1 = Self::PARAMS.z * tv1;
77+
// 3. tv2 = tv1^2
78+
let tv2 = tv1.square();
79+
// 4. tv2 = tv2 + tv1
80+
let tv2 = tv2 + tv1;
81+
// 5. tv3 = tv2 + 1
82+
let tv3 = tv2 + Self::ONE;
83+
// 6. tv3 = B * tv3
84+
let tv3 = Self::PARAMS.map_b * tv3;
85+
// 7. tv4 = CMOV(Z, -tv2, tv2 != 0)
86+
let tv4 = ConditionallySelectable::conditional_select(
87+
&Self::PARAMS.z,
88+
&-tv2,
89+
!Field::is_zero(&tv2),
90+
);
91+
// 8. tv4 = A * tv4
92+
let tv4 = Self::PARAMS.map_a * tv4;
93+
// 9. tv2 = tv3^2
94+
let tv2 = tv3.square();
95+
// 10. tv6 = tv4^2
96+
let tv6 = tv4.square();
97+
// 11. tv5 = A * tv6
98+
let tv5 = Self::PARAMS.map_a * tv6;
99+
// 12. tv2 = tv2 + tv5
100+
let tv2 = tv2 + tv5;
101+
// 13. tv2 = tv2 * tv3
102+
let tv2 = tv2 * tv3;
103+
// 14. tv6 = tv6 * tv4
104+
let tv6 = tv6 * tv4;
105+
// 15. tv5 = B * tv6
106+
let tv5 = Self::PARAMS.map_b * tv6;
107+
// 16. tv2 = tv2 + tv5
108+
let tv2 = tv2 + tv5;
109+
// 17. x = tv1 * tv3
110+
let x = tv1 * tv3;
111+
// 18. (is_gx1_square, y1) = sqrt_ratio(tv2, tv6)
112+
let (is_gx1_square, y1) = Self::sqrt_ratio_3mod4(tv2, tv6);
113+
// 19. y = tv1 * u
114+
let y = tv1 * self;
115+
// 20. y = y * y1
116+
let y = y * y1;
117+
// 21. x = CMOV(x, tv3, is_gx1_square)
118+
let x = ConditionallySelectable::conditional_select(&x, &tv3, is_gx1_square);
119+
// 22. y = CMOV(y, y1, is_gx1_square)
120+
let y = ConditionallySelectable::conditional_select(&y, &y1, is_gx1_square);
121+
// 23. e1 = sgn0(u) == sgn0(y)
122+
let e1 = self.sgn0().ct_eq(&y.sgn0());
123+
// 24. y = CMOV(-y, y, e1)
124+
let y = ConditionallySelectable::conditional_select(&-y, &y, e1);
125+
// 25. x = x / tv4
126+
let x = x * tv4.invert().unwrap();
127+
// 26. return (x, y)
85128
(x, y)
86129
}
87130
}

0 commit comments

Comments
 (0)