Skip to content

Commit 3fd8ac7

Browse files
authored
[WIP] elliptic-curve: extract toplevel Curve trait (#223)
This is a fairly substantial refactoring of the `elliptic-curve` crate which extracts a toplevel `elliptic_curve::Curve` trait and redefines all types to use it. The `elliptic_curve::weierstrass::Curve` trait is maintained, but relegated to a marker trait. That said, it's still used as the marker trait for all traits/types defined in the `elliptic_curve::weierstrass` module. Notably the main thing this facilitates is making `SecretKey` generic around a `C: elliptic_curve::Curve` generic type. The previous impetus was to avoid directly associating types dependent on scalars with specific elliptic curves (rather the curve's order), but this is ultimately unhelpful as it precludes accounting for trait impls on the curve in trait bounds. With the new approach, we can use trait bounds to conditionally define methods on `SecretKey`, e.g. bounding a `SecretKey::generate` impl on curves which impl `Arithmetic where Self::Scalar: Generate`. This would eliminate the need for a special `GenerateSecretKey` trait. One other notable change is the associated type for computing type sizes for a particular curve has been renamed to `ElementSize`, rather than the previous `ScalarSize`. This hopefully captures that this size is for all elements related to a particular curve, i.e. both the base and scalar fields.
1 parent 8d67bb6 commit 3fd8ac7

File tree

6 files changed

+148
-149
lines changed

6 files changed

+148
-149
lines changed

elliptic-curve/src/lib.rs

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,16 +36,46 @@ pub use subtle;
3636
#[cfg(feature = "rand_core")]
3737
pub use rand_core;
3838

39+
use core::{fmt::Debug, ops::Add};
40+
use generic_array::{typenum::Unsigned, ArrayLength, GenericArray};
41+
3942
#[cfg(feature = "rand_core")]
4043
use rand_core::{CryptoRng, RngCore};
4144

42-
/// Byte array containing a serialized scalar value (i.e. an integer)
43-
pub type ScalarBytes<Size> = generic_array::GenericArray<u8, Size>;
45+
/// Elliptic curve.
46+
///
47+
/// This trait is intended to be impl'd by a ZST which represents a concrete
48+
/// elliptic curve.
49+
///
50+
/// Other traits in this crate which are bounded by [`Curve`] are intended to
51+
/// be impl'd by these ZSTs, facilitating types which are generic over elliptic
52+
/// curves (e.g. [`SecretKey`]).
53+
pub trait Curve: Clone + Debug + Default + Eq + Ord + Send + Sync {
54+
/// Number of bytes required to serialize elements of field elements
55+
/// associated with this curve, e.g. elements of the base/scalar fields.
56+
///
57+
/// This is used for computing the sizes for types related to this curve.
58+
type ElementSize: ArrayLength<u8> + Add + Eq + Ord + Unsigned;
59+
}
60+
61+
/// Elliptic curve with curve arithmetic support
62+
pub trait Arithmetic: Curve {
63+
/// Scalar type for a given curve
64+
type Scalar;
4465

45-
/// Trait for randomly generating a value
66+
/// Affine point type for a given curve
67+
type AffinePoint;
68+
}
69+
70+
/// Trait for randomly generating a value.
71+
///
72+
/// Primarily intended for use with scalar types for a particular curve.
4673
#[cfg(feature = "rand_core")]
4774
#[cfg_attr(docsrs, doc(cfg(feature = "rand_core")))]
4875
pub trait Generate {
4976
/// Generate a random element of this type using the provided [`CryptoRng`]
5077
fn generate(rng: impl CryptoRng + RngCore) -> Self;
5178
}
79+
80+
/// Byte array containing a serialized scalar value (i.e. an integer)
81+
pub type ScalarBytes<C> = GenericArray<u8, <C as Curve>::ElementSize>;

elliptic-curve/src/secret_key.rs

Lines changed: 16 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -7,35 +7,26 @@
77
//! When the `zeroize` feature of this crate is enabled, it also handles
88
//! zeroing it out of memory securely on drop.
99
10-
use crate::{error::Error, ScalarBytes};
10+
use crate::{error::Error, Curve, ScalarBytes};
1111
use core::{
1212
convert::{TryFrom, TryInto},
13-
fmt,
13+
fmt::{self, Debug},
1414
};
15-
use generic_array::ArrayLength;
15+
use generic_array::{typenum::Unsigned, GenericArray};
1616

