@@ -103,8 +103,8 @@ use core::ops::{Mul, MulAssign};
103
103
104
104
use cfg_if:: cfg_if;
105
105
106
- #[ cfg( feature = "digest " ) ]
107
- use crate :: elligator2:: map_to_point ;
106
+ #[ cfg( feature = "elligator2 " ) ]
107
+ use crate :: elligator2:: { map_fe_to_edwards , MASK_UNSET_BYTE } ;
108
108
#[ cfg( feature = "digest" ) ]
109
109
use digest:: { generic_array:: typenum:: U64 , Digest } ;
110
110
@@ -598,57 +598,42 @@ impl EdwardsPoint {
598
598
599
599
let sign_bit = ( res[ 31 ] & 0x80 ) >> 7 ;
600
600
601
- let fe1 = map_to_point ( & res) ;
601
+ let fe1 = MontgomeryPoint :: map_to_point_unbounded ( & res) ;
602
602
let E1_opt = fe1. to_edwards ( sign_bit) ;
603
603
604
604
E1_opt
605
605
. expect ( "Montgomery conversion to Edwards point in Elligator failed" )
606
606
. mul_by_cofactor ( )
607
607
}
608
608
609
- #[ cfg( elligator2) ]
610
- /// Build an [`EdwardsPoint`] using the birational mapping from (the
611
- /// extended `(u, v)` form of) a montgomery point.
612
- pub fn from_uv ( u : & [ u8 ; 32 ] , v : & [ u8 ; 32 ] ) -> EdwardsPoint {
613
- let u_fe = FieldElement :: from_bytes ( u) ;
614
- let v_fe = FieldElement :: from_bytes ( v) ;
615
- let ( x, y) = Self :: new_edwards_point ( & u_fe, & v_fe) ;
616
- Self :: from_xy ( x, y)
617
- }
618
-
619
- #[ cfg( elligator2) ]
620
- fn new_edwards_point ( u : & FieldElement , v : & FieldElement ) -> ( FieldElement , FieldElement ) {
621
- // Per RFC 7748: (x, y) = (sqrt(-486664)*u/v, (u-1)/(u+1))
622
-
623
- let two = & FieldElement :: ONE + & FieldElement :: ONE ;
624
- let ( _, sqrt_neg_a_plus_two) =
625
- FieldElement :: sqrt_ratio_i ( & ( & MONTGOMERY_A_NEG + & two) , & FieldElement :: ONE ) ;
626
-
627
- let mut x = & ( u * & v. invert ( ) ) * & sqrt_neg_a_plus_two;
628
-
629
- let u_plus_one = u + & FieldElement :: ONE ;
630
- let u_minus_one = u - & FieldElement :: ONE ;
631
-
632
- let mut y = & u_minus_one * & u_plus_one. invert ( ) ;
633
-
634
- // This mapping is undefined when t == 0 or s == -1, i.e., when the
635
- // denominator of either of the above rational functions is zero.
636
- // Implementations MUST detect exceptional cases and return the value
637
- // (v, w) = (0, 1), which is the identity point on all twisted Edwards
638
- // curves.
639
- let result_undefined = v. is_zero ( ) | u_plus_one. is_zero ( ) ;
640
- x. conditional_assign ( & FieldElement :: ZERO , result_undefined) ;
641
- y. conditional_assign ( & FieldElement :: ONE , result_undefined) ;
642
-
643
- // Convert from Edwards (x, y) to extended (x, y, z, t) coordinates.
644
- // new_edwards_from_xy(x, y)
645
-
646
- ( x, y)
609
+ #[ cfg( feature = "elligator2" ) ]
610
+ /// Perform the Elligator2 mapping to an [`EdwardsPoint`].
611
+ ///
612
+ /// Calculates a point on elliptic curve E (Curve25519) from an element of
613
+ /// the finite field F over which E is defined. See section 6.7.1 of the
614
+ /// RFC.
615
+ ///
616
+ /// The input u and output P are elements of the field F. Note that
617
+ /// the output P is a point on the edwards curve and as such it's byte
618
+ /// representation is distinguishable from uniform random.
619
+ ///
620
+ /// Input:
621
+ /// * u -> an element of field F.
622
+ ///
623
+ /// Output:
624
+ /// * P - a point on the Edwards elliptic curve.
625
+ ///
626
+ /// See <https://datatracker.ietf.org/doc/rfc9380/>
627
+ pub fn map_to_point ( r : & [ u8 ; 32 ] ) -> EdwardsPoint {
628
+ let mut clamped = * r;
629
+ clamped[ 31 ] &= MASK_UNSET_BYTE ;
630
+ let r_0 = FieldElement :: from_bytes ( & clamped) ;
631
+ let ( x, y) = map_fe_to_edwards ( & r_0) ;
632
+ Self :: from_xy ( & x, & y)
647
633
}
648
634
649
- #[ cfg( elligator2) ]
635
+ #[ cfg( feature = " elligator2" ) ]
650
636
fn from_xy ( x : & FieldElement , y : & FieldElement ) -> EdwardsPoint {
651
- // Yeah yeah yeah, no where better to put this. :(
652
637
let z = FieldElement :: ONE ;
653
638
let t = x * y;
654
639
@@ -2275,10 +2260,6 @@ mod test {
2275
2260
"2eb10d432702ea7f79207da95d206f82d5a3b374f5f89f17a199531f78d3bea6" ,
2276
2261
"d8f8b508edffbb8b6dab0f602f86a9dd759f800fe18f782fdcac47c234883e7f" ,
2277
2262
] ,
2278
- vec![
2279
- "84cbe9accdd32b46f4a8ef51c85fd39d028711f77fb00e204a613fc235fd68b9" ,
2280
- "93c73e0289afd1d1fc9e4e78a505d5d1b2642fbdf91a1eff7d281930654b1453" ,
2281
- ] ,
2282
2263
vec![
2283
2264
"c85165952490dc1839cb69012a3d9f2cc4b02343613263ab93a26dc89fd58267" ,
2284
2265
"43cbe8685fd3c90665b91835debb89ff1477f906f5170f38a192f6a199556537" ,
@@ -2291,35 +2272,44 @@ mod test {
2291
2272
"1618c08ef0233f94f0f163f9435ec7457cd7a8cd4bb6b160315d15818c30f7a2" ,
2292
2273
"da0b703593b29dbcd28ebd6e7baea17b6f61971f3641cae774f6a5137a12294c" ,
2293
2274
] ,
2294
- vec![
2295
- "48b73039db6fcdcb6030c4a38e8be80b6390d8ae46890e77e623f87254ef149c" ,
2296
- "ca11b25acbc80566603eabeb9364ebd50e0306424c61049e1ce9385d9f349966" ,
2297
- ] ,
2298
2275
vec![
2299
2276
"a744d582b3a34d14d311b7629da06d003045ae77cebceeb4e0e72734d63bd07d" ,
2300
2277
"fad25a5ea15d4541258af8785acaf697a886c1b872c793790e60a6837b1adbc0" ,
2301
2278
] ,
2302
- vec![
2303
- "80a6ff33494c471c5eff7efb9febfbcf30a946fe6535b3451cda79f2154a7095" ,
2304
- "57ac03913309b3f8cd3c3d4c49d878bb21f4d97dc74a1eaccbe5c601f7f06f47" ,
2305
- ] ,
2306
2279
vec![
2307
2280
"f06fc939bc10551a0fd415aebf107ef0b9c4ee1ef9a164157bdd089127782617" ,
2308
2281
"785b2a6a00a5579cc9da1ff997ce8339b6f9fb46c6f10cf7a12ff2986341a6e0" ,
2309
2282
] ,
2283
+ // Non Least-Square-Root representative values. (i.e. representative > 2^254-10 )
2284
+ vec![
2285
+ "84cbe9accdd32b46f4a8ef51c85fd39d028711f77fb00e204a613fc235fd68b9" ,
2286
+ "93c73e0289afd1d1fc9e4e78a505d5d1b2642fbdf91a1eff7d281930654b1453" ,
2287
+ ] ,
2288
+ vec![
2289
+ "48b73039db6fcdcb6030c4a38e8be80b6390d8ae46890e77e623f87254ef149c" ,
2290
+ "ca11b25acbc80566603eabeb9364ebd50e0306424c61049e1ce9385d9f349966" ,
2291
+ ] ,
2292
+ vec![
2293
+ "80a6ff33494c471c5eff7efb9febfbcf30a946fe6535b3451cda79f2154a7095" ,
2294
+ "57ac03913309b3f8cd3c3d4c49d878bb21f4d97dc74a1eaccbe5c601f7f06f47" ,
2295
+ ] ,
2310
2296
]
2311
2297
}
2312
2298
2313
2299
#[ test]
2314
2300
#[ allow( deprecated) ]
2315
2301
#[ cfg( all( feature = "alloc" , feature = "digest" ) ) ]
2316
2302
fn elligator_signal_test_vectors ( ) {
2317
- for vector in test_vectors ( ) . iter ( ) {
2318
- let input = hex:: decode ( vector[ 0 ] ) . unwrap ( ) ;
2319
- let output = hex:: decode ( vector[ 1 ] ) . unwrap ( ) ;
2303
+ for ( n , vector) in test_vectors ( ) . iter ( ) . enumerate ( ) {
2304
+ let input = hex:: decode ( vector[ 0 ] ) . expect ( "failed to decode hex input" ) ;
2305
+ let output = hex:: decode ( vector[ 1 ] ) . expect ( "failed to decode hex output" ) ;
2320
2306
2321
2307
let point = EdwardsPoint :: nonspec_map_to_curve :: < sha2:: Sha512 > ( & input) ;
2322
- assert_eq ! ( point. compress( ) . to_bytes( ) , output[ ..] ) ;
2308
+ assert_eq ! (
2309
+ hex:: encode( point. compress( ) . to_bytes( ) ) ,
2310
+ hex:: encode( & output[ ..] ) ,
2311
+ "signal map_to_curve failed for test {n}"
2312
+ ) ;
2323
2313
}
2324
2314
}
2325
2315
}
0 commit comments