Skip to content

Commit 336ded9

Browse files
committed
x448: api fixups
1 parent 4f40906 commit 336ded9

File tree

1 file changed

+28
-44
lines changed

1 file changed

+28
-44
lines changed

x448/src/lib.rs

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

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};
56
use rand_core::{CryptoRng, RngCore};
67
use zeroize::Zeroize;
78

@@ -20,24 +21,26 @@ impl From<[u8; 56]> for Secret {
2021
/// XXX: Waiting for upstream PR to use pre-computation
2122
impl From<&Secret> for PublicKey {
2223
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())
2527
}
2628
}
2729

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

3134
/// A Secret is a Scalar on Curve448.
32-
#[derive(Zeroize)]
35+
#[derive(Clone, Zeroize)]
3336
#[zeroize(drop)]
3437
pub struct Secret([u8; 56]);
3538

3639
/// A SharedSecret is a point on Curve448.
3740
/// This point is the result of a Diffie-Hellman key exchange.
3841
#[derive(Zeroize)]
3942
#[zeroize(drop)]
40-
pub struct SharedSecret(MontgomeryPoint);
43+
pub struct SharedSecret(MontgomeryXpoint);
4144

4245
impl PublicKey {
4346
/// Converts a bytes slice into a Public key
@@ -62,7 +65,7 @@ impl PublicKey {
6265

6366
// Check if the point has low order
6467
let arr = slice_to_array(bytes);
65-
let point = MontgomeryPoint(arr);
68+
let point = MontgomeryXpoint(arr);
6669

6770
Some(PublicKey(point))
6871
}
@@ -85,7 +88,7 @@ impl Secret {
8588
// Taken from dalek-x25519
8689
pub fn new<T>(csprng: &mut T) -> Self
8790
where
88-
T: RngCore + CryptoRng,
91+
T: RngCore + CryptoRng + ?Sized,
8992
{
9093
let mut bytes = [0u8; 56];
9194

@@ -101,8 +104,9 @@ impl Secret {
101104
}
102105

103106
/// 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)
106110
}
107111

108112
/// Performs a Diffie-hellman key exchange between the secret key and an external public key
@@ -112,7 +116,7 @@ impl Secret {
112116
return None;
113117
}
114118
let shared_key = &public_key.0 * &self.as_scalar();
115-
Some(SharedSecret(shared_key))
119+
Some(SharedSecret(shared_key.to_affine()))
116120
}
117121

118122
/// 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] {
152156
pub fn x448(scalar_bytes: [u8; 56], point_bytes: [u8; 56]) -> Option<[u8; 56]> {
153157
let point = PublicKey::from_bytes(&point_bytes)?;
154158
let scalar = Secret::from(scalar_bytes).as_scalar();
155-
Some((&point.0 * &scalar).0)
159+
Some((&point.0 * &scalar).to_affine().0)
156160
}
157161
/// An unchecked version of the x448 function defined in RFC448
158162
/// No checks are made on the points.
159163
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);
161165
let scalar = Secret::from(scalar_bytes).as_scalar();
162-
(&point * &scalar).0
166+
(&point * &scalar).to_affine().0
163167
}
164168

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

167171
#[cfg(test)]
168172
mod test {
@@ -173,38 +177,18 @@ mod test {
173177

174178
#[test]
175179
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-
196180
// Notice, that this is the only way to add low order points into the system
197181
// 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);
200184
assert!(checked_bad_key_a.is_none());
201185

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);
204188
assert!(checked_bad_key_b.is_none());
205189

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);
208192
assert!(checked_bad_key_c.is_none());
209193

210194
let mut rng = rand::rng();
@@ -392,8 +376,8 @@ mod test {
392376
0xda, 0x8d, 0x52, 0x4d, 0xe3, 0xd6, 0x9b, 0xd9, 0xd9, 0xd6, 0x6b, 0x99, 0x7e, 0x37,
393377
];
394378

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;
397381
let mut result = [0u8; 56];
398382

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

0 commit comments

Comments
 (0)