Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 12 additions & 4 deletions elliptic-curve/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ extern crate std;
pub mod error;
pub mod oid;
pub mod ops;
pub mod point;
pub mod scalar;
pub mod secret_key;

// TODO(tarcieri): other curve forms
Expand All @@ -41,9 +43,12 @@ pub use rand_core;
#[cfg(feature = "zeroize")]
pub use zeroize;

use core::{fmt::Debug, ops::Add};
use core::{
fmt::Debug,
ops::{Add, Mul},
};
use generic_array::{typenum::Unsigned, ArrayLength, GenericArray};
use subtle::ConditionallySelectable;
use subtle::{ConditionallySelectable, ConstantTimeEq};

#[cfg(feature = "rand_core")]
use rand_core::{CryptoRng, RngCore};
Expand All @@ -67,10 +72,13 @@ pub trait Curve: Clone + Debug + Default + Eq + Ord + Send + Sync {
/// Elliptic curve with curve arithmetic support
pub trait Arithmetic: Curve {
/// Scalar type for a given curve
type Scalar: ConditionallySelectable + Default + secret_key::FromSecretKey<Self>;
type Scalar: ConditionallySelectable
+ ConstantTimeEq
+ Default
+ secret_key::FromSecretKey<Self>;

/// Affine point type for a given curve
type AffinePoint: ConditionallySelectable + ops::MulBase<Scalar = Self::Scalar>;
type AffinePoint: ConditionallySelectable + Mul<scalar::NonZeroScalar<Self>> + point::Generator;
}

/// Associate an object identifier (OID) with a curve
Expand Down
11 changes: 0 additions & 11 deletions elliptic-curve/src/ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,3 @@ pub trait Invert {
/// Invert a field element.
fn invert(&self) -> CtOption<Self::Output>;
}

/// Fixed-base scalar multiplication.
///
/// This trait is intended to be implemented on a point type.
pub trait MulBase: Sized {
/// Scalar type
type Scalar;

/// Multiply scalar by the generator point for the elliptic curve
fn mul_base(scalar: &Self::Scalar) -> CtOption<Self>;
}
7 changes: 7 additions & 0 deletions elliptic-curve/src/point.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
//! Traits for elliptic curve points

/// Obtain the generator point.
pub trait Generator {
/// Get the generator point for this elliptic curve
fn generator() -> Self;
}
51 changes: 51 additions & 0 deletions elliptic-curve/src/scalar.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
//! Scalar types

use crate::{Arithmetic, Curve};
use subtle::{ConstantTimeEq, CtOption};

#[cfg(feature = "zeroize")]
use zeroize::Zeroize;

/// Non-zero scalar type.
///
/// This type ensures that its value is not zero, ala `core::num::NonZero*`.
/// To do this, the generic `S` type must impl both `Default` and
/// `ConstantTimeEq`, with the requirement that `S::default()` returns 0.
///
/// In the context of ECC, it's useful for ensuring that scalar multiplication
/// cannot result in the point at infinity.
pub struct NonZeroScalar<C: Curve + Arithmetic> {
scalar: C::Scalar,
}

impl<C> NonZeroScalar<C>
where
C: Curve + Arithmetic,
{
/// Create a [`NonZeroScalar`] from a scalar, performing a constant-time
/// check that it's non-zero.
pub fn new(scalar: C::Scalar) -> CtOption<Self> {
let is_zero = scalar.ct_eq(&C::Scalar::default());
CtOption::new(Self { scalar }, !is_zero)
}
}

impl<C> AsRef<C::Scalar> for NonZeroScalar<C>
where
C: Curve + Arithmetic,
{
fn as_ref(&self) -> &C::Scalar {
&self.scalar
}
}

#[cfg(feature = "zeroize")]
impl<C> Zeroize for NonZeroScalar<C>
where
C: Curve + Arithmetic,
C::Scalar: Zeroize,
{
fn zeroize(&mut self) {
self.scalar.zeroize();
}
}
17 changes: 11 additions & 6 deletions elliptic-curve/src/weierstrass/public_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,14 @@ use super::{
point::{CompressedPoint, CompressedPointSize, UncompressedPoint, UncompressedPointSize},
Curve,
};
use crate::{ops::MulBase, secret_key::FromSecretKey, Arithmetic, Error, SecretKey};
use core::fmt::{self, Debug};
use core::ops::Add;
use crate::{
point::Generator, scalar::NonZeroScalar, secret_key::FromSecretKey, Arithmetic, Error,
SecretKey,
};
use core::{
fmt::{self, Debug},
ops::{Add, Mul},
};
use generic_array::{
typenum::{Unsigned, U1},
ArrayLength, GenericArray,
Expand Down Expand Up @@ -107,6 +112,7 @@ where
impl<C> PublicKey<C>
where
C: Curve + Arithmetic,
C::AffinePoint: Mul<NonZeroScalar<C>, Output = C::AffinePoint>,
C::ElementSize: Add<U1>,
<C::ElementSize as Add>::Output: Add<U1>,
CompressedPoint<C>: From<C::AffinePoint>,
Expand All @@ -118,14 +124,13 @@ where
///
/// The `compress` flag requests point compression.
pub fn from_secret_key(secret_key: &SecretKey<C>, compress: bool) -> Result<Self, Error> {
let ct_option =
C::Scalar::from_secret_key(&secret_key).and_then(|s| C::AffinePoint::mul_base(&s));
let ct_option = C::Scalar::from_secret_key(&secret_key).and_then(NonZeroScalar::new);

if ct_option.is_none().into() {
return Err(Error);
}

let affine_point = ct_option.unwrap();
let affine_point = C::AffinePoint::generator() * ct_option.unwrap();

if compress {
Ok(PublicKey::Compressed(affine_point.into()))
Expand Down