Skip to content

Commit 7d81302

Browse files
authored
elliptic-curve: add AffineXCoordinate trait (#817)
Protocols like ECDH and ECDSA rely on x-coordinate access. We've tried various ways of trying to keep affine coordinate access out of the public API, but it complicates generic implementations of these protocols. Most recently RustCrypto/signatures#395 attempted to add a trait which encapsulated ECDSA signing, but a similar (or expaned version of the same) trait is needed for verification. All of these problems go away, and can be expressed with simple trait bounds, if there is some way to access the x-coordinate of an `AffinePoint` as serialized `FieldBytes`. This commit adds such a trait: `AffineXCoordinate`, which is a mandatory bound of `AffineArithmetic::AffinePoint`.
1 parent f484ed6 commit 7d81302

File tree

5 files changed

+44
-22
lines changed

5 files changed

+44
-22
lines changed

elliptic-curve/src/arithmetic.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! Elliptic curve arithmetic traits.
22
3-
use crate::{Curve, FieldBytes, IsHigh, PrimeCurve, ScalarCore};
3+
use crate::{AffineXCoordinate, Curve, FieldBytes, IsHigh, PrimeCurve, ScalarCore};
44
use core::fmt::Debug;
55
use subtle::{ConditionallySelectable, ConstantTimeEq};
66
use zeroize::DefaultIsZeroes;
@@ -10,6 +10,7 @@ use zeroize::DefaultIsZeroes;
1010
pub trait AffineArithmetic: Curve + ScalarArithmetic {
1111
/// Elliptic curve point in affine coordinates.
1212
type AffinePoint: 'static
13+
+ AffineXCoordinate<Self>
1314
+ Copy
1415
+ Clone
1516
+ ConditionallySelectable

elliptic-curve/src/dev.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ use crate::{
1212
sec1::{FromEncodedPoint, ToEncodedPoint},
1313
subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption},
1414
zeroize::DefaultIsZeroes,
15-
AffineArithmetic, AlgorithmParameters, Curve, IsHigh, PrimeCurve, ProjectiveArithmetic,
16-
ScalarArithmetic,
15+
AffineArithmetic, AffineXCoordinate, AlgorithmParameters, Curve, IsHigh, PrimeCurve,
16+
ProjectiveArithmetic, ScalarArithmetic,
1717
};
1818
use core::{
1919
iter::Sum,
@@ -368,6 +368,12 @@ pub enum AffinePoint {
368368
Other(EncodedPoint),
369369
}
370370

371+
impl AffineXCoordinate<MockCurve> for AffinePoint {
372+
fn x(&self) -> FieldBytes {
373+
unimplemented!();
374+
}
375+
}
376+
371377
impl ConstantTimeEq for AffinePoint {
372378
fn ct_eq(&self, _other: &Self) -> Choice {
373379
unimplemented!();

elliptic-curve/src/ecdh.rs

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@
2727
//! [SIGMA]: https://webee.technion.ac.il/~hugo/sigma-pdf.pdf
2828
2929
use crate::{
30-
AffinePoint, Curve, FieldBytes, NonZeroScalar, ProjectiveArithmetic, ProjectivePoint, PublicKey,
30+
AffineArithmetic, AffinePoint, AffineXCoordinate, Curve, FieldBytes, NonZeroScalar,
31+
ProjectiveArithmetic, ProjectivePoint, PublicKey,
3132
};
3233
use core::borrow::Borrow;
3334
use group::Curve as _;
@@ -60,13 +61,10 @@ pub fn diffie_hellman<C>(
6061
) -> SharedSecret<C>
6162
where
6263
C: Curve + ProjectiveArithmetic,
63-
SharedSecret<C>: for<'a> From<&'a AffinePoint<C>>,
6464
{
6565
let public_point = ProjectivePoint::<C>::from(*public_key.borrow());
66-
let mut secret_point = (public_point * secret_key.borrow().as_ref()).to_affine();
67-
let shared_secret = SharedSecret::from(&secret_point);
68-
secret_point.zeroize();
69-
shared_secret
66+
let secret_point = (public_point * secret_key.borrow().as_ref()).to_affine();
67+
SharedSecret::new(secret_point)
7068
}
7169

7270
/// Ephemeral Diffie-Hellman Secret.
@@ -100,7 +98,6 @@ where
10098
impl<C> EphemeralSecret<C>
10199
where
102100
C: Curve + ProjectiveArithmetic,
103-
SharedSecret<C>: for<'a> From<&'a AffinePoint<C>>,
104101
{
105102
/// Generate a cryptographically random [`EphemeralSecret`].
106103
pub fn random(rng: impl CryptoRng + RngCore) -> Self {
@@ -126,7 +123,6 @@ where
126123
impl<C> From<&EphemeralSecret<C>> for PublicKey<C>
127124
where
128125
C: Curve + ProjectiveArithmetic,
129-
SharedSecret<C>: for<'a> From<&'a AffinePoint<C>>,
130126
{
131127
fn from(ephemeral_secret: &EphemeralSecret<C>) -> Self {
132128
ephemeral_secret.public_key()
@@ -172,6 +168,17 @@ pub struct SharedSecret<C: Curve> {
172168
}
173169

174170
impl<C: Curve> SharedSecret<C> {
171+
/// Create a new [`SharedSecret`] from an [`AffinePoint`] for this curve.
172+
#[inline]
173+
fn new(point: AffinePoint<C>) -> Self
174+
where
175+
C: AffineArithmetic,
176+
{
177+
Self {
178+
secret_bytes: point.x(),
179+
}
180+
}
181+
175182
/// Shared secret value, serialized as bytes.
176183
///
177184
/// As noted in the comments for this struct, this value is non-uniform and

elliptic-curve/src/lib.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,9 @@ mod jwk;
7878

7979
pub use crate::{
8080
error::{Error, Result},
81-
point::{DecompactPoint, DecompressPoint, PointCompaction, PointCompression},
81+
point::{
82+
AffineXCoordinate, DecompactPoint, DecompressPoint, PointCompaction, PointCompression,
83+
},
8284
scalar::{core::ScalarCore, IsHigh},
8385
secret_key::SecretKey,
8486
};

elliptic-curve/src/point.rs

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,10 @@
33
use crate::{Curve, FieldBytes};
44
use subtle::{Choice, CtOption};
55

6-
/// Point compression settings.
7-
pub trait PointCompression {
8-
/// Should point compression be applied by default?
9-
const COMPRESS_POINTS: bool;
10-
}
11-
12-
/// Point compaction settings.
13-
pub trait PointCompaction {
14-
/// Should point compaction be applied by default?
15-
const COMPACT_POINTS: bool;
6+
/// Obtain the affine x-coordinate of an elliptic curve point.
7+
pub trait AffineXCoordinate<C: Curve> {
8+
/// Get the affine x-coordinate as a serialized field element.
9+
fn x(&self) -> FieldBytes<C>;
1610
}
1711

1812
/// Attempt to decompress an elliptic curve point from its x-coordinate and
@@ -27,3 +21,15 @@ pub trait DecompactPoint<C: Curve>: Sized {
2721
/// Attempt to decompact an elliptic curve point
2822
fn decompact(x: &FieldBytes<C>) -> CtOption<Self>;
2923
}
24+
25+
/// Point compression settings.
26+
pub trait PointCompression {
27+
/// Should point compression be applied by default?
28+
const COMPRESS_POINTS: bool;
29+
}
30+
31+
/// Point compaction settings.
32+
pub trait PointCompaction {
33+
/// Should point compaction be applied by default?
34+
const COMPACT_POINTS: bool;
35+
}

0 commit comments

Comments
 (0)