Skip to content

Commit 13faeb7

Browse files
committed
feat: add osswu trait
Signed-off-by: Michael Lodder <[email protected]>
1 parent b611df3 commit 13faeb7

File tree

3 files changed

+89
-0
lines changed

3 files changed

+89
-0
lines changed

elliptic-curve/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ dev = ["arithmetic", "hex-literal", "pem", "pkcs8"]
4949
ecdh = ["arithmetic"]
5050
hazmat = []
5151
jwk = ["alloc", "base64ct/alloc", "serde", "serde_json", "zeroize/alloc"]
52+
osswu = ["ff"]
5253
pem = ["alloc", "arithmetic", "pem-rfc7468/alloc", "pkcs8", "sec1/pem"]
5354
pkcs8 = ["sec1/pkcs8"]
5455
std = ["alloc", "rand_core/std"]

elliptic-curve/src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,10 @@ pub mod ecdh;
9494
#[cfg(feature = "jwk")]
9595
mod jwk;
9696

97+
/// Optimized simplified Shallue-van de Woestijne-Ulas methods
98+
#[cfg(feature = "osswu")]
99+
pub mod osswu;
100+
97101
pub use crate::{
98102
error::{Error, Result},
99103
point::{

elliptic-curve/src/osswu.rs

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
use ff::Field;
2+
use subtle::Choice;
3+
4+
/// The Optimized Simplified Shallue-van de Woestijne-Ulas parameters
5+
pub struct OsswuMapParams<F>
6+
where
7+
F: Field,
8+
{
9+
/// The first constant term
10+
pub c1: [u64; 4],
11+
/// The second constant term
12+
pub c2: F,
13+
/// The ISO A variable or Curve A variable
14+
pub map_a: F,
15+
/// The ISO A variable or Curve A variable
16+
pub map_b: F,
17+
/// The Z parameter
18+
pub z: F,
19+
}
20+
21+
/// Trait for determining the parity of the field
22+
pub trait Sgn0: Field {
23+
/// Return the parity of the field
24+
/// 1 == negative
25+
/// 0 == non-negative
26+
fn sgn0(&self) -> u8;
27+
}
28+
29+
/// The optimized simplified Shallue-van de Woestijne-Ulas method
30+
/// for mapping elliptic curve scalars to affine points.
31+
pub trait OsswuMap: Sgn0 {
32+
/// The OSSWU parameters for mapping the field to affine points.
33+
/// For Weierstrass curves having A==0 or B==0, the parameters
34+
/// should be for isogeny where A≠0 and B≠0.
35+
const PARAMS: OsswuMapParams<Self>;
36+
37+
/// Convert this field element into an affine point on the ellliptic curve
38+
/// returning (X, Y). For Weierstrass curves having A==0 or B==0
39+
/// the result is a point on an isogeny.
40+
fn osswu(&self) -> (Self, Self) {
41+
let tv1 = self.square(); // u^2
42+
let tv3 = Self::PARAMS.z * tv1; // Z * u^2
43+
let mut tv2 = tv3.square(); // tv3^2
44+
let mut xd = tv2 + tv3; // tv3^2 + tv3
45+
let x1n = Self::PARAMS.map_b * (xd + Self::one()); // B * (xd + 1)
46+
let a_neg = -Self::PARAMS.map_a;
47+
xd *= a_neg; // -A * xd
48+
49+
let tv = Self::PARAMS.z * Self::PARAMS.map_a;
50+
xd.conditional_assign(&tv, xd.is_zero());
51+
52+
tv2 = xd.square(); //xd^2
53+
let gxd = tv2 * xd; // xd^3
54+
tv2 *= Self::PARAMS.map_a; // A * tv2
55+
56+
let mut gx1 = x1n * (tv2 + x1n.square()); //x1n *(tv2 + x1n^2)
57+
tv2 = gxd * Self::PARAMS.map_b; // B * gxd
58+
gx1 += tv2; // gx1 + tv2
59+
60+
let mut tv4 = gxd.square(); // gxd^2
61+
tv2 = gx1 * gxd; // gx1 * gxd
62+
tv4 *= tv2;
63+
64+
let y1 = tv4.pow_vartime(&Self::PARAMS.c1) * tv2; // tv4^C1 * tv2
65+
let x2n = tv3 * x1n; // tv3 * x1n
66+
67+
let y2 = y1 * Self::PARAMS.c2 * tv1 * self; // y1 * c2 * tv1 * u
68+
69+
tv2 = y1.square() * gxd; //y1^2 * gxd
70+
71+
let e2 = tv2.ct_eq(&gx1);
72+
73+
// if e2 , x = x1, else x = x2
74+
let mut x = Self::conditional_select(&x2n, &x1n, e2);
75+
// xn / xd
76+
x *= xd.invert().unwrap();
77+
78+
// if e2, y = y1, else y = y2
79+
let mut y = Self::conditional_select(&y2, &y1, e2);
80+
81+
y.conditional_assign(&-y, Choice::from(self.sgn0() ^ y.sgn0()));
82+
(x, y)
83+
}
84+
}

0 commit comments

Comments
 (0)