1
1
#![ no_std]
2
2
3
- use ed448_goldilocks:: MontgomeryPoint ;
4
- use ed448_goldilocks:: Scalar ;
3
+ use ed448_goldilocks:: MontgomeryScalar ;
4
+ use ed448_goldilocks:: MontgomeryXpoint ;
5
+ use ed448_goldilocks:: elliptic_curve:: { bigint:: U448 , scalar:: FromUintUnchecked } ;
5
6
use rand_core:: { CryptoRng , RngCore } ;
6
7
use zeroize:: Zeroize ;
7
8
@@ -20,24 +21,26 @@ impl From<[u8; 56]> for Secret {
20
21
/// XXX: Waiting for upstream PR to use pre-computation
21
22
impl From < & Secret > for PublicKey {
22
23
fn from ( secret : & Secret ) -> PublicKey {
23
- let point = & MontgomeryPoint :: GENERATOR * & Scalar :: from_bytes ( & secret. 0 ) ;
24
- PublicKey ( point)
24
+ let secret = secret. as_scalar ( ) ;
25
+ let point = & MontgomeryXpoint :: GENERATOR * & secret;
26
+ PublicKey ( point. to_affine ( ) )
25
27
}
26
28
}
27
29
28
30
/// A PublicKey is a point on Curve448.
29
- pub struct PublicKey ( MontgomeryPoint ) ;
31
+ #[ derive( Debug , PartialEq , Eq , Copy , Clone ) ]
32
+ pub struct PublicKey ( MontgomeryXpoint ) ;
30
33
31
34
/// A Secret is a Scalar on Curve448.
32
- #[ derive( Zeroize ) ]
35
+ #[ derive( Clone , Zeroize ) ]
33
36
#[ zeroize( drop) ]
34
37
pub struct Secret ( [ u8 ; 56 ] ) ;
35
38
36
39
/// A SharedSecret is a point on Curve448.
37
40
/// This point is the result of a Diffie-Hellman key exchange.
38
41
#[ derive( Zeroize ) ]
39
42
#[ zeroize( drop) ]
40
- pub struct SharedSecret ( MontgomeryPoint ) ;
43
+ pub struct SharedSecret ( MontgomeryXpoint ) ;
41
44
42
45
impl PublicKey {
43
46
/// Converts a bytes slice into a Public key
@@ -62,7 +65,7 @@ impl PublicKey {
62
65
63
66
// Check if the point has low order
64
67
let arr = slice_to_array ( bytes) ;
65
- let point = MontgomeryPoint ( arr) ;
68
+ let point = MontgomeryXpoint ( arr) ;
66
69
67
70
Some ( PublicKey ( point) )
68
71
}
@@ -85,7 +88,7 @@ impl Secret {
85
88
// Taken from dalek-x25519
86
89
pub fn new < T > ( csprng : & mut T ) -> Self
87
90
where
88
- T : RngCore + CryptoRng ,
91
+ T : RngCore + CryptoRng + ? Sized ,
89
92
{
90
93
let mut bytes = [ 0u8 ; 56 ] ;
91
94
@@ -101,8 +104,9 @@ impl Secret {
101
104
}
102
105
103
106
/// Views a Secret as a Scalar
104
- fn as_scalar ( & self ) -> Scalar {
105
- Scalar :: from_bytes ( & self . 0 )
107
+ fn as_scalar ( & self ) -> MontgomeryScalar {
108
+ let secret = U448 :: from_le_slice ( & self . 0 ) ;
109
+ MontgomeryScalar :: from_uint_unchecked ( secret)
106
110
}
107
111
108
112
/// Performs a Diffie-hellman key exchange between the secret key and an external public key
@@ -112,7 +116,7 @@ impl Secret {
112
116
return None ;
113
117
}
114
118
let shared_key = & public_key. 0 * & self . as_scalar ( ) ;
115
- Some ( SharedSecret ( shared_key) )
119
+ Some ( SharedSecret ( shared_key. to_affine ( ) ) )
116
120
}
117
121
118
122
/// Performs a Diffie-hellman key exchange once between the secret key and an external public key
@@ -152,17 +156,17 @@ fn slice_to_array(bytes: &[u8]) -> [u8; 56] {
152
156
pub fn x448 ( scalar_bytes : [ u8 ; 56 ] , point_bytes : [ u8 ; 56 ] ) -> Option < [ u8 ; 56 ] > {
153
157
let point = PublicKey :: from_bytes ( & point_bytes) ?;
154
158
let scalar = Secret :: from ( scalar_bytes) . as_scalar ( ) ;
155
- Some ( ( & point. 0 * & scalar) . 0 )
159
+ Some ( ( & point. 0 * & scalar) . to_affine ( ) . 0 )
156
160
}
157
161
/// An unchecked version of the x448 function defined in RFC448
158
162
/// No checks are made on the points.
159
163
pub fn x448_unchecked ( scalar_bytes : [ u8 ; 56 ] , point_bytes : [ u8 ; 56 ] ) -> [ u8 ; 56 ] {
160
- let point = MontgomeryPoint ( point_bytes) ;
164
+ let point = MontgomeryXpoint ( point_bytes) ;
161
165
let scalar = Secret :: from ( scalar_bytes) . as_scalar ( ) ;
162
- ( & point * & scalar) . 0
166
+ ( & point * & scalar) . to_affine ( ) . 0
163
167
}
164
168
165
- pub const X448_BASEPOINT_BYTES : [ u8 ; 56 ] = MontgomeryPoint :: GENERATOR . 0 ;
169
+ pub const X448_BASEPOINT_BYTES : [ u8 ; 56 ] = MontgomeryXpoint :: GENERATOR . 0 ;
166
170
167
171
#[ cfg( test) ]
168
172
mod test {
@@ -173,38 +177,18 @@ mod test {
173
177
174
178
#[ test]
175
179
fn test_low_order ( ) {
176
- // These are also in ed448-goldilocks. We could export them, but I cannot see any use except for this test.
177
- const LOW_A : MontgomeryPoint = MontgomeryPoint ( [
178
- 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
179
- 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
180
- 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
181
- 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
182
- ] ) ;
183
- const LOW_B : MontgomeryPoint = MontgomeryPoint ( [
184
- 0x01 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
185
- 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
186
- 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
187
- 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
188
- ] ) ;
189
- const LOW_C : MontgomeryPoint = MontgomeryPoint ( [
190
- 0xfe , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff ,
191
- 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff ,
192
- 0xfe , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff ,
193
- 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff ,
194
- ] ) ;
195
-
196
180
// Notice, that this is the only way to add low order points into the system
197
181
// and this is not exposed to the user. The user will use `from_bytes` which will check for low order points.
198
- let bad_key_a = PublicKey ( LOW_A ) ;
199
- let checked_bad_key_a = PublicKey :: from_bytes ( & LOW_A . 0 ) ;
182
+ let bad_key_a = PublicKey ( MontgomeryXpoint :: LOW_A ) ;
183
+ let checked_bad_key_a = PublicKey :: from_bytes ( & MontgomeryXpoint :: LOW_A . 0 ) ;
200
184
assert ! ( checked_bad_key_a. is_none( ) ) ;
201
185
202
- let bad_key_b = PublicKey ( LOW_B ) ;
203
- let checked_bad_key_b = PublicKey :: from_bytes ( & LOW_B . 0 ) ;
186
+ let bad_key_b = PublicKey ( MontgomeryXpoint :: LOW_B ) ;
187
+ let checked_bad_key_b = PublicKey :: from_bytes ( & MontgomeryXpoint :: LOW_B . 0 ) ;
204
188
assert ! ( checked_bad_key_b. is_none( ) ) ;
205
189
206
- let bad_key_c = PublicKey ( LOW_C ) ;
207
- let checked_bad_key_c = PublicKey :: from_bytes ( & LOW_C . 0 ) ;
190
+ let bad_key_c = PublicKey ( MontgomeryXpoint :: LOW_C ) ;
191
+ let checked_bad_key_c = PublicKey :: from_bytes ( & MontgomeryXpoint :: LOW_C . 0 ) ;
208
192
assert ! ( checked_bad_key_c. is_none( ) ) ;
209
193
210
194
let mut rng = rand:: rng ( ) ;
@@ -392,8 +376,8 @@ mod test {
392
376
0xda , 0x8d , 0x52 , 0x4d , 0xe3 , 0xd6 , 0x9b , 0xd9 , 0xd9 , 0xd6 , 0x6b , 0x99 , 0x7e , 0x37 ,
393
377
] ;
394
378
395
- let mut point = MontgomeryPoint :: GENERATOR . 0 ;
396
- let mut scalar = MontgomeryPoint :: GENERATOR . 0 ;
379
+ let mut point = MontgomeryXpoint :: GENERATOR . 0 ;
380
+ let mut scalar = MontgomeryXpoint :: GENERATOR . 0 ;
397
381
let mut result = [ 0u8 ; 56 ] ;
398
382
399
383
// Iterate 1 time then check value on 1st iteration
0 commit comments