Skip to content

Commit 70cd31c

Browse files
committed
x448: api fixups
1 parent c2d518b commit 70cd31c

File tree

1 file changed

+29
-44
lines changed

1 file changed

+29
-44
lines changed

x448/src/lib.rs

Lines changed: 29 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
#![no_std]
22

3-
use ed448_goldilocks::MontgomeryPoint;
4-
use ed448_goldilocks::Scalar;
3+
use ed448_goldilocks::{
4+
MontgomeryScalar, MontgomeryXpoint,
5+
elliptic_curve::{bigint::U448, scalar::FromUintUnchecked},
6+
};
57
use rand_core::{CryptoRng, RngCore};
68
use zeroize::Zeroize;
79

@@ -20,24 +22,26 @@ impl From<[u8; 56]> for Secret {
2022
/// XXX: Waiting for upstream PR to use pre-computation
2123
impl From<&Secret> for PublicKey {
2224
fn from(secret: &Secret) -> PublicKey {
23-
let point = &MontgomeryPoint::GENERATOR * &Scalar::from_bytes(&secret.0);
24-
PublicKey(point)
25+
let secret = secret.as_scalar();
26+
let point = &MontgomeryXpoint::GENERATOR * &secret;
27+
PublicKey(point.to_affine())
2528
}
2629
}
2730

2831
/// A PublicKey is a point on Curve448.
29-
pub struct PublicKey(MontgomeryPoint);
32+
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
33+
pub struct PublicKey(MontgomeryXpoint);
3034

3135
/// A Secret is a Scalar on Curve448.
32-
#[derive(Zeroize)]
36+
#[derive(Clone, Zeroize)]
3337
#[zeroize(drop)]
3438
pub struct Secret([u8; 56]);
3539

3640
/// A SharedSecret is a point on Curve448.
3741
/// This point is the result of a Diffie-Hellman key exchange.
3842
#[derive(Zeroize)]
3943
#[zeroize(drop)]
40-
pub struct SharedSecret(MontgomeryPoint);
44+
pub struct SharedSecret(MontgomeryXpoint);
4145

4246
impl PublicKey {
4347
/// Converts a bytes slice into a Public key
@@ -62,7 +66,7 @@ impl PublicKey {
6266

6367
// Check if the point has low order
6468
let arr = slice_to_array(bytes);
65-
let point = MontgomeryPoint(arr);
69+
let point = MontgomeryXpoint(arr);
6670

6771
Some(PublicKey(point))
6872
}
@@ -85,7 +89,7 @@ impl Secret {
8589
// Taken from dalek-x25519
8690
pub fn new<T>(csprng: &mut T) -> Self
8791
where
88-
T: RngCore + CryptoRng,
92+
T: RngCore + CryptoRng + ?Sized,
8993
{
9094
let mut bytes = [0u8; 56];
9195

@@ -101,8 +105,9 @@ impl Secret {
101105
}
102106

103107
/// Views a Secret as a Scalar
104-
fn as_scalar(&self) -> Scalar {
105-
Scalar::from_bytes(&self.0)
108+
fn as_scalar(&self) -> MontgomeryScalar {
109+
let secret = U448::from_le_slice(&self.0);
110+
MontgomeryScalar::from_uint_unchecked(secret)
106111
}
107112

108113
/// Performs a Diffie-hellman key exchange between the secret key and an external public key
@@ -112,7 +117,7 @@ impl Secret {
112117
return None;
113118
}
114119
let shared_key = &public_key.0 * &self.as_scalar();
115-
Some(SharedSecret(shared_key))
120+
Some(SharedSecret(shared_key.to_affine()))
116121
}
117122

118123
/// Performs a Diffie-hellman key exchange once between the secret key and an external public key
@@ -152,17 +157,17 @@ fn slice_to_array(bytes: &[u8]) -> [u8; 56] {
152157
pub fn x448(scalar_bytes: [u8; 56], point_bytes: [u8; 56]) -> Option<[u8; 56]> {
153158
let point = PublicKey::from_bytes(&point_bytes)?;
154159
let scalar = Secret::from(scalar_bytes).as_scalar();
155-
Some((&point.0 * &scalar).0)
160+
Some((&point.0 * &scalar).to_affine().0)
156161
}
157162
/// An unchecked version of the x448 function defined in RFC448
158163
/// No checks are made on the points.
159164
pub fn x448_unchecked(scalar_bytes: [u8; 56], point_bytes: [u8; 56]) -> [u8; 56] {
160-
let point = MontgomeryPoint(point_bytes);
165+
let point = MontgomeryXpoint(point_bytes);
161166
let scalar = Secret::from(scalar_bytes).as_scalar();
162-
(&point * &scalar).0
167+
(&point * &scalar).to_affine().0
163168
}
164169

165-
pub const X448_BASEPOINT_BYTES: [u8; 56] = MontgomeryPoint::GENERATOR.0;
170+
pub const X448_BASEPOINT_BYTES: [u8; 56] = MontgomeryXpoint::GENERATOR.0;
166171

167172
#[cfg(test)]
168173
mod test {
@@ -173,38 +178,18 @@ mod test {
173178

174179
#[test]
175180
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-
196181
// Notice, that this is the only way to add low order points into the system
197182
// 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);
183+
let bad_key_a = PublicKey(MontgomeryXpoint::LOW_A);
184+
let checked_bad_key_a = PublicKey::from_bytes(&MontgomeryXpoint::LOW_A.0);
200185
assert!(checked_bad_key_a.is_none());
201186

202-
let bad_key_b = PublicKey(LOW_B);
203-
let checked_bad_key_b = PublicKey::from_bytes(&LOW_B.0);
187+
let bad_key_b = PublicKey(MontgomeryXpoint::LOW_B);
188+
let checked_bad_key_b = PublicKey::from_bytes(&MontgomeryXpoint::LOW_B.0);
204189
assert!(checked_bad_key_b.is_none());
205190

206-
let bad_key_c = PublicKey(LOW_C);
207-
let checked_bad_key_c = PublicKey::from_bytes(&LOW_C.0);
191+
let bad_key_c = PublicKey(MontgomeryXpoint::LOW_C);
192+
let checked_bad_key_c = PublicKey::from_bytes(&MontgomeryXpoint::LOW_C.0);
208193
assert!(checked_bad_key_c.is_none());
209194

210195
let mut rng = rand::rng();
@@ -392,8 +377,8 @@ mod test {
392377
0xda, 0x8d, 0x52, 0x4d, 0xe3, 0xd6, 0x9b, 0xd9, 0xd9, 0xd6, 0x6b, 0x99, 0x7e, 0x37,
393378
];
394379

395-
let mut point = MontgomeryPoint::GENERATOR.0;
396-
let mut scalar = MontgomeryPoint::GENERATOR.0;
380+
let mut point = MontgomeryXpoint::GENERATOR.0;
381+
let mut scalar = MontgomeryXpoint::GENERATOR.0;
397382
let mut result = [0u8; 56];
398383

399384
// Iterate 1 time then check value on 1st iteration

0 commit comments

Comments
 (0)