17-
/// Secret keys.
17+
/// Elliptic curve secret keys.
1818
///
19-
/// In elliptic curve cryptography, secret keys are concretely privately known
20-
/// scalar values.
21-
///
22-
/// This type wraps a (serialized) scalar value, helping to prevent accidental
19+
/// This type wraps a serialized scalar value, helping to prevent accidental
2320
/// exposure and securely erasing the value from memory when dropped
2421
/// (when the `zeroize` feature of this crate is enabled).
25-
pub struct SecretKey<ScalarSize>
26-
where
27-
ScalarSize: ArrayLength<u8>,
28-
{
22+
pub struct SecretKey<C: Curve> {
2923
/// Private scalar value
30-
scalar: ScalarBytes<ScalarSize>,
24+
scalar: ScalarBytes<C>,
3125
}
3226

33-
impl<ScalarSize> SecretKey<ScalarSize>
34-
where
35-
ScalarSize: ArrayLength<u8>,
36-
{
27+
impl<C: Curve> SecretKey<C> {
3728
/// Create a new secret key from a serialized scalar value
38-
pub fn new(bytes: ScalarBytes<ScalarSize>) -> Self {
29+
pub fn new(bytes: ScalarBytes<C>) -> Self {
3930
Self { scalar: bytes }
4031
}
4132

@@ -45,42 +36,33 @@ where
4536
}
4637

4738
/// Expose the secret [`ScalarBytes`] value this [`SecretKey`] wraps
48-
pub fn secret_scalar(&self) -> &ScalarBytes<ScalarSize> {
39+
pub fn secret_scalar(&self) -> &ScalarBytes<C> {
4940
&self.scalar
5041
}
5142
}
5243

53-
impl<ScalarSize> TryFrom<&[u8]> for SecretKey<ScalarSize>
54-
where
55-
ScalarSize: ArrayLength<u8>,
56-
{
44+
impl<C: Curve> TryFrom<&[u8]> for SecretKey<C> {
5745
type Error = Error;
5846

5947
fn try_from(slice: &[u8]) -> Result<Self, Error> {
60-
if slice.len() == ScalarSize::to_usize() {
48+
if slice.len() == C::ElementSize::to_usize() {
6149
Ok(SecretKey {
62-
scalar: ScalarBytes::clone_from_slice(slice),
50+
scalar: GenericArray::clone_from_slice(slice),
6351
})
6452
} else {
6553
Err(Error)
6654
}
6755
}
6856
}
6957

70-
impl<ScalarSize> fmt::Debug for SecretKey<ScalarSize>
71-
where
72-
ScalarSize: ArrayLength<u8>,
73-
{
58+
impl<C: Curve> Debug for SecretKey<C> {
7459
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
75-
write!(f, "SecretKey<U{}>{{ ... }}", ScalarSize::to_usize())
60+
write!(f, "SecretKey<{:?}>{{ ... }}", C::default())
7661
}
7762
}
7863

7964
#[cfg(feature = "zeroize")]
80-
impl<ScalarSize> Drop for SecretKey<ScalarSize>
81-
where
82-
ScalarSize: ArrayLength<u8>,
83-
{
65+
impl<C: Curve> Drop for SecretKey<C> {
8466
fn drop(&mut self) {
8567
use zeroize::Zeroize;
8668
self.scalar.zeroize();

elliptic-curve/src/weierstrass.rs

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
//! Elliptic curves in short Weierstrass form.
22
3-
pub mod curve;
43
pub mod point;
54
pub mod public_key;
65

7-
pub use curve::Curve;
8-
pub use point::{CompressedPoint, CompressedPointSize, UncompressedPoint, UncompressedPointSize};
9-
pub use public_key::PublicKey;
6+
pub use self::{
7+
point::{CompressedPoint, CompressedPointSize, UncompressedPoint, UncompressedPointSize},
8+
public_key::PublicKey,
9+
};
1010

1111
use crate::{consts::U1, ScalarBytes};
1212
use core::ops::Add;
@@ -19,21 +19,25 @@ use crate::secret_key::SecretKey;
1919
#[cfg(feature = "rand_core")]
2020
use rand_core::{CryptoRng, RngCore};
2121

22+
/// Marker trait for elliptic curves in short Weierstrass form
23+
pub trait Curve: super::Curve {}
24+
2225
/// Fixed-base scalar multiplication
2326
pub trait FixedBaseScalarMul: Curve
2427
where
25-
<Self::ScalarSize as Add>::Output: Add<U1>,
26-
CompressedPoint<Self>: From<Self::Point>,
27-
UncompressedPoint<Self>: From<Self::Point>,
28-
CompressedPointSize<Self::ScalarSize>: ArrayLength<u8>,
29-
UncompressedPointSize<Self::ScalarSize>: ArrayLength<u8>,
28+
Self::ElementSize: Add<U1>,
29+
<Self::ElementSize as Add>::Output: Add<U1>,
30+
CompressedPoint<Self>: From<Self::AffinePoint>,
31+
UncompressedPoint<Self>: From<Self::AffinePoint>,
32+
CompressedPointSize<Self>: ArrayLength<u8>,
33+
UncompressedPointSize<Self>: ArrayLength<u8>,
3034
{
31-
/// Elliptic curve point type
32-
type Point: ConditionallySelectable;
35+
/// Affine point type for this elliptic curve
36+
type AffinePoint: ConditionallySelectable;
3337

3438
/// Multiply the given scalar by the generator point for this elliptic
3539
/// curve.
36-
fn mul_base(scalar: &ScalarBytes<Self::ScalarSize>) -> CtOption<Self::Point>;
40+
fn mul_base(scalar: &ScalarBytes<Self>) -> CtOption<Self::AffinePoint>;
3741
}
3842

3943
/// Generate a secret key for this elliptic curve
@@ -42,5 +46,5 @@ where
4246
pub trait GenerateSecretKey: Curve {
4347
/// Generate a random [`SecretKey`] for this elliptic curve using the
4448
/// provided [`CryptoRng`]
45-
fn generate_secret_key(rng: impl CryptoRng + RngCore) -> SecretKey<Self::ScalarSize>;
49+
fn generate_secret_key(rng: impl CryptoRng + RngCore) -> SecretKey<Self>;
4650
}

elliptic-curve/src/weierstrass/curve.rs

Lines changed: 0 additions & 29 deletions
This file was deleted.

0 commit comments

Comments
 (0)